<?php
/**
* PHP VoiceViewer - Router
*
* Provides some basic functions. Its responsible for routing through the
* VoiceViewer application. Loads output object. Trys to retrieve data from source.
* Uses output to display server, error or configure/throughput indexed file.
* In case application is used will simply switch to specified script context.
*
* Project : PHP VoiceViewer
* Copyright : Christopher Cooper © 2010
* License : FreeBSD
* Author : Christopher Cooper (PaNtHaLooN), hide@address.com
* Date : March 2010
* Version : 1.0.0
*
* Copyright 2010 Christopher Cooper. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY CHRISTOPHER COOPER ``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 CHRISTOPHER COOPER OR
* 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.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of Christopher Cooper.
*/
// Define acronyms
defined('DS') || define('DS', DIRECTORY_SEPARATOR);
// Main iclude
@require_once(dirname(__FILE__) . DS . '..' . DS . 'main.inc.php');
final class vv
{
const INIFILE_PATTERN = '*.ini';
private static $_pre_display_errors = null;
private static $_getfile = false;
private static $filters = array();
private static $text = array();
private static $_xmlrpc = false;
private static $_http_params = array();
public static $config = null;
public static $source = null;
public static function vvDie( $index = 'denied' )
{
if ( isset(self::$config['error_' . $index . '_exec']) )
{
eval(self::$config['error_' . $index . '_exec']);
die();
}
die(self::$config['error_' . $index]);
}
public static function checkAccess()
{
// Wrapper always enables _VV_EXEC
if ( (!defined('_VV_EXEC') || (_VV_EXEC !== true)) && (!defined('_VV_APP_EXEC') || (_VV_APP_EXEC !== true)) )
{
(defined('_VV_INDEX') && (_VV_INDEX === true) && self::vvDie('index')) || self::vvDie();
}
else if ( defined('_VV_WRAPPER_EXEC') && (_VV_WRAPPER_EXEC === true) )
{
if ( !isset(self::$config['wrapper']) )
{
self::vvDie();
}
}
else if ( isset(self::$config['wrapper']) && (!defined('_VV_APP_EXEC') || (_VV_APP_EXEC !== true)) &&
(vv::$config['wrapper_dual_exec'] !== true) && !vv::isXMLRequest() && !self::isFileRequest() )
{
self::vvDie();
}
}
public static function getPrivConfig( $section )
{
switch( $section )
{
case 'default':
case 'config':
return ((defined('_VV_EXEC') && (_VV_EXEC === true)) || (defined('_VV_APP_EXEC') || (_VV_APP_EXEC === true)));
break;
case 'wrapper':
return ( ((defined('_VV_EXEC') && (_VV_EXEC === true)) || (defined('_VV_APP_EXEC') && _VV_APP_EXEC === true)) &&
(!defined('_VV_WRAPPER_CONFIG') || (defined('_VV_WRAPPER_CONFIG') && (_VV_WRAPPER_CONFIG === true))) );
break;
default:
break;
}
return false;
}
public static function isFileRequest()
{
if ( (self::$_getfile === false) && array_key_exists(self::$config['output_file_tag'], $_GET) &&
vvOutput::fileExists(rawurldecode($_GET[self::$config['output_file_tag']])) )
{
self::$_getfile = true;
}
return self::$_getfile;
}
public static function isXMLRequest()
{
if ( (self::$_xmlrpc === false) && (self::$config['xmlrpc_enable'] === true) &&
array_key_exists('xml', $_GET) && (strlen($_GET['xml']) === 0) )
{
self::$_xmlrpc = true;
}
return self::$_xmlrpc;
}
public static function errorHandler( $errno, $errstr, $errfile, $errline, $errcontext )
{
if ( $errno & self::$config['error_types'] )
{
vvOutput::displayError($errno, $errstr, $errfile, $errline, self::$config['error_simple']);
if ( !isset(vv::$config['wrapper']) )
{
die();
}
}
return true; // Don't populate php messages
}
public static function exceptionHandler( $e )
{
vvOutput::displayError($e->getCode(), $e->getMessage(), $e->getFile(),
$e->getLine(), self::$config['error_simple']);
if ( !isset(vv::$config['wrapper']) )
{
die();
}
}
public static function rerouteErrors( $error_handler = 'vv::errorHandler', $exception_handler = 'vv::exceptionHandler' )
{
if ( (self::$config['error_route'] === true) && (self::$_pre_display_errors === null) )
{
self::$_pre_display_errors = ini_get('display_errors');
ini_set('display_errors', 0);
set_error_handler('vv::errorHandler');
set_exception_handler('vv::exceptionHandler');
}
}
public static function restoreErrors()
{
if ( (self::$config['error_route'] === true) && (self::$_pre_display_errors !== null) )
{
restore_exception_handler();
restore_error_handler();
ini_set('display_errors', self::$_pre_display_errors);
self::$_pre_display_errors = null;
}
}
public static function loadLanguagePath( $path )
{
foreach( array_filter(glob($path . self::INIFILE_PATTERN, GLOB_MARK), 'is_file') as $inifile )
{
if( is_array($iniarray = @parse_ini_file($inifile)) )
{
self::$text = array_merge(self::$text, $iniarray);
}
else if ( !self::isFileRequest() )
{
self::exceptionHandler(new vvException('ENGINE_PARSING_LANG_FAILED', 0, $inifile));
}
}
}
public static function init()
{
// First load default language ini files
self::loadLanguagePath(self::$config['vv_path_languages|full'] . self::$config['default_language'] . DS);
// Then load custom language ini files if necessary
if ( self::$config['default_language'] !== self::$config['language'] )
{
self::loadLanguagePath(self::$config['vv_path_languages|full'] . self::$config['language'] . DS);
}
// TODO: Setup logging facility and error hooks
}
public static function loadFilters()
{
foreach( self::getFilterClasses() as $filterclass )
{
eval('self::$filters[] = new vvFilter' . $filterclass . '();');
}
}
public static function applyFilters( ivvServer &$server )
{
foreach( self::$filters as &$filter )
{
$filter->filterServer($server);
}
self::applyChannelFilter($server->getRoot());
}
private static function applyChannelFilter( ivvChannel &$channel )
{
foreach( self::$filters as &$filter )
{
$filter->filterChannel($channel);
}
$users =& $channel->getUsers();
foreach( $users as &$user )
{
self::applyUserFilter($user);
}
$subs =& $channel->getChannels();
foreach( $subs as &$sub )
{
self::applyChannelFilter($sub);
}
}
private static function applyUserFilter( ivvUser &$user )
{
foreach( self::$filters as &$filter )
{
$filter->filterUser($user);
}
}
public static function main()
{
self::rerouteErrors();
if ( !self::isXMLRequest() && self::isFileRequest() )
{
vvOutput::displayFile(rawurldecode($_GET[self::$config['output_file_tag']]));
}
else
{
self::$source = new vvSource();
self::loadFilters();
self::applyFilters(self::$source->getServer());
vvOutput::displayServer(self::$source->getServer());
}
self::restoreErrors();
}
public static function text( $text )
{
if ( array_key_exists($text, self::$text) )
{
$text = self::$text[$text];
}
if ( func_num_args() > 1 )
{
$vargs = func_get_args();
return vsprintf($text, array_slice($vargs, 1));
}
return $text;
}
public static function vtext( $text, array $vargs )
{
if ( array_key_exists($text, self::$text) )
{
$text = self::$text[$text];
}
return vsprintf($text, $vargs);
}
public static function xslValue( $text )
{
if ( $text === true )
{
return '1';
}
else if ( $text === false )
{
return '0';
}
// TODO: make sure values are XML safe?
return "'" . $text . "'";
}
public static function htmlValue( $text )
{
return htmlentities($text, ENT_QUOTES, ivvEntity::DOM_ENCODING);
}
public static function getBaseURL()
{
$ssl = (strtoupper($_SERVER['HTTPS']) === 'ON');
$url = 'http';
$url .= ($ssl) ? 's://' : '://';
$url .= $_SERVER['SERVER_NAME'];
if ( ($_SERVER['SERVER_PORT'] !== '80') || ($ssl && ($_SERVER['SERVER_PORT'] !== '443')) )
{
$url .= ':' . $_SERVER['SERVER_PORT'];
}
$url .= preg_replace('/^(.*\/)[^\/]+$/', '$1', $_SERVER['SCRIPT_NAME']);
return $url;
}
public static function setHttpParam( $name, $value )
{
self::$_http_params[$name] = $value;
}
public static function buildHttpQuery( array $params = null )
{
if ( $params !== null )
{
return http_build_query(array_merge(self::$_http_params, $params));
}
return http_build_query(self::$_http_params);
}
public static function getURLContents( $url, $user = '', $pass = '' )
{
$context = null;
if ( ($user !== '') && ($pass !== '') )
{
$context = stream_context_create(array(
'http' => array('header' => 'Authorization: Basic ' . base64_encode($user . ':' . $pass))
));
}
/*
// file_get_contents does not seem catchable -> always triggers error ?
// users may get private information!
if ( $result = @file_get_contents($url, false, $context) === false )
{
throw new vvException('ENGINE_GETURLCONTENTS_FAILED');
}
return $result;
*/
return file_get_contents($url, false, $context);
}
public static function filePath( $name, $location = 'library', $type = 'inc', $extension = '.php' )
{
if ( strlen($type) === 0 )
{
return self::$config['vv_path_' . $location . '|full'] . $name . $extension;
}
return self::$config['vv_path_' . $location . '|full'] . $name . '.' . $type . $extension;
}
public static function outputFileURL( $name )
{
$file[self::$config['output_file_tag']] = rawurlencode($name);
return self::$config['vv_url'] . '?' . self::buildHttpQuery($file);
}
public static function outputFilePath( $name )
{
if ( preg_match('/^(?P<base>[^\.]+)\./', self::$config['output'], $matches) === 1 )
{
$base = $matches['base'];
}
else
{
$base = self::$config['output'];
}
return self::$config['vv_path_output|full'] . $base . '/' . $name;
}
public static function &transformToDOMElement( &$data )
{
$result = null;
if ( is_string($data) )
{
$doc = new DOMDocument();
if ( $doc->loadXML($data) !== null )
{
$result =& $doc->documentElement;
}
}
else if ( ($data instanceof DOMElement) || ($data instanceof DOMDocument) ||
($data instanceof SimpleXMLElement) )
{
if ( $data instanceof DOMElement )
{
$result =& $data;
}
else if ( $data instanceof DOMDocument )
{
$result =& $data->firstChild;
}
else
{
$result =& dom_import_simplexml($data);
}
}
return $result;
}
public static function &loadXSLT( $file, array $attributes = null )
{
$xsl = new DOMDocument();
$xsl->load($file);
if ( $attributes !== null )
{
$xpath = new DOMXPath($xsl);
foreach ( $xpath->query('//xsl:param') as $param )
{
if ( array_key_exists($name = $param->getAttribute('name'), $attributes) )
{
$param->setAttribute('select', $attributes[$name]);
}
}
}
return $xsl;
}
public static function isDebug()
{
return self::$config['debug'];
}
public static function getFilterPaths()
{
$filters = array();
foreach( self::$config['filter'] as $filter )
{
$filters[] = self::filePath($filter, 'filters', 'filter');
}
return $filters;
}
public static function getFilterClasses()
{
$filters = array();
foreach( self::$config['filter'] as $filter )
{
$filters[] = ucfirst(strtolower($filter));
}
return $filters;
}
}
?>