<?php
/**
 * Project:   BeFramed - simple site engine
 * File:      /admin/versions.apnl.php
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * @link http://www.jaud.be
 * @copyright 2025 becast.at
 * @author Bernhard Jaud <bernhard at becast dot at>
 * @package BeFramed core
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: 7fcb8f105d16b786834239396aefd13402f25a7b $
*/
If (!defined("in_BL_ADMIN")) {
    die("Dieses Script kann nicht ausserhalb des Frameworks laufen!");
} 
$addnav["right"]=FALSE;
$session->page_begin("Version", True);

$subnav_item="<a href=\"/management.html\">Verwaltung</a> &raquo; <a>Systemstatus</a>";

class versions_panel extends admin_module{

	function output(){
		global $module,$config,$db,$panel,$admin,$module,$root,$core;
			$files=$this->listdir($root.'/modules');
			foreach($files as $file){
				$file_object = array(
				'name' => substr($file,strlen($root.'/modules/')),
				'size' => $this->byteConvert(filesize($file)),
				'time' => date("d.m.Y, H:i:s", filemtime($file)));
				$dir_objects[] = $file_object;
			}
			
			$url="http://www.astat.org/versions.php";
			$file = @fopen($url,"r");
			if($file != false){
				$data = @fread($file,"4048");
				$xml=new xml();
				$out = $xml->parse($data, NULL);
				$i=0;
				$max=count($out["mod"]);
				while($i<=$max){
					$versions[$i]["name"]=$out["mod"][$i];
					$versions[$i]["ver"]=$out["ver"][$i];
					$i++;
				}
				$vers=$core->ver_major.".".$core->ver_minor.".".$core->ver_rev;
				$panel->title="Moduleversionen";
				$panel->content.="<table width=\"80%\" cellspacing=\"2\">
								<tr>	
								    <th align=\"center\">Modul</th>
								    <th align=\"center\">Version</th>
								    <th align=\"center\">Update</th>
								</tr>";
				if($out["relase"]["version"]>$vers){
					$panel->content.="<tr><td colspan=\"3\">Diese Version ist nicht mehr aktuell.<br />Besuche <a href=\"http://www.astat.org\">die Projektseite</a> f&uuml;r ein Update</td></tr>";
				}else{
				
					foreach($module as $mod){
						$panel->content.="<tr>
						<td align=\"center\">".$mod["name"]."</td>
						<td align=\"center\">".$mod["ver"]."</td>";
							foreach($versions as $v){
								if($v["name"]==$mod["name"]){
									if($mod["ver"]<$v["ver"]){
										$panel->content.="<td align=\"center\"><a href=\"http://projectx.becast.at/get_file.php?file=".urlencode($v["name"])."\">Neue Version verf&uuml;gbar!</a></td>";
									}elseif($mod["ver"]==$v["ver"]){
										$panel->content.="<td align=\"center\">Aktuell</td>";
									}else{
										$panel->content.="<td align=\"center\">Modified file?</td>";
									}
								}
							}
						$panel->content.="</tr>";
						
					}
					foreach($core->mod_ as $mod){
						$panel->content.="<tr>
						<td align=\"center\"><a href=\"".$mod["url"]."\">".$mod["name"]."<a></td>
						<td align=\"center\">".$mod["version"]."</td>";
						foreach($versions as $v){
								if($v["name"]==$mod["name"]){
									if($mod["version"]<$v["ver"]){
										$panel->content.="<td align=\"center\"><a href=\"http://projectx.becast.at/get_file.php?file=".urlencode($v["name"])."\">Neue Version verf&uuml;gbar!</a></td>";
									}elseif($mod["version"]==$v["ver"]){
										$panel->content.="<td align=\"center\">Aktuell</td>";
									}else{
										$panel->content.="<td align=\"center\">Modified file?</td>";
									}
								}
							}
						$panel->content.="</tr>";
					}
				}
				$panel->content.="</table><br />";
				$panel->parse_page();
			}else{
				$panel->title="Moduleversionen";
				$panel->content.="Die Versionpr&uuml;fung ist fehlgeschlagen.";
				$panel->content.="<table width=\"80%\" cellspacing=\"2\">
								<tr>	
								    <th align=\"center\">Modul</th>
								    <th align=\"center\">Version</th>
								</tr>";
				
				
					foreach($module as $mod){
						$panel->content.="<tr>
						<td align=\"center\">".$mod["name"]."</td>
						<td align=\"center\">".$mod["ver"]."</td>";
						$panel->content.="</tr>";
					}	
				$panel->content.="</table><br />";
				$panel->parse_page();
			}
			$panel->title="Datei Infos";
			$panel->content.="<table width=\"80%\" cellspacing=\"2\">
						<tr>
						<th align=\"center\">Datei</th>
						<th align=\"center\">Gr&ouml;&szlig;e</th>
						<th align=\"center\">zuletzt Ge&auml;ndert</th>
						</tr>";
			foreach($dir_objects as $files){
				$panel->content.="<tr>
				<td align=\"center\">".$files["name"]."</td>
				<td align=\"center\">".$files["size"]."</td>
				<td align=\"center\">".$files["time"]."</td>
				</tr>";
			}

			$panel->content.="</table>";
	}
	
	function byteConvert( $bytes ) {
   
		if ($bytes<=0)
		return '0 Byte';
		   
		$convention=1000; //[1000->10^x|1024->2^x]
		$s=array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB');
		$e=floor(log($bytes,$convention));
		return round($bytes/pow($convention,$e),2).' '.$s[$e];
	}

	function listdir($start_dir='.') {

	  $files = array();
	  if (is_dir($start_dir)) {
	    $fh = opendir($start_dir);
	    while (($file = readdir($fh)) !== false) {
	      # loop through the files, skipping . and .., and recursing if necessary
	      if (strcmp($file, '.')==0 || strcmp($file, '..')==0) continue;
	      $filepath = $start_dir . '/' . $file;
	      if ( is_dir($filepath) )
		$files = array_merge($files, $this->listdir($filepath));
	      else
		array_push($files, $filepath);
	    }
	    closedir($fh);
	  } else {
	    # false if the function was called with an invalid non-directory argument
	    $files = false;
	  }
 	 return $files;
	}
	
}

class Xml {

	/**
	 * Xml parser container.
	 *
	 * @var resource parser
	 */
	var $parser;

	/**
	 * Parse result.
	 *
	 * @var array pOut
	 */
	var $pOut = array();

	/**
	 * Contain the overlap tag temporarily .
	 *
	 * @var array track
	 */
	var $track = array();

	/**
	 * Current tag level.
	 *
	 * @var string tmpLevel
	 */
	var $tmpLevel = '';

	/**
	 * Attribut of current tag.
	 *
	 * @var array tmpAttrLevel
	 */
	var $tmpAttrLevel = array();

	/**
	 * Write result.
	 *
	 * @var string wOut
	 */
	var $wOut = '';




	/**
	 * parse
	 * Set the parser Xml and theses options.
	 * Xml file could be a string, a file, or curl.
	 * When the source is loaded, we run the parse.
	 * After, we clean all the memory and variables,
	 * and return the result in an array.
	 *
	 * @access  public
	 * @param   src       string    Source
	 * @param   typeof    string    Source type : NULL, FILE, CURL.
	 * @param   encoding  string    Encoding type.
	 * @return  array
	 */
	function parse ( $src, $typeof = 'FILE', $encoding = 'UTF-8' ) {

		// ini;
		// (re)set array;
		$this->pOut = array();
		$this->parser = xml_parser_create();

		xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
		xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $encoding);

		xml_set_object($this->parser, $this);
		xml_set_element_handler($this->parser, 'startHandler', 'endHandler');
		xml_set_character_data_handler($this->parser, 'contentHandler');

		if(empty($src))
			trigger_error('Source could not be empty.', E_USER_ERROR);     

		// format source;
		if($typeof == NULL)
			$data = $src;
		elseif($typeof == 'FILE') {
			$fop  = fopen($src, 'r');
			$data = null;
			while(!feof($fop))
				$data .= fread($fop, 1024);
			fclose($fop);
		}
		elseif($typeof == 'CURL') {
			$curl = curl_init();
			curl_setopt($curl, CURLOPT_URL, $src);
			curl_setopt($curl, CURLOPT_HEADER, 0);
			$data = curl_exec($curl);
			curl_close($curl);
		}
		else
			return trigger_error('Xml parser need data.', E_USER_ERROR);

		// parse $data;
		$parse = xml_parse($this->parser, $data);
		if(!$parse)
			return trigger_error('XML Error : %s at line %d.', E_USER_ERROR,
				array(xml_error_string(xml_get_error_code($this->parser)),
					xml_get_current_line_number($this->parser)));

		// destroy parser;
		xml_parser_free($this->parser);

		// unset extra vars;
		unset($data,
			  $this->track,
			  $this->tmpLevel);

		// remove global tag and return the result;
		return $this->pOut[0][key($this->pOut[0])];
	}



	/**
	 * startHandler
	 * Manage the open tag, and these attributs by callback.
	 * The purpose is to create a pointer : {{int ptr}}.
	 * If the pointer exists, we have a multi-tag situation.
	 * Tag name  is stocked like : '<tag>'
	 * Attributs is stocked like : '<tag>-ATTR'
	 * Return true but built $this->pOut.
	 *
	 * @access  private
	 * @param   parser  resource    Parser resource.
	 * @param   tag     string      Tag name.
	 * @param   attr    array       Attribut.
	 * @return  bool
	 */
	function startHandler ( $parser, $tag, $attr ) {

		// built $this->track;
		$this->track[] = $tag;
		// place pointer to the end;
		end($this->track);
		// temp level;
		$this->tmpLevel = key($this->track);

		// built attrLevel into $this->tmpAttrLevel
		if(isset($this->tmpAttrLevel[$this->tmpLevel]['attrLevel']))
			$this->tmpAttrLevel[$this->tmpLevel]['attrLevel']++;

		// built $this->pOut;
		if(!isset($this->pOut[key($this->track)][$tag])) {
			$this->pOut[key($this->track)][$tag] = '{{'.key($this->track).'}}';

			if(!isset($this->tmpAttrLevel[$this->tmpLevel]['attrLevel']))
				$this->tmpAttrLevel[$this->tmpLevel]['attrLevel'] = 0;				
		}

		// built attributs;
		if(!empty($attr)) {

			$this->tmpAttrLevel[$this->tmpLevel][] = $this->tmpAttrLevel[$this->tmpLevel]['attrLevel'];
			end($this->tmpAttrLevel[$this->tmpLevel]);

			// it's the first attribut;
			if(!isset($this->pOut[key($this->track)][$tag.'-ATTR']))
					$this->pOut[key($this->track)][$tag.'-ATTR'] = $attr;

			// or it's not the first;
			else {
				// so it's the second;
				if(!prev($this->tmpAttrLevel[$this->tmpLevel])) {
					$this->pOut[key($this->track)][$tag.'-ATTR'] = array(
						current($this->tmpAttrLevel[$this->tmpLevel]) => $this->pOut[key($this->track)][$tag.'-ATTR'],
						next($this->tmpAttrLevel[$this->tmpLevel])    => $attr
					);
				}
				// or one other;
				else
					$this->pOut[key($this->track)][$tag.'-ATTR'][$this->tmpAttrLevel[$this->tmpLevel]['attrLevel']] = $attr;
			}
		}

		return true;
	}



	/**
	 * contentHandler
	 * Detect the pointer, or the multi-tag by callback.
	 * If we have a pointer, the method replaces this pointer by the content.
	 * Else we have a multi-tag, the method add a element to this array.
	 * Return true but built $this->pOut.
	 *
	 * @access  private
	 * @param   parser          resource    Parser resource.
	 * @param   contentHandler  string      Tag content.
	 * @return  bool
	 */
	function contentHandler ( $parser, $contentHandler ) {

		// remove all spaces;
		if(!preg_match('#^\\\\s*$#', $contentHandler)) {

			// $contentHandler is a string;
			if(is_string($this->pOut[key($this->track)][current($this->track)])) {

				// then $contentHandler is a pointer : {{int ptr}}     case 1;
				if(preg_match('#{{([0-9]+)}}#', $this->pOut[key($this->track)][current($this->track)]))
					$this->pOut[key($this->track)][current($this->track)] = $contentHandler;

				// or then $contentHandler is a multi-tag content      case 2;
				else {
					$this->pOut[key($this->track)][current($this->track)] = array(
						0 => $this->pOut[key($this->track)][current($this->track)],
						1 => $contentHandler
					);
				}
			}
			// or $contentHandler is an array;
			else {

				// then $contentHandler is the multi-tag array         case 1;
				if(isset($this->pOut[key($this->track)][current($this->track)][0]))
					$this->pOut[key($this->track)][current($this->track)][] = $contentHandler;

				// or then $contentHandler is a node-tag               case 2;
				else
					$this->pOut[key($this->track)][current($this->track)] = array(
						0 => $this->pOut[key($this->track)][current($this->track)],
						1 => $contentHandler
					);
			}

		}

		return true;
	}



	/**
	 * endHandler
	 * Detect the last pointer by callback.
	 * Move the last tags block up.
	 * And reset some temp variables.
	 * Return true but built $this->pOut.
	 *
	 * @access  private
	 * @param   parser  resource    Parser resource.
	 * @param   tag     string      Tag name.
	 * @return  bool
	 */
	function endHandler ( $parser, $tag ) {

		// if level--;
		if(key($this->track) == $this->tmpLevel-1) {
			// search up tag;
			// use array_keys if an empty tag exists (taking the last tag);

			// if it's a normal framaset;
			$keyBack = array_keys($this->pOut[key($this->track)], '{{'.key($this->track).'}}');
			$count = count($keyBack);

			if($count != 0) {
				$keyBack = $keyBack[$count-1];
				// move this level up;
				$this->pOut[key($this->track)][$keyBack] = $this->pOut[key($this->track)+1];
			}

			// if we have a multi-tag framaset ($count == 0);
			else {
				// if place is set;
				if(isset($this->pOut[key($this->track)][current($this->track)][0])) {

					// if it's a string, we built an array;
					if(is_string($this->pOut[key($this->track)][current($this->track)]))
						$this->pOut[key($this->track)][current($this->track)] = array(
							0 => $this->pOut[key($this->track)][current($this->track)],
							1 => $this->pOut[key($this->track)+1]
						);

					// else add an index into the array;
					else
						$this->pOut[key($this->track)][current($this->track)][] = $this->pOut[key($this->track)+1];
				}
				// else set the place;
				else
					$this->pOut[key($this->track)][current($this->track)] = array(
						0 => $this->pOut[key($this->track)][current($this->track)],
						1 => $this->pOut[key($this->track)+1]
					);
			}

			// kick $this->pOut level out;
			array_pop($this->pOut);
			end($this->pOut);
		}

		// re-temp level;
		$this->tmpLevel = key($this->track);

		while(isset($this->tmpAttrLevel[$this->tmpLevel+1]))
			array_pop($this->tmpAttrLevel);

		// kick $this->track level out;
		array_pop($this->track);
		end($this->track);

		return true;
	}
}

?>
