<?php
/**
 * tIndexmenu Admin Plugin:   Indexmenu Component.
 *
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Samuele Tognini <samuele@netsons.org>
 * @author     Rene Hadler <rene.hadler@iteas.at>
 */

if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'admin.php');
require_once(DOKU_INC.'inc/HTTPClient.php');
require_once(DOKU_PLUGIN."tindexmenu/inc/pclzip.lib.php");
if(!defined('INDEXMENU_IMG_ABSDIR')) define('INDEXMENU_IMG_ABSDIR',DOKU_PLUGIN."tindexmenu/images");
define('INDEXMENU_ICOS','base,folder,folderopen,folderh,folderhopen,page,plus,minus,nolines_plus,nolines_minus,minusbottom,plusbottom,join,joinbottom,line,empty');

class admin_plugin_indexmenu extends DokuWiki_Admin_Plugin {
	var $req = 'fetch';
	var $repos = array (
			"url"  => array(DOKU_URL),
			"status" => array(""),
	);

	var $selected=-1;

	/**
	 * return some info
	 */
	function getInfo(){
		return array(
				'author' => 'Samuele Tognini mod. by Rene Hadler',
				'email'  => 'samuele@netsons.org, rene.hadler@iteas.at',
				'date'   => rtrim(io_readFile(DOKU_PLUGIN.'tindexmenu/VERSION.txt')),
				'name'   => 'tIndexmenu (admin plugin component)',
				'desc'   => 'tIndexmenu admin functions.',
				'url'    => 'http://wiki.splitbrain.org/plugin:tindexmenu',
		);
	}

	/**
	 * return sort order for position in admin menu
	 */
	function getMenuSort() {
		return 999;
	}

	/**
	 * handle user request
	 */
	function handle() {
		$url=$this->getConf('themes_url');
		if (empty($url)) {
			$this->repos['url'][]=$this->getLang('no_repos');
			$this->repos['status'][]="disabled";
			$this->repos['install'][]=-1;
		} else {
			$this->repos['url']= array_merge($this->repos['url'],explode(',',$url));
		}

		if (!isset($_REQUEST['req'])) return;   // first time - nothing to do
		$this->req=$_REQUEST['req'];

		if (is_numeric($_REQUEST['repo'])) $this->selected=$_REQUEST['repo'];
	}

	/**
	 * output appropriate html
	 */
	function html() {
		global $conf;
		ptln('<div id="config__manager">');
		ptln(' <h1>'.$this->getLang('menu').'</h1>');
		ptln($this->_donate());
		ptln(' <fieldset>');
		ptln('   <legend>'.$this->getLang('checkupdates').'</legend>');
		$this->_form_open("checkupdates");
		$this->_form_close('check');
		if ($this->req=='checkupdates') {
			$this->_checkupdates();
		}
		ptln(' </fieldset>');
		ptln(' <fieldset>');
		ptln('   <legend>Themes</legend>');
		ptln('   <table class="inline">');
		ptln('   <tr class="default"><td class="label" colspan="2">');
		ptln('   <span class="outkey">'.$this->getLang('infos').'</span>');
		ptln('   </td></tr>');
		$n=0;
		//cycles thru repositories urls
		foreach ($this->repos['url'] as $url) {
			ptln('    <tr class="search_hit"><td>');
			$legend=($n == 0) ? $conf['title'] : $this->repos['url'][$n];
			ptln('     <span><label><strong>'.$legend.'</strong></label></span>');
			ptln('    </td>');
			ptln('    <td class="value">');
			$this->_form_open("fetch",$n);
			$this->_form_close("fetch");
			ptln('    </td></tr>');
			//list requested theme
			if ($n==$this->selected) {
				ptln('    <tr class="default"><td colspan="2">');
				if ($this->req=='install') $this->install($this->selected,$_REQUEST['name']);
				if ($this->req=='upload' && $_REQUEST['name']) {
					$info="";
					if (isset($_REQUEST['author_info'])) {
						$obfuscate = array('@' => ' [at] ', '.' => ' [dot] ', '-' => ' [dash] ');
						$info .= "author=".strtr($_REQUEST['author_info'], $obfuscate)."\n";
					}
					if (isset($_REQUEST['url_info'])) $info .= "url=".$_REQUEST['url_info']."\n";
					if (isset($_REQUEST['author_info'])) $info .= "description=".$_REQUEST['author_info'];
					if (!$this->upload($_REQUEST['name'],$info)) msg($this->getLang('install_no'),-1);
				}
				if ($this->req=='delete' && $_REQUEST['name']) $this->_delete($_REQUEST['name']);
				ptln('    </td></tr><tr><td colspan="2">');
				$this->dolist($n);
				ptln('    </td></tr>');
			}
			$n++;
		}
		ptln('   </table>');
		ptln('  </fieldset>');
		ptln('</div>');
	}

	/**
	 * Connect to theme repository and list themes
	 *
	 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
	 * @author     Samuele Tognini <samuele@netsons.org>
	 */
	function dolist($n) {
		global $INFO;
		if ($n === false) return;
		//info.txt keys to parse
		$keys=array('author','url','description');
		$icos=explode(',',INDEXMENU_ICOS);
		$turl="";
		$info="";
		//get list
		$data=$this->_remotequery($this->repos['url'][$n]."/lib/plugins/tindexmenu/ajax.php?req=local");
		$data=explode(",",$data);
		//print themes
		for ($i=3;$i<count($data);$i++) {
			$theme=$data[$i];
			$turl=$data[1].$data[2]."/".$theme;
			ptln('     <em>'.$theme.'</em>');
			ptln('    <div class="indexmenu_list_themes">');
			ptln('     <div>');
			//print images
			foreach (array_slice($icos,0,8) as $ico) {
				$ext = explode(".", $theme);
				$ext=array_pop($ext);
				$ext=($ext == $theme) ? '.gif' : ".$ext";
				ptln('      <img src="'.$turl."/".$ico.$ext.'" title="'.$ico.'" alt="'.$ico.'" />');
			}
			ptln('      </div>');
			//get theme info.txt
			if ($info=$this->_remotequery($turl."/info.txt",false)) {
				foreach ($keys as $key) {
					if (!preg_match('/'.$key.'=(.*)/',$info,$out)) continue;
					ptln("       <div>");
					ptln("       <strong>".hsc($key).": </strong>".hsc($out[1]));
					ptln("       </div>");
				}
			}
			if ($n == 0) {
				$act="upload";
				if ($theme != "default" ) {
					$this->_form_open("delete",$n);
					ptln('       <input type="hidden" name="name" value="'.$theme.'" />');
					$this->_form_close("delete");
				}
			} else {
				$act="install";
				ptln('      <a href="'.$this->repos['url'][$n]."$repo/lib/plugins/tindexmenu/ajax.php?req=send&amp;t=".$theme.'">Download</a>');
			}
			$this->_form_open($act,$n);
			if ($n==0 && !is_file(INDEXMENU_IMG_ABSDIR."/".$theme."/info.txt")) {
				ptln('       <div><strong>author:</strong><input type="text" name="author_info" value="'.$INFO["userinfo"]["name"].hsc(" <".$INFO["userinfo"]["mail"].">").'" size="50" maxlength="100" /><br />');
				ptln('       <strong>url:</strong><input type="text" name="url_info" value="'.$this->repos['url'][$n].'" size="50" maxlength="200" /><br />');
				ptln('       <strong>description:</strong><input type="text" name="description_info" value="" size="50" maxlength="200" /></div>');
			}
			ptln('       <input type="hidden" name="name" value="'.$theme.'" />');
			$this->_form_close($act);
			ptln('     <br /><br /></div>');
		}
	}

	/**
	 * Download and install themes
	 *
	 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
	 * @author     Samuele Tognini <samuele@netsons.org>
	 */
	function install ($n,$name) {
		$repo=$this->repos['url'][$n];
		if (!isset($name)) return false;
		$return=true;
		if (!$absdir=$this->checktmpsubdir()) return;
		$tmp=$absdir."/tmp";

		//send theme list request
		if (!$zipfile=io_download($repo."/lib/plugins/tindexmenu/ajax.php?req=send&t=".$name,"$tmp/",true)) {
			msg($this->getLang('down_err').": $name",-1);
			$return=false;
		} else {
			//create zip
			$zip=new PclZip("$tmp/$zipfile");
			$regexp="/^".$name."\/(info.txt)|(style.css)|(".str_replace(",","|",INDEXMENU_ICOS).")\.(gif|png|jpg)$/i";
			$status=$zip->extract(PCLZIP_OPT_PATH,$absdir."/",PCLZIP_OPT_BY_PREG,$regexp);
			//error
			if ($status == 0) {
				msg($this->getLang('zip_err')." $tmp/$zipfile: ".$zip->errorName(true),-1);
				$return=false;
			} else {
				msg("<strong>$name</strong> ".$this->getLang('install_ok'),1);
			}
		}
		//clean tmp
		$this->_rm_dir($tmp);
		return $return;
	}


	/**
	 * Remove a directory
	 *
	 */
	function _rm_dir($path) {
		if (!is_string($path) || $path == "") return false;

		if (is_dir($path)) {
			if (!$dh = @opendir($path)) return false;

			while ($f = readdir($dh)) {
				if ($f == '..' || $f == '.') continue;
				$this->_rm_dir("$path/$f");
			}

			closedir($dh);
			return @rmdir($path);
		} else {
			return @unlink($path);
		}

		return false;
	}

	/**
	 * Retrive and create themes tmp directory
	 *
	 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
	 * @author     Samuele Tognini <samuele@netsons.org>
	 */
	function checktmpsubdir () {
		$tmp=INDEXMENU_IMG_ABSDIR."/tmp";
		if (!io_mkdir_p($tmp)) {
			msg($this->getLang('dir_err').": $tmp",-1);
			return false;
		}
		return INDEXMENU_IMG_ABSDIR;
	}


	/**
	 * Upload a theme into my site
	 *
	 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
	 * @author     Samuele Tognini <samuele@netsons.org>
	 */
	function upload($theme,$info) {
		$return=true;
		$host='samuele.netsons.org';
		$path='/dokuwiki/lib/plugins/tindexmenu/upload/index.php';
		//TODO: merge zip creation with that in ajax.php (create a class?)
		if (!$absdir=$this->checktmpsubdir()) return false;
		$tmp=$absdir."/tmp";
		$zipfile="$theme.zip";
		$filelist="$absdir/$theme";
		//create info
		if (!empty($info)) {
			io_savefile("$tmp/$theme/info.txt",$info);
			$filelist .= ",$tmp/$theme";
		}
		//create zip
		$zip=new PclZip("$tmp/$zipfile");
		$status=$zip->create($filelist,PCLZIP_OPT_REMOVE_ALL_PATH);
		if ($status == 0) {
			//error
			msg($this->getLang('zip_err').": ".$zip->errorName(true),-1);
			$return=false;
		} else {
			//prepare POST headers.
			$boundary = "---------------------------".uniqid("");
			$data=join("", file("$tmp/$zipfile"));
			$header="POST $path HTTP/1.0\r\n";
			$header.= "Host: $host\r\n";
			$header.= "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1) Gecko/20061024 Iceweasel/2.0 (Debian-2.0+dfsg-1)\r\n";
			$header.= "Content-type: multipart/form-data, boundary=$boundary\r\n";
			$body="--".$boundary."\r\n";
			$body.= "Content-Disposition: form-data; name=\"userfile\"; filename=\"$zipfile\"\r\n";
			$body.= "Content-Type: application/x-zip-compressed\r\n\r\n";
			$body.=$data."\r\n";
			$body.= "--".$boundary."\r\n";
			$body.= "Content-Disposition: form-data; name=\"upload\"\r\n\r\n";
			$body.= "Upload\r\n";
			$body.="--".$boundary."--\r\n";
			$header.= "Content-Length: ".strlen($body)."\r\n\r\n";

			//connect and send zip
			if ($fp = fsockopen($host, 80)) {
				fwrite($fp,$header.$body);
				//reply
				$buf="";
				while (!feof($fp)) {
					$buf .= fgets($fp,3200);
				}
				fclose($fp);
				//parse reply
				if (preg_match("/<!--indexmenu-->(.*)<!--\/indexmenu-->/s",$buf,$match)) {
					$str=substr($match[1],4,7);
					switch ($str) {
						case "ERROR  ":
							$mesg_type=-1;
							break;
						case "SUCCESS":
							$mesg_type=1;
							break;
						default:
							$mesg_type=2;
					}
					msg($match[1],$mesg_type);
				} else {
					$return=false;
				}
			} else {
				$return=false;
			}
		}

		$this->_rm_dir($tmp);
		return $return;
	}

	/**
	 * Check for new messages from upstream
	 *
	 * @author Samuele Tognini <samuele@netsons.org>
	 */
	function _checkupdates() {
		// We dont have checks for updates yet
		;
	}


	/**
	 * Get url response and check it
	 *
	 * @author Samuele Tognini <samuele@netsons.org>
	 */
	function _remotequery($url,$tag=true) {
		require_once (DOKU_INC.'inc/HTTPClient.php');
		$http = new DokuHTTPClient();
		$http->timeout = 8;
		$data = $http->get($url);
		if ($tag) {
			if ($data===false) {
				msg($this->getLang('conn_err'),-1);
			} else {
				(substr($data,0,9)==="indexmenu") ? $data=substr($data,9): $data="";
			}
		}
		return $data;
	}


	/**
	 * Open an html form
	 *
	 * @author Samuele Tognini <samuele@netsons.org>
	 */
	function _form_open($act,$n=-1) {
		ptln('     <form action="'.wl($ID).'" method="post">');
		ptln('      <input type="hidden" name="do" value="admin" />');
		ptln('      <input type="hidden" name="page" value="'.$this->getPluginName().'" />');
		ptln('      <input type="hidden" name="req" value="'.$act.'" />');
		ptln('      <input type="hidden" name="repo" value="'.$n.'" />');
	}

	/**
	 * Close the html form
	 *
	 * @author Samuele Tognini <samuele@netsons.org>
	 */
	function _form_close($act) {
		ptln('      <input type="submit" name="btn" '.$this->repos['status'][$n].' value="'.$this->getLang($act).'" />');
		ptln('     </form>');
	}

	/**
	 * Remove an installed theme
	 *
	 * @author Samuele Tognini <samuele@netsons.org>
	 */
	function _delete($theme) {
		if ($theme=="default") return;
		if ($this->_rm_dir(INDEXMENU_IMG_ABSDIR."/".utf8_encodeFN(basename($theme)))) {
			msg($this->getLang('delete_ok').": $theme.",1);
		} else {
			msg($this->getLang('delete_no').": $theme.",-1);
		}
	}

	/**
	 * Print the donate button.
	 *
	 * @author Samuele Tognini <samuele@netsons.org>
	 */
	function _donate() {
		$out = "<fieldset>\n";
		$out .= '<p>'.$this->getLang('donation_text').'</p>';
		$out .= '<form action="https://www.paypal.com/cgi-bin/webscr" method="post">'."\n";
		$out .= '<input type="hidden" name="cmd" value="_s-xclick" />'."\n";
		$out .= '<input type="hidden" name="hosted_button_id" value="102873" />'."\n";
		$out .= '<input type="image" src="https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif" name="submit" alt="" />'."\n";
		$out .= '<img alt="" src="https://www.paypal.com/it_IT/i/scr/pixel.gif" width="1" height="1" />'."\n";
		$out .= "</form></fieldset>\n";
		return $out;
	}

}
