<?php
/**
 * Project:   BeCast WebEngine - simple site engine
 * File:      /inc/core.class.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.becast.at
 * @copyright 2009 - 2025 becast.at
 * @author Bernhard Jaud <bernhard at becast dot at>
 * @package BcWe core
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
 * @version $Id: dc6f9fe72943f565d4ccf10a5e96d7f6b272df11 $
*/

$module['core']['name']='Core Class';
$module['core']['ver']='1.1.0';

class Core{

	/**
	* 
	* Database Connection
	*
	* @var object
	*/
	var $db;
	
	/**
	* 
	* Logging Class
	*
	* @var object
	*/
	var $log;
	
	/**
	* 
	* Template Class
	*
	* @var object
	*/
 	var $tpl;

	/**
	* 
	* loaded Modules
	*
	* @var array
	*/
	var $mod_=array();

	/**
	* 
	* Sidebar Modules
	*
	* @var array
	*/
 	var $nav=array();

	/**
	* 
	* Major Version
	*
	* @var string
	*/
	var $ver_major='1';
	
	/**
	* 
	* Minor Version
	*
	* @var string
	*/
	var $ver_minor='1';

	/**
	* 
	*	Revision
	*
	* @var string
	*/
	var $ver_rev='0';

	/**
	* 
	*	Codename
	*
	* @var string
	*/
	var $ver_codename='Tim';
	
	/**
	* 
	*	Navbits
	*
	* @var array
	*/
	var $navbits=array();

	/**
	* Constructor
	*
	* @param Database
	* @param Log
	* @param Template
	*/
	function __construct(& $db,& $log,& $tpl) {
		global $config;
		$this->log = & $log;
		$this->db = & $db;
		$this->tpl = & $tpl;
		$this->nav['left']=TRUE;
		$this->nav['right']=TRUE;
		$this -> add_navbit($config['sitetitle'],$config['path'].'/index.php');
	}
	
	/**
	* Loads all installed modules from the database
	*
	*/
	function load_modules(){
		global $config, $db;
		$result = $db->query("SELECT * FROM " . $config['prefix'] . "module");
		while ($row = $db->fetch_array($result)){
		    	$this->mod_[$row['file']] = $row;
		}

   	}

	/**
	* Creates the Sidebar
	*
	* @param string The side for which the Content should be rendered (l=left, r=right)
	* @return false|string
	*/
	function create_nav($side){
	    global $config, $cache, $db, $session, $lang, $plugin;
		$navrow = '';
		$navtpl= $this->tpl;
		$root = $_SERVER['DOCUMENT_ROOT'] . $config['path'];
		if($navtpl-> isCached('navmain.tpl','navmain'.$side)){
			$compilednav = $navtpl-> fetch('navmain.tpl','navmain'.$side);
			return $compilednav;
		}else{
			$nav = $cache->read('sidebar');
			if($nav==FALSE){
				$cache->update_sidebars();
				$nav = $cache->read('sidebar');
			}
			if($nav[$side] != NULL){
				foreach($nav[$side] as $row){
					$nav_title = $row['name'];
					$nav_content = $row['content'];
					$nav_file = $row['file'];
					if($nav_file == ''){
						preg_match_all ('{right=\"(?P<value>.*?)\"}',$nav_content,$regs);
						if(is_array($regs)){
							foreach($regs['value'] as $reg){
								if($session->userdata[$reg]){
									$nav_content=preg_replace("/\{right=\"".$reg."\"\}(.*?)\{\/right\}/si","\\1",$nav_content);
								}else{
									$nav_content=preg_replace("/\{right=\"".$reg."\"\}(.*?)\{\/right\}/si","",$nav_content);
								}
							}
						}

						if($session->userdata['uid']!=0){
							$nav_content=preg_replace("/\{logged_in\}(.*?)\{\/logged_in\}/si","\\1",$nav_content);
							$nav_content=preg_replace("/\{logged_out\}(.*?)\{\/logged_out\}/si","",$nav_content);
						}else{
							$nav_content=preg_replace("/\{logged_in\}(.*?)\{\/logged_in\}/si","",$nav_content);
							$nav_content=preg_replace("/\{logged_out\}(.*?)\{\/logged_out\}/si","\\1",$nav_content);
						}
						if($session->userdata['allow_grimdark']!=0){
							$nav_content=preg_replace("/\{allow_gd\}(.*?)\{\/allow_gd\}/si","\\1",$nav_content);
						}else{
							$nav_content=preg_replace("/\{allow_gd\}(.*?)\{\/allow_gd\}/si","",$nav_content);
						}

						if(trim($nav_content)!=''){
							$navtpl->assign('navtitle', $nav_title);
							$navtpl->assign('navcontent', $nav_content);
							$navrow .= $navtpl->fetch('nav.tpl');
						}
						
						
					}elseif(file_exists($root.'/nav_modules/nav_' . $nav_file .'.php')){
						$navtpl->assign('navtitle', $nav_title);
						$navtpl->assign('navcontent', $nav_content);
						// include a Navigation Module. The Navigation Module MUST return a variable $navcontent
						include($root.'/nav_modules/nav_' . $nav_file .'.php');
					}
				}
				
				$navtpl->assign('nav', $navrow);

				if($side=='l'){
					$sidename='leftside';
				}else{
					$sidename='rightside';
				}
			
				$navtpl->assign('sidename', $sidename);
				$compilednav = $navtpl->fetch('navmain.tpl','navmain'.$side);
				$plugin->run_hook('nav_finish',array(&$compilednav));
				return $compilednav;
			}else{
				return false;
			}
		}

	}

	/**
	* Outputs a Message
	*
	* @param string $title The title of the message
	* @param string $message The message
	* @param bool $redirect Should the user be redirected
	* @param string $url The redirect URL
	* @param integer $time The Time in seconds until the user gets redirected
	* @param bool $minimal Should the Sidebars not get rendered
	* 
	*/
	
	function message($title,$message,$redirect=FALSE,$url='',$time=4,$minimal=FALSE,$fetch_page=TRUE){
		global $config, $userdata, $userinfo, $tpl, $session, $lang, $meta;
		if(!isset($session->userdata) && $fetch_page){
			$session->page_begin('Message', FALSE);
		}
		
		if($url!='' && $redirect){
			$tpl->assign('message', $message.'<br /><a href="'.$url.'">'.$lang->_('CLICKREDIRECT').'</a>');
		}elseif($url!='' && !$redirect){
			$tpl->assign('message', $message.'<br /><a href="'.$url.'">'.$lang->_('CLICKCONTINUE').'</a>');
		}else{
			$tpl->assign('message', $message);
		}
		$tpl->assign('messagetitle', $title);
		if($redirect && $url!=''){	
			if(substr( $url, 0, 4 ) != "http") {
				$url = '//'.$config['domain'].$config['path'].$url;
			}
			$meta.='<meta http-equiv="refresh" content="'.$time.';URL='.$url.'" />';
		}
		$this->make_page($tpl->fetch('message.tpl'),$minimal);

	}

	/**
	* Outputs a Message
	*
	* @deprec  0.8.60 - 2009/06/20
	* @param string $title The title of the message
	* @param string $message The message
	* @param bool $redirect Should the user be redirected
	* @param string $url The redirect URL
	* @param integer $time The Time in seconds until the user gets redirected
	* 
	*/
	function redirect_message($title,$message,$redirect=FALSE,$url='',$time=4){
		$this->message($title,$message,$redirect,$url,$time,TRUE);
	}

	/**
	* Adds a Navbit
	*
	* @param string $title The title of the navbit
	* @param string $url The navbit url
	* 
	*/
	function add_navbit($title,$url=''){
		$this->navbits[]=array('name'=>$title,'url'=>$url);
	}
	
	/**
	* Clears Navbits
	* 
	*/
	function clear_navbits(){
		unset($this->navbits);
	}
	
	/**
	* get Navbits
	*
	* @returns string
	*
	*/
	function get_navbits(){
		foreach($this->navbits as $key => $nav){
			if(isset($this->navbits[$key+1])){
				if($nav['url']==''){
					$bit='<span class="navbit">'.$nav['name'].'</span>';
				}else{
					$bit='<a href="'.$nav['url'].'"><span class="navbit">'.$nav['name'].'</span></a>';
				}
			}else{
				if($nav['url']==''){
					$bit='<span class="active_navbit">'.$nav['name'].'</span>';
				}else{
					$bit='<a href="'.$nav['url'].'"><span class="active_navbit">'.$nav['name'].'</span></a>';
				}
			}
			
			if(!$navs){
				$navs=$bit;
			}else{
				$navs.=' / '.$bit;
			}
		}
		
		return $navs;
	}
	
	/**
	* Gets a module and renders the main content
	*
	* @param string $task The name of the module
	* @param string $subtask The name of the subfunction
	* @return void|string
	* 
	*/
	function get_module($task,$subtask=''){
		global $config, $userdata, $db, $cache, $tpl, $error, $session, $meta, $mod, $footer, $plugin;
		$content='';
		include dirname(dirname(__FILE__)).'/class_templates/page_module.template.php';
		if (strpos($task, '://') !== FALSE || strpos($task, '../') !== FALSE){
	 		$tpl->assign('messagetitle','Intruder Alert!');
        		$tpl->assign('message', 'The System has caught a possible attack. The Admins have been informed.');
			if($config['logging'])
				$this->log->write('XSS ATTACK: Someone tried calling '.$task.'!',1);
					
			return $tpl->fetch('message.tpl','INTRUDER');
		}elseif((file_exists('modules/'.$task.'/' . $task . '.output.php') && is_array($this->mod_[$task]) )|| $task==''){
			if($config['startmodule'] == $task){
				$result=$db->query("SELECT * FROM `".$config['prefix']."navigation` WHERE `side`='m' ORDER BY `sort`");
			}else{
				$result=$db->query("SELECT * FROM `".$config['prefix']."navigation` WHERE `side`='m' AND `valid`='E' ORDER BY `sort`");
			}
			while($row=$db->fetch_array($result)){
			
				if($row['name']=='maincontent'){
					if($task!=''){
						include 'modules/'.$task.'/' . $task. '.output.php';
						if($config['logging'])
							$this->log->write($task.' called.');
							
						if(class_exists($task)){
							$mod = new $task();
							$mod->get=$_GET;
							$mod->post=$_POST;
							$mod->files=$_FILES;
							$mod->request=$_REQUEST;
							if(isset($_SESSION)){
								$mod->session=$_SESSION;
							}
							$mod->cookie=$_COOKIE;
							$root = $_SERVER['DOCUMENT_ROOT'] . $config['path'];
							if(isset($config['theme']) && $config['theme']!='' && is_dir($root . '/modules/'.$task.'/templates/'.$config['theme']) && !$mod -> uses_default_templates){
								$mod -> tpl-> setTemplateDir($root . '/modules/'.$task.'/templates/'.$config['theme']);
							}elseif($mod -> uses_default_templates){
								if(isset($config['theme'])  && $config['theme']!='' && is_dir($root . '/themes/'.$config['theme'])){
									$mod -> tpl-> setTemplateDir($root . '/themes/'.$config['theme']);
				
								}else{
									$mod -> tpl-> setTemplateDir($root . '/themes/default');
								}
							}else{
								$mod -> tpl-> setTemplateDir($root . '/modules/'.$task.'/templates/default');
							}
						
							$meta.= $mod->redirect;
							if($subtask!=''){
								$submeta='meta_'.$subtask;
								$subfooter='footer_'.$subtask;
								$subtask='output_'.$subtask;

								if(!is_callable(array($mod,$subtask))){
									if($config['logging'])
										$this->log->write('FATAL ERROR: Modul '.$task.' was found, but does not contain FUNCTION '.$subtask.'!',1);
									
									return $error->http_error('404');
								}else{
									if(!is_callable(array($mod,$submeta))){
										$meta.= $mod->meta();
									}else{
										$meta.= $mod->$submeta();
									}
									if(!is_callable(array($mod,$subfooter))){
										$footer.= $mod->footer();
									}else{
										$footer.= $mod->$subfooter();
									}
									$content.=$mod->$subtask();	
								}
							}else{
								$meta.= $mod->meta();
								$footer.= $mod->footer();
								$content.=$mod->output();
							}
						}else{
							if($config['logging'])
								$this->log->write('FATAL ERROR: Modul '.$task.' was found, but does not contain CLASS '.$task.'!',1);
								
							return $error->http_error('404');
						}
					}
				}else{
					if($row['file']!=''){
						$file_content=$plugin->run_hook($row['file'],array(&$tpl));
						$content.=$file_content;
					}else{
						preg_match_all ('{right=\"(?P<value>.*?)\"}',$row['content'],$regs);
						if(is_array($regs)){
							foreach($regs['value'] as $reg){
								if($session->userdata[$reg]){
									$nav_content=preg_replace("/\{right=\"".$reg."\"\}(.*?)\{\/right\}/si","\\1",$row['content']);
								}else{
									$nav_content=preg_replace("/\{right=\"".$reg."\"\}(.*?)\{\/right\}/si","",$row['content']);
								}
							}
						}
						$session->page_begin('content', false);
						if($session->userdata['uid']!=0){
							$row['content']=preg_replace("/\{logged_in\}(.*?)\{\/logged_in\}/si","\\1",$row['content']);
							$row['content']=preg_replace("/\{logged_out\}(.*?)\{\/logged_out\}/si","",$row['content']);
						}else{
							$row['content']=preg_replace("/\{logged_in\}(.*?)\{\/logged_in\}/si","",$row['content']);
							$row['content']=preg_replace("/\{logged_out\}(.*?)\{\/logged_out\}/si","\\1",$row['content']);
						}
						if($session->userdata['allow_grimdark']!=0){
							$row['content']=preg_replace("/\{allow_gd\}(.*?)\{\/allow_gd\}/si","\\1",$row['content']);
						}else{
							$row['content']=preg_replace("/\{allow_gd\}(.*?)\{\/allow_gd\}/si","",$row['content']);
						}
						$content.=$row['content'];
					}
				}
			}
		}else{
			if($config['logging'])
				$this->log->write('Modul '.$task.' not found!',2);
				
			return $error->http_error('404');
		}
		$this->make_page($content);
	}

	function makeDownload($file, $dir, $type) {
	    	$fullPath=$dir.$file;
		// Must be fresh start
		if( headers_sent()) 
			die('Headers Sent');

		// Required for some browsers
		if(ini_get('zlib.output_compression'))
			ini_set('zlib.output_compression', 'Off');

		// File Exists?
		
		if( file_exists($fullPath) ){

			// Parse Info / Get Extension
			$fsize = filesize($fullPath);
			$path_parts = pathinfo($fullPath);
			$ext = strtolower($path_parts["extension"]);

			// Determine Content Type
			switch ($ext) {
				case "pdf": $ctype="application/pdf"; break;
				case "exe": $ctype="application/octet-stream"; break;
				case "zip": $ctype="application/zip"; break;
				case "doc": $ctype="application/msword"; break;
				case "xls": $ctype="application/vnd.ms-excel"; break;
				case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
				case "apk": $ctype='application/vnd.android.package-archive'; break;
				case "gif": $ctype="image/gif"; break;
				case "png": $ctype="image/png"; break;
				case "jpeg":
				case "jpg": $ctype="image/jpg"; break;
				default: $ctype="application/force-download";
			}

			header("Pragma: no-cache"); // required
			header("Expires: Mon, 26 Jul 1997 05:00:00 GMT\n");
			header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
			header("Content-Description: File Transfer");
			header("Cache-Control: no-cache, no-store, must-revalidate, post-check=0, pre-check=0");
			header("Content-Type: $ctype");
			header("Content-Disposition: attachment; filename=\"".basename($fullPath)."\";" );
			header("Content-Transfer-Encoding: binary");
			header("Content-Length: ".$fsize);
			ob_clean();
			readfile( $fullPath );
			flush();
		} else {
			die('File Not Found');
		}
	} 

	/**
	* Renders the Page
	*
	* @param string $content The content for the page
	* @param bool $minimal Render the Page in a minmal mode (e.g. for redirect)
	* @param string $minimal_tpl Custom minimal template
	* @param string $header_tpl Custom header template
	* @param string $footer_tpl Custom footer template	
	* @return void
	* 
	*/
	function make_page($content, $minimal=FALSE,$minimal_tpl='minimal_index.tpl',$header_tpl='header.tpl',$footer_tpl='footer.tpl', $headers=array()){
		global $config, $session, $start, $tpl, $db, $meta, $footer, $mod, $plugin,$plugin_content;
		$plugin->run_hook('frontpage_start',array(&$tpl));
		if(!empty($headers)){
			foreach($headers as $header){
				header($header['name'].": ".$header['value']);
			}
		}
		if($config['p3p_active']==1){
           header('P3P: CP="'.$config['p3p_string'].'"');
		}
		$tpl -> assign("path",$config["path"]."/");
        $tpl -> assign("themepath",'/themes/'.$config['theme']);
		$tpl -> assign('sitetitle', $config['sitetitle']);
		if(isset($mod->titleaddon) && $mod->titleaddon!=''){
			$tpl -> assign('titleaddon', ' - '.$mod->titleaddon);
		}
		$tpl -> assign('navbits',$this -> get_navbits());
		$tpl -> assign('meta', $meta);
		
		if($header_tpl!=''){
				$header=$tpl->fetch($header_tpl);
				$tpl -> assign('header', $header);
		}
		
		if(!$minimal){
			if($this->nav['right']){
				$rightnav = $this->create_nav('r');
				$tpl -> assign('rightnav', $rightnav);
			}
			if($this->nav['left']){
				$leftnav = $this->create_nav('l');
				$tpl -> assign('leftnav', $leftnav);
			}
			$plugin->run_hook('frontpage_middle',array(&$tpl));
			$tpl -> assign('content', $content);
			$tpl -> display('index.tpl');	
		}else{
			$tpl -> assign('content', $content);
			$tpl -> display($minimal_tpl);
		}
		$tpl->assign('queries', $db->querys());
		$tpl->assign('user', $session->userdata);
		$tpl->assign('memory', number_format((@memory_get_usage()/1048576),2).' Mb');
		$tpl->assign('version', $this->ver_major.'.'.$this->ver_minor.'.'.$this->ver_rev.' - '.$this->ver_codename);
		$tpl -> assign('footer', $footer);
		$end = getTime();
		$tpl->assign('gentime',round($end - $start,4));
		if($footer_tpl!=''){
			$tpl->display($footer_tpl);
		}
		$plugin->run_hook('frontpage_end',array(&$tpl));
		exit();
	}
	
	/**
	* Uploads a file
	*
	* @param string $filename The name for the file
	* @param string $tmpname The name of the Temporary (read uploaded) File
	* @param integer $maxwidth Maximal width of the image
	* @param integer $maxheight Maximal height of the image
	* @param bool $resize Resize the image if its bigger	
	* @param bool $keep_ratio Keep the Height to Width ratio when resizing
	* @return bool|string
	* 
	*/
	function upload_file($filename, $tmpname, $maxwidth=160, $maxheight=160, $resize=FALSE, $keep_ratio=TRUE){
		global $config, $lang;
		if(file_exists($tmpname)){
			 $sizes = getimagesize($tmpname);
			 $aspect_ratio = $sizes[1]/$sizes[0];
			 if ($sizes[1] <= $maxheight && $sizes[0] <= $maxwidth){
				$new_width = $sizes[0];
				$new_height = $sizes[1];
			}elseif(!$resize){
				return sprintf($lang->_('PICSIZE'),$maxwidth,$maxheight);
			 }elseif($keep_ratio){
				$new_height = $maxheight;
				$new_width = abs($new_height/$aspect_ratio);
				if($new_width > $maxwidth){
					$new_width = $maxwidth;
					$new_height = abs($new_width*$aspect_ratio);
				}
			 }else{
				$new_width = $maxwidth;
				$new_height = $maxheight;
			 }
			 
			$destimg=ImageCreateTrueColor($new_width,$new_height);
			
			if(!$destimg)
				return $lang->_('PICNOCREATE');
			
			/**
			*
			* Needed to fix PNG Background Transparency
			*/
			imagealphablending($destimg, false);
			imagesavealpha($destimg, true);
			
			$srcimg= $this->imagecreatefromfile($tmpname);
			
			if(!$srcimg)
				return $lang->_('PICNOCREATE');
				
			$cpy=ImageCopyResized($destimg,$srcimg,0,0,0,0,$new_width,$new_height,ImageSX($srcimg),ImageSY($srcimg));
			
			if(!$cpy)	
				return $lang->_('NORESIZE');
				
			$out=$this->imageoutput($sizes[2],$destimg,$filename);
			
			if(!$out)
				return $lang->_('CANTSAVEPIC');
			
			imagedestroy($destimg);
			imagedestroy($srcimg);
			return TRUE;
		}else{
			return $tmpname.' - '.$lang->_('FILENOEXIST');
		}
	
	}
	
	function imagecreatefromfile($path){
	    $info = @getimagesize($path);
	   
	    if(!$info)
	    {
		return false;
	    }
	   
	    $functions = array(
		IMAGETYPE_GIF => 'imagecreatefromgif',
		IMAGETYPE_JPEG => 'imagecreatefromjpeg',
		IMAGETYPE_PNG => 'imagecreatefrompng',
		IMAGETYPE_WBMP => 'imagecreatefromwbmp',
		IMAGETYPE_XBM => 'imagecreatefromwxbm',
		);
	   
	    if(!$functions[$info[2]])
	    {
		return false;
	    }
	   
	    if(!function_exists($functions[$info[2]]))
	    {
		return false;
	    }
	   
	    return $functions[$info[2]]($path);
	}
	
	function imageoutput($userfile_type, $image, $imgout=NULL){
	    	   
	    $functions = array(
		IMAGETYPE_GIF => 'imagegif',
		IMAGETYPE_JPEG => 'imagejpeg',
		IMAGETYPE_PNG => 'imagepng',
		IMAGETYPE_WBMP => 'imagewbmp',
		IMAGETYPE_XBM => 'imagewxbm',
		);
	   
	    if(!$functions[$userfile_type])
	    {
		return false;
	    }
	   
	    if(!function_exists($functions[$userfile_type]))
	    {
		return false;
	    }
	   
		if($functions[$userfile_type]=='imagejpeg'){
			return $functions[$userfile_type]($image, $imgout,100);
		}elseif($functions[$userfile_type]=='imagepng'){
			return $functions[$userfile_type]($image, $imgout,0);
		}else{
			return $functions[$userfile_type]($image, $imgout);		
		}
	
	}
}
?>
