plugins:np_linktoskinfiles:np_linktoskinfiles_code

NP_LinkToSkinFiles.phpのソースコード

<?php 
class NP_LinkToSkinFiles extends NucleusPlugin { 
	function getName() { return 'NP_LinkToSkinFiles'; }
	function getMinNucleusVersion() { return 250; }
	function getAuthor()  { return 'Katsumi + yama.kyms + yu'; }
	function getVersion() { return '0.2.4'; }
	function getURL() {return 'http://japan.nucleuscms.org/wiki/plugins:np_linktoskinfiles';}
	function getDescription() { return $this->getName().' plugin'; } 
	function supportsFeature($what) { return (int)($what=='SqlTablePrefix'); }
	function getEventList() { return array('AdminPrePageHead','AdminPrePageFoot'); }
	function install(){
		$this->createOption('linkstyle','Link style?','select','iframe','Normal|normal|New Window|newwindow|Inline Frame|iframe');
		$this->createOption('iframeheight','Hight of iframe?','text','650','datatype=numeric');
		$this->createOption('inctags','Check these tags:','textarea',"include\n"."parsedinclude\n"."phpinclude\n"."skinfile\n");
		$this->createOption('textext','Text file extensions:','textarea',"htm html txt\n"."js css inc\n"."php cgi pl xbmp\n");
	}
	var $ob_ok=false;
	function event_AdminPrePageHead(&$data){
		if ($data['action']!='skinedittype' && $data['action']!='skinupdate') return;
		$this->ob_ok=ob_start();// Begin the collection of html.
	}
	var $texts='';
	function event_AdminPrePageFoot(){
		global $CONF,$manager,$DIR_SKINS;
		if (!$this->ob_ok) return;
		$html=ob_get_contents();// End the collection of html.
		ob_end_clean();
		$skinid=intRequestVar('skinid');// $skinid is clean; it's integer.
		$type=requestVar('type');
		// Create the select form HTML
		$descs=array('index'=>_SKIN_PART_MAIN,
			'item'=>_SKIN_PART_ITEM,
			'archivelist'=>_SKIN_PART_ALIST,
			'archive'=>_SKIN_PART_ARCHIVE,
			'search'=>_SKIN_PART_SEARCH,
			'error'=>_SKIN_PART_ERROR,
			'member'=>_SKIN_PART_MEMBER,
			'imagepopup'=>_SKIN_PART_POPUP);
		$res=sql_query('SELECT stype FROM '.sql_table('skin')." WHERE sdesc=$skinid");
		$select='</form>
<form method="GET" action="">
<input type="hidden" name="skinid" value="'.$skinid.'"/>
<input type="hidden" name="type" value="'.htmlspecialchars($type).'"/>
<input type="hidden" name="action" value="skinedittype"/>
<input type="submit" style="display:none;" id="np_linktoskinfiles_select" />
<select name="type" onchange="if (this.value!=\'\') document.getElementById(\'np_linktoskinfiles_select\').click();">
<option value="">Go to</option>';
		while ($row=mysql_fetch_row($res)) {
			if (!($desc=@$descs[$row[0]])) $desc=$row[0];
			$select.='
<option value="'.htmlspecialchars($row[0]).'">'.htmlspecialchars($desc).'</option>';
		}
		$select.="</select><br /><br />\n";
		$html=str_replace(_SKIN_ALLOWEDVARS,$select._SKIN_ALLOWEDVARS,$html);
		// Prepare JavaScript
		switch($this->getOption('linkstyle')){
		case 'newwindow':
			$jscode=' onclick="window.open(this.href);return false;"';
			break;
		case 'iframe':
			$jscode=' onclick="document.getElementById(\'NP_LinkToSkinFiles_iframe\').style.display=\'block\';'.
				'document.getElementById(\'NP_LinkToSkinFiles_iframe\').scrolling=((this.href+\'\').indexOf(\'?action=editfile\')>0)?\'no\':\'auto\';'.
				'document.getElementById(\'NP_LinkToSkinFiles_iframe\').src=this.href;'.
				'return false;"';
			break;
		default:
			$jscode='';
		}
		// Inport the skin data
		$text=quickQuery('SELECT scontent as result FROM '.sql_table('skin')." WHERE sdesc=$skinid AND stype='".addslashes($type)."' LIMIT 1");// Obtain the content of skin.
		$sdir=quickQuery('SELECT sdincpref as result FROM '.sql_table('skin_desc')." WHERE sdnumber=$skinid AND sdincmode='skindir' LIMIT 1");// The skindir
		// Create the regular expression to search tags for including files.
		$textext=trim($this->getOption('textext'));
		$textext=preg_replace('/[\s]+/','|',$textext);
		$search=trim($this->getOption('inctags'));
		$search=preg_replace('/[\s]+/','|',$search);
		$search=preg_replace('/[^0-9a-zA-Z_|]+/','',$search);
		$search='/<%('.$search.')\(([^\)]+)\.('.$textext.')\)%>/';
		// Search the include tags
		$this->texts=$text;
		if (($text && $sdir && preg_match_all($search,$text,$matches,PREG_SET_ORDER))) {
			// Create the tree of *.inc files
			$inctree=array();
			foreach($matches as $match) $inctree[$match[2].'.'.$match[3]]=$this->_seekIncFile($match[2].'.'.$match[3],$DIR_SKINS.$sdir,$search);
			// Create the links
			$skinfiles=$CONF['PluginURL'].'skinfiles/';
			$links='Edit by <a href="'.htmlspecialchars($skinfiles.'?dir='.$sdir).'"[[[__jscode__]]]>SkinFiles</a>:<br />';
			$first=true;
			foreach($inctree as $filename=>$childes) {
				if (!$first) $links.=', ';
				$first=false;
				$this->_createLinks($links,$filename,$childes,$sdir,$skinfiles);
			}
			$links=str_replace('[[[__jscode__]]]',$jscode,$links);// $jscode is clean; it does not contain the outside data.
			$links.=' [<a href="'.htmlspecialchars("?action=skinedittype&skinid=$skinid&type=$type").'">Refresh</a>]';
			$links.="<br /><br />\n";
		} else $links='';
 
		/* Insert template links */
		$tsearch='{<%([0-9a-zA-Z_-]+)\(([0-9a-zA-Z/_-]+)[^\)]*\)%>}';
		if (($this->texts && preg_match_all($tsearch,$this->texts,$tmatches,PREG_SET_ORDER))) {
			$tlist = array();
 
			$tdnames='';
			foreach($tmatches as $tmatch) {
				$tdname = $tmatch[2];
				/*if (strpos($tdname, '/') === false) continue;*/ 
				$tdnames.=($tdnames?',"':'"').addslashes($tdname).'"'; // $tdnames is clean
			}
			if (strlen($tdnames)){
				$query = 'SELECT tdnumber, tdname FROM '.sql_table('template_desc').' WHERE tdname in ('.$tdnames.')';
				$res = sql_query($query);
				while ($row=mysql_fetch_assoc($res)) {
					$url = 'index.php?action=templateedit&templateid=' . (int)$row['tdnumber']; //make edit link
					//$url = $manager->addTicketToUrl($url);
					$tlist[ $row['tdname'] ] = $url;
				}
			}
 
			if (count($tlist)) {
				if (count($tlist)==1) $links.='Template used:';
				else $links.='Templates used:';
				$links.='</a><br />';
				foreach ($tlist as $name => $url) {// $jscode is clean; it does not contain the outside data.
					$links.='<a href="'.htmlspecialchars($url).'"'.$jscode.'>'.htmlspecialchars($name).'</a>, ';
				}
				$links = substr($links, 0, -2);
				$links.= ' [<a href="'.htmlspecialchars("?action=skinedittype&skinid=$skinid&type=$type").'">Refresh</a>]';
				$links.= "<br /><br />\n";
			}
		}
 
		if (!strlen($links)) {
			echo $html;
			return;
		}
		$links.='<iframe width="100%" height="'.(int)$this->getOption('iframeheight').'" id="NP_LinkToSkinFiles_iframe" style="display:none;" onload="NP_LinkToSkinFiles_hideMenu(this);"></iframe>';
		$links.="\n";
		echo str_replace(_SKIN_ALLOWEDVARS,$links._SKIN_ALLOWEDVARS,$html);
?><script type="text/javascript">
/*<![CDATA[*/
function NP_LinkToSkinFiles_hideMenu(obj){
  var docobj=obj.contentWindow.document;
  if (!docobj.getElementById('quickmenu')) return;
  docobj.getElementById('quickmenu').style.display='none';
  docobj.getElementById('content').style.marginLeft='0px';
  docobj.getElementsByTagName('h1')[0].style.display='none';
  divobj = docobj.getElementsByTagName('div');
  for (i=0; i<divobj.length; i++) {
    if (divobj[i].attributes[0].value=='loginname') {
      divobj[i].style.display='none';
      break;
    }
  }
}
/*]]>*/
</script><?php
	}
	// Sub routines follow.  Currently, these are used for making links of *.inc files.
	function _seekIncFile($filename,$skindir,$search){
		if (!file_exists($skindir.$filename)) return false;
		if (strpos(realpath($skindir.$filename),realpath($skindir))) return false;
		if (!($fhandle=@fopen($skindir.$filename,'r'))) return false;
		$result=array();
		$text='';
		while ( !feof($fhandle) ) {
			$line = fgets($fhandle, 4096);
			$text.=$line;
			if ( !preg_match_all($search,$line,$incfiles,PREG_SET_ORDER) ) continue;
			foreach($incfiles as $match){
				$result[$match[2].'.'.$match[3]]=$this->_seekIncFile($match[2].'.'.$match[3],$skindir,$search);
			}
		}
		fclose($fhandle);
		$this->texts.=$text;
		return count($result)?$result:false;
	}
	function _createLinks(&$links,$filename,$childes,$sdir,$skinfiles){
		// $links will be directry echoed, so be careful and think about XSS.
		global $DIR_SKINS,$manager,$CONF;
		if (file_exists($DIR_SKINS.$sdir.$filename)) {
			// Link to SkinFiles
			$url=$skinfiles.'?action=editfile';
			$url.='&file='.$sdir.$filename;
			$url=$manager->addTicketToUrl($url);
		} else {
			// Link to action of this plugin
			$url=$CONF['ActionURL'];
			$url.='?action=plugin&name=LinkToSkinFiles&type=createfile';
			$url.='&file='.$sdir.$filename;
		}
		$links.='<a href="'.htmlspecialchars($url).'"'.
			'[[[__jscode__]]]>'.htmlspecialchars($filename).'</a>';
		if ($childes) {
			$links.='(';
			$first=true;
			foreach($childes as $childname=>$grandchildes) {
				if (!$first) $links.=', ';
				$first=false;
				$this->_createLinks($links,$childname,$grandchildes,$sdir,$skinfiles);
			}
			$links.=')';
		}
	}
	// doAction is used for creating form to confirm making a new file.
	function doAction($type){
		global $manager,$member,$DIR_SKINS,$CONF;
		// Allow only super-admin to do this.
		if (!($member->isLoggedIn() && $member->isAdmin())) return _ERROR_DISALLOWED;
		switch($type=strtolower($type)){
		case 'createfile':
			$skinfiles=$CONF['PluginURL'].'skinfiles/';
			if (!($file=getVar('file'))) return _ERROR_DISALLOWED;
			$fullpath=$DIR_SKINS.$file;
			// Check if the fullpath is within DIR_SKINS
			$tempdir=$fullpath;
			while(preg_match('![^\/][\/]!',$tempdir)){
				if (file_exists($tempdir=dirname($tempdir))) break;
			}
			if (strpos(realpath($tempdir),realpath($DIR_SKINS))!==0) return _ERROR_DISALLOWED;
			$url=$skinfiles.'?action=editfile';
			$url.='&file='.htmlspecialchars($file,ENT_QUOTES);
			$url=$manager->addTicketToUrl($url);
			if (file_exists($fullpath)) {
				// Redirect to SkinFiles if the file exists.
				redirect($url);
				exit;
			}
			if ($manager->checkTicket() && requestVar('ticket')==postVar('ticket')) {
				// POST mode is used to create the file really.
				// Create a file and redirect to SkinFiles
				if (postVar('createdir')=='yes') {
					// Create the directory
					$count=0;
					while(!file_exists(dirname($fullpath))) {
						if (10==$count++) return 'Cannot create the directory.';
						$tempdir=dirname($fullpath);
						while(preg_match('![^\/][\/]!',$tempdir)){
							if (realpath(dirname($tempdir))) break;
							$tempdir=dirname($tempdir);
						}
						@mkdir($tempdir,0755);
					}
				}
				if (!@fclose(@fopen($fullpath,'x'))) return 'Cannot create the file (maybe, the directory does not exist).';
				redirect($url);
				exit;
			}
			// There is no valid ticket. Let's show the form button to create file.
			header('Content-type: text/html; charset='._CHARSET);
?><html><head><title>Create a skin file</title>
<meta http-equiv="Content-Type" content="text/html; charset=<?php echo _CHARSET;?>" />
</head><body><form method="POST" action="">
Create the file, "<span style="color:red;"><?php echo htmlspecialchars($file); ?></span>" in skins directory?<br /><br />
<?php $manager->addTicketHidden(); ?>
<?php if (!file_exists(dirname($fullpath))) echo '<input type="checkbox" name="createdir" value="yes" />Check if create a new directory.<br /><br />'; ?>
<input type="submit" value="<?php echo _YES; ?>" />
<input type="button" value="<?php echo _NO; ?>" onclick="
document.location='<?php echo htmlspecialchars($skinfiles.'?dir='.dirname($file).'/',ENT_QUOTES); ?>';
return false;"/>
</form></body></html><?php
			exit;
		default:
			return _ERROR_DISALLOWED;
		}
	}
}
?>
 
plugins/np_linktoskinfiles/np_linktoskinfiles_code.txt · 最終更新: 2011/03/23 21:28 (外部編集)