<?php
/*
* Copyright Renaud GOMBERT, 2007 - rgombert@essentiel.net - http://zite.prositif.com
* Copyright (c) 2009, ZiteCMS - Le Centre Informatique asbl - Michael Barchy
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Neither the name of the University of California, Berkeley nor the
*       names of its contributors may be used to endorse or promote products
*       derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
error_reporting(E_ERROR | E_PARSE);
ini_set('display_errors', 1);
ini_set('arg_separator.output', '&amp;');
set_magic_quotes_runtime(0);
define('ZITEVER', '0.6.9');
class zite {
	var $zpath, $ipath, $cpath, $fpath, $config, $args, $struct, $messages, $syspages, $truepage, $parents, $base, $content, $rewrite, $current_file, $plugins_objects, $menu_show = array(), $collapse = array();
	function zite($caller, $cs = false) {
		$this->collapse = & $this->menu_show;
		$this->plugins('before', 'init');
		$this->zpath = dirname(__FILE__);
		$this->ipath = dirname($caller);
		$this->cpath = $this->ipath . '/zdata';
		$this->fpath = $this->ipath . '/zfiles';
		$this->config = parse_ini_file($this->cpath . '/config.ini', true);
		$this->config_def = @parse_ini_file($this->cpath . '/config_def.ini', true);
		$upload_max_filesize = intval(ini_get('upload_max_filesize')) * 1024 * 1024;
		if ($this->config['upload_maxweight'] == '0' || floatval($this->config['upload_maxweight']) > $upload_max_filesize) {
			$this->config['upload_maxweight'] = $upload_max_filesize;
		}
		$args = explode($this->config['argsep'], $_GET['z']);
		foreach($args as $arg) {
			$parts = split(':', $arg);
			if (count($parts) > 1) {
				$args[@array_shift($parts) ] = @join(':', $parts);
			}
		}
		$this->args = $args;
		$this->struct = (array)unserialize(@file_get_contents($this->cpath . '/structure.dta'));
		$this->content = $this->parents = array();
		$this->messages = $this->truepage = false;
		$this->rewrite = true;
		$this->base = $this->config['files_index'] . '?z=';
		$this->syspages = array('login', 'logout', 'admin', 'ini_editor', 'config_editor', 'page_editor', 'source_editor', 'delete', 'files');
		session_start();
		if ($cs || !array_key_exists('zite_admin', $_SESSION) || $_SESSION['zite_id'] != $this->config['site_id']) {
			session_unset();
			$_SESSION['zite_admin'] = 0;
			$_SESSION['zite_id'] = $this->config['site_id'];
		}
		if (array_key_exists('perma', $_GET)) {
			$z = - 1;
			$p = $_GET['perma'];
			foreach($this->struct as $k => $v) if ($v[0] == $p) $z = $k;
			$_GET['z'] = $this->args[0] = $z;
		}
		$page = strlen($_GET['z']) ? $this->args[0] : 1;
		if (in_array($page, $this->syspages)) {
			$this->truepage = $this->args[1];
		} else {
			$this->truepage = $page;
		}
    $deco = $this->config['folder_deco'];
    if ($deco == '') $deco = 'deco/';
    if(is_file($deco.'zite.css')) {
      $this->config['files_zite'] = $deco.'zite.css';
    } else {
      $this->config['files_zite'] = 'zite.css';
    }
		$this->plugins('after', 'init');
	}
	function newpage($p, $title = false, $content = false, $f = false, $php = false) {
		$dta = @$this->struct[$p];
		$level = @$dta[2];
		if (@$f == '_Zite') $level = 1;
		if (@$dta[0] == '_Zite' || @$this->struct[$p - 1][0] == '_Zite') $level = 2;
		$max = count($this->struct);
		if (!$f) $f = md5(uniqid(rand()));
		$np = $max + 1;
		$np2 = $p + 1;
		if (!$title) $title = $this->get_message('page_default_title') . " [$np]";
		$t = 1;
		if ($php) $t = 2;
		$this->struct[$np] = array($f, $title, $level, $t, 0, 0);
		for ($j = $np;$j > $np2;$j--) $this->swap($j);
		if (!$content) $content = $this->get_message('page_default_content');
		$this->writefile($this->cpath . '/' . $f . '.txt', $content);
		return $j;
	}
	function builder() {
		$this->plugins('before', 'build');
		if ($this->rewrite == true) {
			$v = explode('.', basename($_SERVER['REQUEST_URI']));
			if (count($v) == 2) {
				if (!array_key_exists('z', $_GET)) {
					$_GET['perma'] = $v[0];
				}
			} else {
				$_GET['z'] = $this->args[0] = 1;
			}
		}
		if (array_key_exists('perma', $_GET)) {
			$z = - 1;
			$p = $_GET['perma'];
			foreach($this->struct as $k => $v) if ($v[0] == $p) $z = $k;
			$_GET['z'] = $this->args[0] = $z;
		}
		$page = strlen($_GET['z']) ? $this->args[0] : 1;
		if (in_array($page, $this->syspages)) {
			$pagesys = "page_$page";
			$this->content['main'] = $this->$pagesys();
		} else {
			if ($this->config['site_status'] == 'on' | $_SESSION['zite_admin'] > 0) {
				if (array_key_exists($page, $this->struct) && ($this->struct[$page][4] || $_SESSION['zite_admin'] > 0)) {
					$this->truepage = $page;
					$infos = $this->struct[$page];
					$this->content['menu_title'] = $infos[1];
					$this->truepage = $page;
					$tmp = $this->get_content($infos[0], $infos[3] == 2);
					$this->content['main'] = $tmp ? $tmp : $this->get_message('errorNOFILE');
				} else {
					$this->content['main'] = $this->get_message('error404');
					header("HTTP/1.0 404 Not Found");
				}
			} else {
				$this->content['main'] = $this->get_message('errorCLOSED');
			}
		}
		$this->navbuilder();
		if ($_SESSION['zite_admin']) $this->prepend($this->adminbar());
		$this->plugins('after', 'build');
	}
	function navbuilder() {
		$this->menu_show = array();
		$n = $this->truepage ? $this->truepage : 0;
		$isadmin = (int)$_SESSION['zite_admin'] > 0;
		$rewrite = $this->rewrite && !$isadmin;
		$base = $this->rewrite ? ($isadmin ? $this->base . $this->get_data('navig_admin') : '') : $this->base;
    $max = count($this->struct);    
    
    if ($n != 0) {
      // root children
      $l = $this->struct[$n][2];
      for($i = $n-1;$i > 0;$i--) {
        $s = $this->struct[$i];
        if ($s[2] == 1) break;
        if ($s[2] <= $this->struct[$n][2] && $s[2] <= $l) {
          array_push($this->menu_show, $i);
          $l = $s[2];
        }
      }    
      $l = $this->struct[$n][2];    
      for($i = $n;$i <= $max;$i++) {
        $s = $this->struct[$i];
        if ($s[2] == 1) break;
        if ($s[2] <= $this->struct[$n][2] && $s[2] <= $l) {
          array_push($this->menu_show, $i);
          $l = $s[2];
        }
      }
      // this children
      $l = 0;
      for($i = $n+1;$i <= $max;$i++) {
        $s = $this->struct[$i];
        if ($s[2] <= $this->struct[$n][2]) break;
        if ($l == 0) $l = $s[2];
        if ($s[2] == $l) array_push($this->menu_show, $i);
      }      
    }
    // roots
    for($i = 1;$i <= $max;$i++) {
      $s = $this->struct[$i];
      if ($s[2] == 1) array_push($this->menu_show, $i);
    }
		$nav_pre = $this->plugins('before', 'menu');
		$nav_pre.= '<ul class="zul">';
		$nav = '';
		foreach($this->struct as $pageid => $s) {
			if (($s[4] || $isadmin) && in_array($pageid, $this->menu_show)) {
				$style1 = 'zli zli' . $s[2];
				if ($pageid == $n) $style1.= ' zon zon' . $s[2];
				$style2 = 'za za' . $s[2];
				if ($pageid == $n) $style2.= ' zaon zaon' . $s[2];
				$nav.= '<li class="' . $style1 . '"><a class="' . $style2 . '" href="' . $base . ($rewrite ? $s[0] . '.html' : $pageid . '&perma=' . $s[0]) . '">' . $s[1] . '</a></li>';
			}
		}
		$this->content['menu'] = $nav_pre . $nav . '</ul>' . $this->plugins('after', 'menu');
		asort($this->parents);
	}
	function output() {
		$this->plugins('before', 'output');
		$this->content['main'] = $this->content['pre_main'] . $this->content['main'] . $this->content['post_main'];
		ob_start();
		$zite = & $this;
		require ($this->ipath . '/' . $this->config['files_template']);
		$this->plugins('after', 'output');
		return ob_get_clean();
	}
	function adminbar() {
		$admin = $_SESSION['zite_admin'] == 2;
		$out = $this->plugins('before', 'adminbar');
		$out.= $admin ? $this->get_message('admin_admintitle') : $this->get_message('admin_usertitle');
		$out.= ' : <a href="' . $this->base . 'admin">' . $this->get_message('edit_admin') . '</a>';
		if ($this->truepage && ($admin || !$this->struct[$this->truepage][5])) $out.= ' <a href="' . $this->base . 'page_editor|' . $this->truepage . '">' . $this->get_message('edit') . '</a>';
		if ($this->truepage && $admin) $out.= ' <a href="' . $this->base . 'source_editor|' . $this->truepage . '">' . $this->get_message('edit_source') . '</a>';
		if ($admin) {
			$out.= ' <a href="' . $this->base . 'config_editor">' . $this->get_message('edit_config') . '</a>';
		}
		$out.= ' <a href="' . $this->base . 'files">' . $this->get_message('files_admin') . '</a>';
		$out.= ' <a href="' . $this->base . 'logout" onclick="return confirm(\'' . $this->get_message('logout') . '?\');">' . $this->get_message('logout') . '</a>';
		$out.= $this->plugins('before', 'adminbar');
		return '<div id="zadmin">' . $out . '</div>';
	}
	function get_content($key, $php = false) {
		$result = '';
		$key = preg_replace('/[^A-z0-9_-]/', '', $key);
		$file = $this->cpath . "/$key.txt";
		$this->current_file = $file;
		$result.= $this->plugins('before', 'content');
		if (!file_exists($this->current_file)) {
			return false;
		}
		if ($php) {
			ob_start();
			$zite = & $this;
			include ($this->current_file);
			$result.= ob_get_clean();
		} else {
			$result.= file_get_contents($this->current_file);
		}
		$result.= $this->plugins('after', 'content');
		$this->current_file = '';
		return $result;
	}
	function get_message($key) {
		$result = '';
		$result.= $this->plugins('before', 'message');
		if (!$this->messages) $this->messages = @parse_ini_file($this->cpath . '/messages.ini', true);
		$result.= array_key_exists($key, $this->messages) ? $this->messages[$key] : "[$key*]";
		$result.= $this->plugins('after', 'message');
		return $result;
	}
	function get_data($key) {
		$result = '';
		$result.= $this->plugins('before', 'data');
		$result.= array_key_exists($key, $this->config) ? $this->config[$key] : "[NO KEY FOR $key]";
		$result.= $this->plugins('after', 'data');
		return $result;
	}
	function prepend($text) {
		$this->content['pre_main'].= $text;
	}
	function append($text) {
		$this->content['post_main'] = $text . $this->content['post_main'];
	}
	function page_login() {
		$login_form = '';
		$login_form.= $this->plugins('before', 'login');
		if (strcmp($_POST['id'], $this->config['login_username']) == 0 && strcmp(md5($_POST['pass']), $this->config['login_userpass']) == 0) {
			$_SESSION['zite_admin'] = 1;
			header('Location: ' . $this->base);
			exit;
		} elseif (strcmp($_POST['id'], $this->config['login_adminname']) == 0 && strcmp(md5($_POST['pass']), $this->config['login_adminpass']) == 0) {
			$_SESSION['zite_admin'] = 2;
			header('Location: ' . $this->base . 'admin');
			exit;
		}
		$login_form2 = $this->get_content('_Login');
		if (!$login_form2) $login_form2 = $this->get_message('login_form');
		$login_form.= $login_form2;
		$login_form.= $this->plugins('after', 'login');
		return $login_form;
	}
	function page_logout() {
		$this->plugins('before', 'logout');
		session_unset();
		header('Location: ' . $this->base . '1');
		$this->plugins('after', 'logout');
		exit;
	}
	function page_admin() {
		$this->plugins('before', 'admin');
		if ($_SESSION['zite_admin']) {
			$max = count($this->struct);
			$admin = $_SESSION['zite_admin'] == 2;
			$tools = $admin || $this->get_data('rights_structure') == 'on';
			if ($tools) {
				$c = $this->args[1];
				$p = (int)$this->args[2];
				if ($p > 0 && $p <= $max) {
					$change = true;
					$dta = & $this->struct[$p];
					if (@$dta[2] > 1) {
						$p2 = $p;
						while ($p2 > 0) {
							$p2--;
							$dta2 = @$this->struct[$p2];
							if (intval(@$dta2[2]) < @$dta[2]) {
								$parent_dta = $dta2;
								break;
							}
						}
					}
					$power = $admin || $dta[5] == 0;
					if ($c == 'l' && $dta[2] > 1) { // left
						if ($dta[2] > 1 && @$dta[0] != '_Zite' && @$this->struct[$p - 1][0] != '_Zite') $dta[2]--;
					} elseif ($c == 'r') { // right
						if (@$dta[0] != '_Zite' && @$this->struct[$p - 1][0] != '_Zite') $dta[2]++;
					} elseif ($c == 'u') { // up
						if ($p > 1 && @$dta[0] != '_Zite' && @$this->struct[$p - 1][0] != '_Zite') $this->swap($p);
					} elseif ($c == 'd') { // down
						if ($p < $max && @$dta[0] != '_Zite' && @$this->struct[$p + 1][0] != '_Zite') $this->swap($p + 1);
					} elseif ($c == 'v' && $admin) { // Verrou
						$dta[5] = $dta[5] ? 0 : 1;
						if (@$dta[0] == '_Zite' || @$parent_dta[0] == '_Zite') $dta[5] = 1;
					} elseif ($c == 'n') { // Newpage
						sleep(1);
						$this->newpage($p);
						$max++; // ???
						
					} elseif ($c == 's' && $power) { // Status
						$dta[4] = $dta[4] == 1 ? 0 : 1;
						if (@$dta[0] == '_Zite' || @$parent_dta[0] == '_Zite') $dta[4] = 0;
					} else {
						$change = false;
					}
					if ($change) {
						$this->writedata($this->cpath . '/structure.dta', $this->struct);
						$this->plugins('after', 'admin');
						exit(header('Location: ' . $this->base . 'admin|refresh:' . md5(uniqid(rand()))));
					}
				}
			}
			$i = 0;
      $deco = $this->config['folder_deco'];
      if ($deco == '') $deco = 'deco/';
			foreach($this->struct as $k => $v) {
				$i++;
        $tool1 = '';
        $tool2 = '';
				if ($tools) {
					$tb = ' <a href="' . $this->base . 'admin|';
					$r = '';
					$tool1.= $v[2] > 1 ? $tb . 'l|' . $k . $r . '"><img src="'.$deco.'l1.png" /></a>' : ' <img src="'.$deco.'l0.png" />';
					$tool1.= $tb . 'n|' . $k . $r . '" title="' . $this->get_message('page_default_title') . '"><img src="'.$deco.'a.png" /></a>';
					$tool1.= $tb . 'r|' . $k . $r . '"><img src="'.$deco.'r1.png" /></a>';
					$tool2 = '';
					$tool2.= $k > 1 ? $tb . 'u|' . $k . $r . '"><img src="'.$deco.'u1.png" /></a>' : '<img src="'.$deco.'u0.png" />';
					$tool2.= $k < $max ? $tb . 'd|' . $k . $r . '"><img src="'.$deco.'d1.png" /></a>' : ' <img src="'.$deco.'d0.png" />';
					if ($admin) {
						$tool2.= $v[5] ? $tb . 'v|' . $k . $r . '"><img src="'.$deco.'k1.png" /></a>' : $tb . 'v|' . $k . '"><img src="'.$deco.'k0.png" /></a>';
					} else {
						$tool2.= $v[5] ? ' <img src="'.$deco.'k1.png" />' : ' <img src="'.$deco.'k0.png" />';
					}
					if ($admin || $v[5] == 0) {
						$tool2.= $v[4] ? $tb . 's|' . $k . $r . '"><img src="'.$deco.'s1.png" /></a>' : $tb . 's|' . $k . $r . '"><img src="'.$deco.'s0.png" /></a>';
						$tool2.= $max > 1 ? ' <a href="' . $this->base . 'delete|' . $k . $r . '" title="' . strip_tags($this->get_message('delpage')) . '"><img src="'.$deco.'e1.png" /></a>' : ' <img src="'.$deco.'e0.png" />';
					} else {
						$tool2.= $v[4] ? ' <img src="'.$deco.'s1.png" />' : ' <img src="'.$deco.'s0.png" />';
						$tool2.= ' <img src="'.$deco.'e0.png" />';
					}
				}
				$plugins = split(',', $this->config['plugins']);
				foreach($plugins as $plugin) {
					if ($this->plugins_objects[$plugin]->tool) {
					  $tp = $this->truepage;
						$this->truepage = $k;
						$zite = & $this;
						$tool = $this->plugins_objects[$plugin]->on_tool($zite);
						$ico = 'zplugins/' . $plugin . '/' . $tool . '.png';
						if (!is_file($this->ipath . '/' . $ico)) $ico = $deco.'s1.png';
						$tool2.= ' <a href="' . $this->base . 'admin|tool:' . $plugin . '|' . $k . $r . '" title="' . $plugin . ' : ' . $zite->get_message('plugin_' . $plugin . '_' . $tool) . '"><img src="' . $ico . '" /></a> ';
            $this->truepage = $tp;
					}
				}                                
				$nav.= '<tr bgcolor="#' . ($i % 2 ? 'DDDDDD' : 'EEEEEE') . '"><td align="right" width="30" style="white-space: nowrap;">' . $i . '&nbsp;</td><td width="60" style="white-space: nowrap;">' . $tool1 . '</td><td>' . str_repeat('&nbsp; ', 3 * --$v[2]);
				$nav.= ($v[5] && $_SESSION['zite_admin'] == 1) ? $v[1] : ($_SESSION['zite_admin'] == 2 ? '<a href="' . $this->base . 'source_editor|' . $k . '" title="' . strip_tags($this->get_message('edit_source')) . '"><img src="'.$deco.'c.png" /></a> ' : '') . '<a href="' . $this->base . 'page_editor|' . $k . '" title="' . strip_tags($this->get_message('edit')) . '">' . $v[1] . '</a>';
				$nav.= ' <a href="?perma=' . $v[0] . '" title="' . strip_tags($this->get_message('view_page')) . '" style="font-size:75%;color:#AAA">' . $v[0] . '</a>';
				$nav.= '</td><td style="white-space: nowrap;" align="right">' . $tool2 . '</td></tr>';
			}
			$this->plugins('after', 'admin');
			return '<p><table align="center" border="0" cellspacing="0" cellpadding="2" class="ztable"><tr><td colspan="4" align="center">' . $this->get_message('edit_structure') . '</td></tr>' . $nav . '</table></p>';
		} else {
			$this->plugins('after', 'admin');
			return $this->get_message('not_allowed');
		}
	}
	function page_delete() {
		$result = '';
		$result.= $this->plugins('before', 'delete');
		if ($_SESSION['zite_admin']) {
			$max = count($this->struct);
			$p = (int)$this->args[1];
			$dta = @$this->struct[$p];
			if (@$dta[2] > 1) {
				$p2 = $p;
				while ($p2 > 0) {
					$p2--;
					$dta2 = @$this->struct[$p2];
					if (intval(@$dta2[2]) < @$dta[2]) {
						$parent_dta = $dta2;
						break;
					}
				}
			}
			if ($p > 0 && $p <= $max && $max > 1 && @$dta[0] != '_Zite' && @$parent_dta[0] != '_Zite') {
				if ($this->struct[$p][5] == 0 || $_SESSION['zite_admin'] == 2) {
					if ($this->args[2] == 'ok') {
						unlink($this->cpath . '/' . $this->struct[$p][0] . '.txt');
						for ($i = $p;$i < $max;$i++) $this->struct[$i] = $this->struct[$i + 1];
						unset($this->struct[$max]);
						$this->writedata($this->cpath . '/structure.dta', $this->struct);
						header('Location: ' . $this->base . 'admin');
					} else {
						$r = '';
						$result.= $this->get_message('delpage_confirm') . '<p class="zalert"><a href="' . $this->base . 'delete|' . $p . '|ok' . $r . '">' . $this->get_message('delpage') . ' : <strong>' . $this->struct[$p][1] . '</strong></a></p>';
					}
				} else {
					$result.= $this->get_message('not_allowed');
				}
			} else {
				$result.= $this->get_message('not_possible');
			}
		} else {
			$result.= $this->get_message('not_allowed');
		}
		$result.= $this->plugins('after', 'delete');
		return $result;
	}
	function page_page_editor() {
		$pageid = $this->args[1];
		if ($_SESSION['zite_admin'] == 2 || ($_SESSION['zite_admin'] == 1 && $this->struct[$pageid][5] == 0)) {
			$r_in = array('<?', '<?php', '?>', '<?=');
			$r_out = array('<!--?', '<!--?php', '?-->', '<!--?=');
			$this->current_file = $this->cpath . '/' . $this->struct[$pageid][0] . '.txt';
			if (file_exists($this->current_file)) {
				$this->truepage = $pageid;
				$edfile = $this->zpath . '/' . $this->get_data('editor') . '.php';
				$out = '';
				$out_pre = $this->plugins('before', 'edit');
				if ($_POST['save'] == 1) {
					$this->struct[$pageid][1] = $this->utf8tohtml(stripslashes($_POST['title']));
					$this->struct[$pageid][3] = (int)$_POST['code'];
					$source = str_replace($r_out, $r_in, stripslashes($_POST['source']));
					$rslt = $this->writedata($this->cpath . '/' . 'structure.dta', $this->struct) && $this->writefile($this->current_file, $source);
					$out = $rslt ? $this->get_message('done_ok') : $this->get_message('done_failed');
					$out = '<p class="zalert">' . $out . ' - <a href="' . $this->base . $pageid . '">' . $this->get_message('view_page') . '</a>' . '</p>';
				}
				$out.= '<form action="' . $this->base . 'page_editor|' . $pageid . '"  method="post">';
				$out.= $this->get_message('edit_title') . ': <input name="title" size="35" type="text" value="' . $this->struct[$pageid][1] . '" />';
				if ($_SESSION['zite_admin'] == 2) {
					$out.= '<input name="code" type="radio" value="1" ' . ($this->struct[$pageid][3] == '1' ? 'checked="checked" />' : ' />') . 'HTML';
					$out.= '<input name="code" type="radio" value="2" ' . ($this->struct[$pageid][3] == '2' ? 'checked="checked" />' : ' />') . 'PHP';
				} else {
					$out.= '<input name="code" type="hidden" value="' . $this->struct[$pageid][3] . '" />';
				}
				$out.= ' <input name="save" type="hidden" value="1" /><input type="submit" name="Submit" value="' . $this->get_message('submit') . '" /><br />';
				$out.= $out_pre;
				// Chargement de l'editeur
				$content = file_get_contents($this->current_file);
				if (file_exists($edfile)) {
					// Editeur externe
					ob_start();
					include ($edfile);
					$out.= ob_get_clean();
				} else {
					// Editeur brut
					$out.= '<textarea style="width:100%;height:500px;" name="source" id="source">' . $content . '</textarea>';
				}
				$out.= '</form>';
				$out.= $this->plugins('after', 'edit');
				return $out;
			} else {
				return $this->get_message('errorNOFILE');
			}
		} else {
			return $this->get_message('not_allowed');
		}
	}
	function page_source_editor() {
		if ($_SESSION['zite_admin'] == 2) {
			$pageid = $this->args[1];
			if (substr($pageid, 0, 5) == 'files' && array_key_exists($pageid, $this->config)) {
				$filename = $this->get_data($pageid);
        $path = $this->ipath;
        if (strrchr($filename,'.') == '.ini') $path = $this->cpath;
				$file = $path . '/' . $filename;
			} elseif ((int)$pageid && (int)$pageid <= count($this->struct)) {
				$filename = $this->struct[(int)$pageid][1];
				$file = $this->cpath . '/' . $this->struct[(int)$pageid][0] . '.txt';
				$this->truepage = (int)$pageid;
			}
			$this->current_file = $file;
			$out = $this->plugins('before', 'source');
			$file = $this->current_file;
			if (file_exists($file)) {
				if (array_key_exists('source', $_POST)) {
					if ($this->truepage == $pageid) {
						$oldname = $this->struct[(int)$pageid][0];
						$newname = preg_replace('/[^A-z0-9_-]/', '', $_POST['permaname']);
						if ($newname != $oldname) {
							$newfile = $this->cpath . '/' . $newname . '.txt';;
							if (file_exists($newfile)) {
								$out.= '<p class="zalert">' . $this->get_message('permaname_duplicate') . ' (' . $newname . ')' . '</p>';
							} else {
								$oldfile = $this->cpath . '/' . $oldname . '.txt';
								$file = $newfile;
								unlink($oldfile);
								$this->struct[(int)$pageid][0] = $newname;
								$this->writedata($this->cpath . '/structure.dta', $this->struct);
							}
						}
					}
					$tmp = $this->writefile($file, stripslashes($_POST['source'])) ? $this->get_message('done_ok') : $this->get_message('done_failed');
					$out.= '<p class="zalert">' . $tmp . ' : ' . $filename . '</p>';
				}
				$out.= '<form action="' . $this->base . 'source_editor|' . $pageid . '"  method="post"><div id="zadmin">';
				$out.= $this->get_message('edit_file') . ' : ' . $filename;
				$out.= ' <input type="submit" name="Submit" value="' . $this->get_message('submit') . '" /></div>';
				if ($this->truepage == $pageid) {
					$out.= $this->get_message('edit_permaname') . '<input type="text" size="35" name="permaname" value="' . $this->struct[(int)$pageid][0] . '" /><br />';
				}
				$out.= '<textarea style="width:100%;height:500px;" name="source">' . htmlentities(file_get_contents($file)) . '</textarea>';
				$out.= '</form>';
				$out.= $this->plugins('after', 'source');
				return $out;
			} else {
				return $this->get_message('errorNOFILE');
			}
		} else {
			return $this->get_message('not_allowed');
		}
	}
	function page_ini_editor($f = false, $config = false) {
		if ($_SESSION['zite_admin'] == 2) {
			$out = '';
			if (!$f) $f = $this->cpath . '/' . $this->config[$this->args[1]];
			if ($config) $f = $this->cpath . '/config.ini';
			$this->current_file = $f;
			$out.= $this->plugins('before', 'ini');
			$f = $this->current_file;
			if (file_exists($f)) {
				if ($config) {
					ksort($this->config);
					if (array_key_exists('save', $_POST)) { // Enregistrement
						foreach($_POST as $k => $v) {
							if (substr($k, 0, 1) == '_') {
								$k2 = substr($k, 1, strlen($k) - 1);
								if (substr($k2, -4) == 'pass') {
									if (strlen($v)) $this->config[$k2] = md5($v);
								} else {
									$this->config[$k2] = $this->utf8tohtml(stripslashes($v));
								}
							}
							if ($k == 'new_ini_key' && $v != '') $this->config[$v] = '';
						}
						$out.= '<p class="zalert">' . ($this->writeconfig($f, $this->config) ? $this->get_message('done_ok') : $this->get_message('done_failed')) . '</p>';
					}
					$ini = $this->config;
				} else {
					$ini = parse_ini_file($f, true);
					ksort($ini);
					if (array_key_exists('save', $_POST)) { // Enregistrement
						foreach($_POST as $k => $v) {
							if (substr($k, 0, 1) == '_') {
								$k2 = substr($k, 1, strlen($k) - 1);
								$ini[$k2] = stripslashes($v);
							}
							if ($k == 'new_ini_key' && $v != '') $ini[$v] = '';
						}
						$out.= '<p class="zalert">' . ($this->writeconfig($f, $ini) ? $this->get_message('done_ok') : $this->get_message('done_failed')) . '</p>';
					}
				}
				$msg = $this->get_message('edit_source');
				$out.= '<form action="' . $this->base . ($config ? 'config' : 'ini') . '_editor' . $this->config['argsep'] . $this->args[1] . '" method="post">';
				$out.= '<table style="width:100%">';
				if ($config) {
					foreach($ini as $k => $v) {
						$k2 = $this->get_message('config_' . $k);
						if (substr($k2, 0, 1) == '[') $k2 = $k;
						if (substr($k, 0, 6) == 'files_') $out.= '<tr bgcolor="#' . (++$i % 2 ? 'DDDDDD' : 'EEEEEE') . '"><td width="25%"><strong>' . $k2 . ':</strong></td><td><a href="' . $this->base . (strrchr($v, '.') == '.ini' ? 'ini' : 'source') . '_editor|' . $k . '">' . $msg . '</a></td></tr>';
					}
				}
				foreach($ini as $k => $v) {
					$d = explode($this->config['argsep'], @$this->config_def[$k . '_def']);
					$t = @$d[0];
					if ($t == '') $t = 'text';
					$l = split(';', @$d[1]);
					$m = '';
          $out2 = '';
          if ($t == 'readonly') {
            $t = 'hidden';
            $m = '/>' . $v . '<input type="hidden"';
          }
					if ($t == 'checkbox') {
						$t = 'hidden';
						$m = '/><input type="checkbox" onclick="if (this.checked) { this.form.elements[\'_' . $k . '\'].value = \'' . @$l[0] . '\'; } else { this.form.elements[\'_' . $k . '\'].value = \'' . @$l[1] . '\'; }" ';
						if ($v == @$l[0]) $m.= 'checked';
					}
          if ($t == 'list') {
            $l0 = $l[0];
            if(substr($l0, 0, 1) == '@') {
              $l0 = substr($l0, 1);
              $l = @$this->$l0();
              if (!is_array($l)) $l = array();
            }
            $out2 .= '<select name="_' . $k . '">';
            $default = @array_shift($l);
            $out2 .= '<option value="' . $default . '"' . (($v == $default)?' SELECTED':'') . '>' . $this->get_message('default_'.$k) . '</option>';
            foreach($l as $e => $n) {
              $out2 .= '<option value="' . $e . '"' . (($v == $e)?' SELECTED':'') . '">' . $n . '</option>';
            }
            $out2 .= '</select>';
            $t = '';
          }
					$k2 = $this->get_message('config_' . $k);
					if (substr($k2, 0, 1) == '[') $k2 = $k;
					$out.= '<tr bgcolor="#' . (++$i % 2 ? 'DDDDDD' : 'EEEEEE') . '"><td width="25%">' . $k2 . ':</td><td>';
          if ($t != '') $out.= '<input name="_' . $k . '" type="' . $t . '" value="' . (substr($k, -4) == 'pass' && $config ? '' : $v) . '" class="z' . $t . '" ' . $m . ' />';
          $out.= $out2 . '</td></tr>';
				}
				$out.= '<tr bgcolor="#' . (++$i % 2 ? 'DDDDDD' : 'EEEEEE') . '"><td width="25%">' . $this->get_message('new_ini_key') . '</td><td><input name="new_ini_key" type="text" value="" class="ztext" /></td></tr>';
				$out.= '<tr bgcolor="#' . (++$i % 2 ? 'DDDDDD' : 'EEEEEE') . '"><td colspan="2" align="center"><input type="submit" name="Submit" value="' . $this->get_message('submit') . '" /></td></tr>';
				$out.= '</table>';
				$out.= '<input type="hidden" name="save" value="1" />';
				$out.= '</form>';
				$out.= $this->plugins('after', 'ini');
				return $out;
			} else {
				$this->plugins('after', 'ini');
				return $this->get_message('errorNOFILE');
			}
		} else {
			$this->plugins('after', 'ini');
			return $this->get_message('not_allowed');
		}
	}
	function page_config_editor() {
		return $this->page_ini_editor(false, true);
	}
	function page_files() {
		if ($_SESSION['zite_admin']) {
			$file = $this->cpath . '/files.dta';
			$f = (array)unserialize(@file_get_contents($file));
			// creation d'un array vide (fichier .dta inexistant ou corrompu)
			if (!is_array($f)) $f = array();
			$max = count($f);
			// actions et sauvegarde
			if ($_POST['save'] == 1) {
				$id = (int)$_POST['pos'];
				if (array_key_exists($id, $f) && $id > 0) {
					// effacement
					if ($_POST['delete'] == 1) {
						unlink($this->fpath . '/' . $f[$id][1] . '.' . $f[$id][2]);
						unset($f[$id]);
						$ext = false;
					} else {
						$ext = $this->getfile($id, $f[$id][2]);
						$f[$id][0] = htmlentities(stripslashes($_POST['name']));
					}
				} else {
					foreach($f as $v) if ($v[1] >= $id) $id = $v[1] + 1;
					// initialisation du numero de fichier ? 1
					if ($id == 0) $id = 1;
					$ext = $this->getfile($id);
					if ($ext) {
						$f[$id][0] = htmlentities(stripslashes($_POST['name']));
						$f[$id][1] = $id;
					}
				}
				if ($ext) {
					$f[$id][2] = $ext;
					$f[$id][3] = $ext == 'gif' || $ext == 'jpg' || $ext == 'png';
				}
				// reformation de la liste et enregistrement
				foreach($f as $v) $f2[$v[1]] = $v;
				$this->writedata($file, $f2);
			}
			// formulaire
			$pos = (int)$this->args[1];
			if (array_key_exists($pos, $f)) {
				$name = $f[$pos][0];
				$del = true;
				$ext = $f[$pos][2];
			}
      $deco = $this->config['folder_deco'];
      if ($deco == '') $deco = 'deco/';      
			$out = $this->plugins('before', 'files');
			$out.= '<form method="post" onsubmit="if(this.delete.checked) return confirm(\'' . strip_tags($this->get_message('files_delwarning')) . '\');" action="' . $this->base . 'files" enctype="multipart/form-data"><table class="ztable">';
			$out.= '<tr><td colspan="2">' . ($pos ? '<a href="' . $this->base . 'files" title="' . strip_tags($this->get_message('files_new')) . '"><img src="'.$deco.'a.png" /></a> ' : '') . '<strong>' . $this->get_message($pos ? 'files_edit' : 'files_new') . ' ' . strtoupper($ext) . ' : </strong>' . $name . '</td></tr>';
			$out.= '<tr><td>' . $this->get_message('files_filename') . ' :</td><td><input name="name" type="text" id="name" value="' . $name . '" style="width:100%;" /></td></tr>';
			$out.= '<tr><td>' . $this->get_message('files_choose') . ' :</td><td><input type="file" name="file" /></td></tr>';
			if ($del) $out.= '<tr><td>' . $this->get_message('files_delete') . ' :</td><td><input name="delete" type="checkbox" value="1" /> ' . $this->get_message('files_delwarning') . '</td></tr>';
			$out.= '<tr><td>&nbsp;</td><td><input type="submit" name="Submit" value="' . $this->get_message('submit') . '" /><input name="save" type="hidden" value="1" /><input name="pos" type="hidden" value="' . $pos . '" /></td></tr></table></form>';
			usort($f, create_function('$a, $b', 'return strcmp($a[0], $b[0]);'));
			$out.= '<table class="ztable">';
			$out.= '<tr bgcolor="#CCCCCC"><td>&nbsp;</td><td>' . $this->get_message('files_filename') . '</td><td>' . $this->get_message('files_filetype') . '</td></tr>';
			foreach($f as $v) {
				if ($v != '') $out.= '<tr bgcolor="#' . (++$i % 2 ? 'DDDDDD' : 'EEEEEE') . '"><td width="20" align="center"><a href="' . $this->base . 'files|' . $v[1] . '"><img src="'.$deco.'c.png" title="' . strip_tags($this->get_message('files_edit')) . '" /></a></td><td><a href="zfiles/' . $v[1] . '.' . $v[2] . '" title="' . strip_tags($this->get_message('files_open')) . '" target="_blank">' . $v[0] . '</a></td><td width="100" align="center">' . strtoupper($v[2]) . '</tr>';
			}
			$out.= '</table>';
			$out.= $this->plugins('after', 'files');
			return $out;
		} else {
			$this->plugins('after', 'files');
			return $this->get_message('not_allowed');
		}
	}
	function plugins($event = false, $key = false) {
		if (!$event || !$key) return;
		$result = '';
		$page = strlen($_GET['z']) ? $this->args[0] : 1;
		$plugins = split(',', $this->config['plugins']);
		foreach($plugins as $plugin) {
			if (!is_object(@$this->plugins_objects[$plugin])) {
				$pfile = $this->ipath . '/zplugins/' . $plugin . '/' . $plugin . '.php';
				if (is_file($pfile)) {
					include_once ($pfile);
					$pclass = 'zite_plugin_' . $plugin;
					$zite = & $this;
					$this->plugins_objects[$plugin] = new $pclass($zite);
				}
			}
			if ($this->plugins_objects[$plugin]->page == $page || $this->plugins_objects[$plugin]->page == '') {
				$pfunc = $event . '_' . $key;
				if (method_exists($this->plugins_objects[$plugin], $pfunc)) {
					$zite = & $this;
					$result.= $this->plugins_objects[$plugin]->$pfunc($zite);
				}
			}
		}
		return $result;
	}
	function getfile($id, $oldext = false) {
		$handle = $_FILES['file'];
		if (empty($handle) || $handle['error'] == 4) {
			return false;
		} else {
			if ($handle['error'] != 0) {
				$this->prepend('<div class="zalert">' . $this->get_message('done_failed') . '</div>');
				return false;
			}
			$ext = pathinfo($handle['name']);
			$ext = $ext['extension'];
			if (in_array($ext, explode(',', $this->get_data('upload_types')))) {
				$temp_file = $handle['tmp_name'];
				if (@move_uploaded_file($temp_file, $this->fpath . '/' . $id . '.' . $ext)) {
					if ($oldext != $ext) unlink($this->fpath . '/' . $id . '.' . $oldext);
					$this->prepend('<div class="zalert">' . $this->get_message('done_ok') . '</div>');
					return $ext;
				} else {
					$this->prepend('<div class="zalert">' . $this->get_message('done_failed') . '</div>');
					return false;
				}
			}
			$this->prepend('<div class="zalert">' . $this->get_message('done_failed') . '</div>');
			return false;
		}
	}
	function writefile($file, $content) {
		$this->plugins('before', 'writefile');
		$r = false;
		$h = fopen($file, 'w');
		if ($h) {
			$r = fwrite($h, $content);
			fclose($h);
		}
		$this->plugins('after', 'writefile');
		return $r;
	}
	function writeconfig($file, $content) {
		$this->plugins('before', 'writeconfig');
		foreach($content as $k => $v) $dta.= "\n$k = \"" . str_replace('"', '&quot;', $v) . '"';
		$r = $this->writefile($file, $dta);
		$this->plugins('after', 'writeconfig');
		return $r;
	}
	function writedata($file, $content) {
		$this->plugins('before', 'writedata');
		$r = $this->writefile($file, serialize($content));
		$this->plugins('after', 'writedata');
		return $r;
	}
	function swap($p) {
		$t = $this->struct[$p - 1];
		$this->struct[$p - 1] = $this->struct[$p];
		$this->struct[$p] = $t;
	}
  function list_styles() {
    $styles = array("style.css");
    $d = 'templates/';
    $dir = @opendir($d);
    while ($f = @readdir($dir)) {
      if (is_dir($d.$f) && substr($f, 0, 1) != '.' && is_file($d.$f.'/'.$f.'.css')) $styles[$d.$f.'/'.$f.'.css'] = $f;
    }
    return $styles;
  }
  function list_themes() {
    $themes = array("deco/");
    $d = 'deco/';
    $dir = @opendir($d);
    while ($f = @readdir($dir)) {
      if (is_dir($d.$f) && substr($f, 0, 1) != '.') $themes[$d.$f.'/'] = $f;
    }
    return $themes;
  }
  function utf8tohtml($utf8, $encodeTags) {
    $result = '';
    for ($i = 0; $i < strlen($utf8); $i++) {
        $char = $utf8[$i];
        $ascii = ord($char);
        if ($ascii < 128) {
            // one-byte character
            $result .= ($encodeTags) ? htmlentities($char) : $char;
        } else if ($ascii < 192) {
            // non-utf8 character or not a start byte
        } else if ($ascii < 224) {
            // two-byte character
            $result .= htmlentities(substr($utf8, $i, 2), ENT_QUOTES, 'UTF-8');
            $i++;
        } else if ($ascii < 240) {
            // three-byte character
            $ascii1 = ord($utf8[$i+1]);
            $ascii2 = ord($utf8[$i+2]);
            $unicode = (15 & $ascii) * 4096 +
                       (63 & $ascii1) * 64 +
                       (63 & $ascii2);
            $result .= "&#$unicode;";
            $i += 2;
        } else if ($ascii < 248) {
            // four-byte character
            $ascii1 = ord($utf8[$i+1]);
            $ascii2 = ord($utf8[$i+2]);
            $ascii3 = ord($utf8[$i+3]);
            $unicode = (15 & $ascii) * 262144 +
                       (63 & $ascii1) * 4096 +
                       (63 & $ascii2) * 64 +
                       (63 & $ascii3);
            $result .= "&#$unicode;";
            $i += 3;
        }
    }
    return $result;
  }  
}
?> 
