includes/common.php
changeset 313 854eecfada20
parent 304 e2cb5f1432c8
parent 311 a007145a0ff6
child 326 ab66d6d1f1f4
equal deleted inserted replaced
310:199b9708f4a2 313:854eecfada20
     9  * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
     9  * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
    10  *
    10  *
    11  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
    11  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
    12  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
    12  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
    13  */
    13  */
    14 
    14  
    15 if(isset($_REQUEST['GLOBALS']))
    15 /**
       
    16  * The main loader script that initializes everything about Enano in the proper order. Prepare to get
       
    17  * redirected if you don't have $_GET['title'] or $_SERVER['PATH_INFO'] set up.
       
    18  * @package Enano
       
    19  * @subpackage Core
       
    20  * @copyright See header block
       
    21  */
       
    22 
       
    23 // Make sure we don't have an attempt to inject globals (register_globals on)
       
    24 if ( isset($_REQUEST['GLOBALS']) )
    16 {
    25 {
    17   ?>
    26   ?>
    18   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html><head><title>Hacking Attempt</title><meta http-equiv="Content-type" content="text/html; charset=utf-8" /></head><style type="text/css">body{background-color:#000;color:#CCC;font-family:trebuchet ms,sans-serif;font-size:9pt;}a{color:#FFF;}</style><body><p>Hacking attempt using <a href="http://www.hardened-php.net/index.76.html">PHP $GLOBALS overwrite vulnerability</a> detected, reported to admin</p><p>You're worse than this guy! Unless you are this guy...</p><p id="billp"><img alt=" " src="about:blank" id="billi" /></p><script type="text/javascript">// <![CDATA[
    27   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html><head><title>Hacking Attempt</title><meta http-equiv="Content-type" content="text/html; charset=utf-8" /></head><style type="text/css">body{background-color:#000;color:#CCC;font-family:trebuchet ms,sans-serif;font-size:9pt;}a{color:#FFF;}</style><body><p>Hacking attempt using <a href="http://www.hardened-php.net/index.76.html">PHP $GLOBALS overwrite vulnerability</a> detected, reported to admin</p><p>You're worse than this guy! Unless you are this guy...</p><p id="billp"><img alt=" " src="about:blank" id="billi" /></p><script type="text/javascript">// <![CDATA[
    19   window.onload=function(){counter();setInterval('counter();', 1000);};var text=false;var cnt=10;function counter(){if(!text){text=document.createElement('span');text.id='billc';text.innerHTML=cnt;text.style.fontSize='96pt';text.style.color='#FF0000';p=document.getElementById('billp');p.appendChild(text);}else{if(cnt==1){document.getElementById('billi').src='http://upload.wikimedia.org/wikipedia/commons/7/7f/Bill_Gates_2004_cr.jpg';document.getElementById('billc').innerHTML='';return;}cnt--;document.getElementById('billc').innerHTML=cnt+' ';}}
    28   window.onload=function(){counter();setInterval('counter();', 1000);};var text=false;var cnt=10;function counter(){if(!text){text=document.createElement('span');text.id='billc';text.innerHTML=cnt;text.style.fontSize='96pt';text.style.color='#FF0000';p=document.getElementById('billp');p.appendChild(text);}else{if(cnt==1){document.getElementById('billi').src='http://upload.wikimedia.org/wikipedia/commons/7/7f/Bill_Gates_2004_cr.jpg';document.getElementById('billc').innerHTML='';return;}cnt--;document.getElementById('billc').innerHTML=cnt+' ';}}
    20   // ]]>
    29   // ]]>
    21   </script><p><span style="color:black;">You been f***ed by Enano | valid XHTML 1.1</span></p></body></html>
    30   </script><p><span style="color:black;">You been f***ed by Enano | valid XHTML 1.1</span></p></body></html>
    22   <?php
    31   <?php
    23   exit;
    32   exit;
    24 }
    33 }
    25 
    34 
       
    35 // Our version number
       
    36 // This needs to match the version number in the database. This number should
       
    37 // be the expected output of enano_version(), which will always be in the
       
    38 // format of 1.0.2, 1.0.2a1, 1.0.2b1, 1.0.2RC1
       
    39 // You'll want to change this for custom distributions.
    26 $version = '1.1.1';
    40 $version = '1.1.1';
       
    41 
       
    42 /**
       
    43  * Returns a floating-point number with the current UNIX timestamp in microseconds. Defined very early because we gotta call it
       
    44  * from very early on in the script to measure the starting time of Enano.
       
    45  * @return float
       
    46  */
    27 
    47 
    28 function microtime_float()
    48 function microtime_float()
    29 {
    49 {
    30   list($usec, $sec) = explode(" ", microtime());
    50   list($usec, $sec) = explode(" ", microtime());
    31   return ((float)$usec + (float)$sec);
    51   return ((float)$usec + (float)$sec);
    32 }
    52 }
    33 
    53 
       
    54 // Determine starting time
    34 global $_starttime;
    55 global $_starttime;
    35 $_starttime = microtime_float();
    56 $_starttime = microtime_float();
    36 
    57 
       
    58 // Verbose error reporting
    37 error_reporting(E_ALL);
    59 error_reporting(E_ALL);
    38 
    60 
    39 // Determine directory (special case for development servers)
    61 //
       
    62 // Determine the location of Enano as an absolute path.
       
    63 //
       
    64 
       
    65 // We need to see if this is a specially marked Enano development server. You can create an Enano
       
    66 // development server by cloning the Mercurial repository into a directory named repo, and then
       
    67 // using symlinks to reference the original files so as to segregate unique files from non-unique
       
    68 // and distribution-standard ones. Enano will pivot its root directory accordingly if the file
       
    69 // .enanodev is found in the Enano root (not /repo/).
    40 if ( strpos(__FILE__, '/repo/') && ( file_exists('.enanodev') || file_exists('../.enanodev') ) )
    70 if ( strpos(__FILE__, '/repo/') && ( file_exists('.enanodev') || file_exists('../.enanodev') ) )
    41 {
    71 {
       
    72   // We have a development directory. Remove /repo/ from the picture.
    42   $filename = str_replace('/repo/', '/', __FILE__);
    73   $filename = str_replace('/repo/', '/', __FILE__);
    43 }
    74 }
    44 else
    75 else
    45 {
    76 {
       
    77   // Standard Enano installation
    46   $filename = __FILE__;
    78   $filename = __FILE__;
    47 }
    79 }
    48 
    80 
    49 if(!defined('ENANO_ROOT')) // ENANO_ROOT is sometimes defined by plugins like AjIM that need the constant before the Enano API is initialized
    81 // ENANO_ROOT is sometimes defined by plugins like AjIM that need the constant before the Enano API is initialized
       
    82 if ( !defined('ENANO_ROOT') )
    50   define('ENANO_ROOT', dirname(dirname($filename)));
    83   define('ENANO_ROOT', dirname(dirname($filename)));
    51 
    84 
    52 if(defined('ENANO_DEBUG') && version_compare(PHP_VERSION, '5.0.0') < 0)
    85 // Debugging features are PHP5-specifid
       
    86 if ( defined('ENANO_DEBUG') && version_compare(PHP_VERSION, '5.0.0') < 0 )
    53 {
    87 {
    54   die(__FILE__.':'.__LINE__.': The debugConsole requires PHP 5.x.x or greater. Please comment out the ENANO_DEBUG constant in your index.php.');
    88   die(__FILE__.':'.__LINE__.': The debugConsole requires PHP 5.x.x or greater. Please comment out the ENANO_DEBUG constant in your index.php.');
    55 }
    89 }
    56 
    90 
    57 /*
    91 // We deprecated debugConsole in 1.0.2 because it was never used and there were a lot of unneeded debugging points in the code.
    58 if(defined('ENANO_DEBUG'))
    92 
    59 {
    93 // _nightly.php is used to tag non-Mercurial-generated nightly builds
    60   require_once(ENANO_ROOT.'/includes/debugger/debugConsole.php');
       
    61 } else {
       
    62 */
       
    63   function dc_here($m)     { return false; }
       
    64   function dc_dump($a, $g) { return false; }
       
    65   function dc_watch($n)    { return false; }
       
    66   function dc_start_timer($u) { return false; }
       
    67   function dc_stop_timer($m) { return false; }
       
    68 //}
       
    69 
       
    70 if ( file_exists( ENANO_ROOT . '/_nightly.php') )
    94 if ( file_exists( ENANO_ROOT . '/_nightly.php') )
    71   require(ENANO_ROOT.'/_nightly.php');
    95   require(ENANO_ROOT.'/_nightly.php');
    72 
    96 
    73 // List of scheduled tasks
    97 // List of scheduled tasks (don't change this manually, use register_cron_task())
    74 $cron_tasks = array();
    98 $cron_tasks = array();
    75 
    99 
    76 // Start including files. LOTS of files. Yeah!
   100 // Start including files. LOTS of files. Yeah!
    77 require_once(ENANO_ROOT.'/includes/constants.php');
   101 require_once(ENANO_ROOT.'/includes/constants.php');
    78 dc_here('Enano CMS '.$version.' (dev) - debug window<br />Powered by debugConsole');
       
    79 dc_here('common: including files');
       
    80 require_once(ENANO_ROOT.'/includes/functions.php');
   102 require_once(ENANO_ROOT.'/includes/functions.php');
    81 require_once(ENANO_ROOT.'/includes/dbal.php');
   103 require_once(ENANO_ROOT.'/includes/dbal.php');
    82 require_once(ENANO_ROOT.'/includes/paths.php');
   104 require_once(ENANO_ROOT.'/includes/paths.php');
    83 require_once(ENANO_ROOT.'/includes/sessions.php');
   105 require_once(ENANO_ROOT.'/includes/sessions.php');
    84 require_once(ENANO_ROOT.'/includes/template.php');
   106 require_once(ENANO_ROOT.'/includes/template.php');
    99 require_once(ENANO_ROOT.'/includes/pageprocess.php');
   121 require_once(ENANO_ROOT.'/includes/pageprocess.php');
   100 require_once(ENANO_ROOT.'/includes/tagcloud.php');
   122 require_once(ENANO_ROOT.'/includes/tagcloud.php');
   101 
   123 
   102 strip_magic_quotes_gpc();
   124 strip_magic_quotes_gpc();
   103 
   125 
   104 // Enano has five parts: the database abstraction layer (DBAL), the session manager, the path/URL manager, the template engine, and the plugin manager.
   126 // Enano has five main components: the database abstraction layer (DBAL), the session manager,
   105 // Each part has its own class and a global var; nearly all Enano functions are handled by one of these five components.
   127 // the path/URL manager, the template engine, and the plugin manager.
       
   128 // Each part has its own class and a global object; nearly all Enano functions are handled by one of these five components.
       
   129 // All of these classes are singletons and are designed to carry as much data as possible within the object
       
   130 // to make data access and function calling easy.
   106 
   131 
   107 global $db, $session, $paths, $template, $plugins; // Common objects
   132 global $db, $session, $paths, $template, $plugins; // Common objects
   108 global $enano_config; // A global used to cache config information without making loads of queries ;-)
   133 global $enano_config; // A global used to cache config information without making loads of queries ;-)
   109                       // In addition, $enano_config is used to fetch config information if die_semicritical() is called.
   134                       // In addition, $enano_config is used to fetch config information if die_semicritical() is called.
   110                       
   135 
       
   136 // Jim Tucek's e-mail encryption code                      
   111 global $email;
   137 global $email;
       
   138 
       
   139 // Language object
   112 global $lang;
   140 global $lang;
   113 
   141 
   114 if(!isset($_SERVER['HTTP_HOST'])) grinding_halt('Cannot get hostname', '<p>Your web browser did not provide the HTTP Host: field. This site requires a modern browser that supports the HTTP 1.1 standard.</p>');
   142 // Because Enano sends out complete URLs in several occasions, we need to know what hostname the user is requesting the page from.
   115                      
   143 // In future versions we may include a fallback "safety" host to use, but that's too much to worry about now
       
   144 if ( !isset($_SERVER['HTTP_HOST']) )
       
   145   grinding_halt('Cannot get hostname', '<p>Your web browser did not provide the HTTP Host: field. This site requires a modern browser that supports the HTTP 1.1 standard.</p>');
       
   146 
       
   147 //
       
   148 // END BACKGROUND AND ENVIRONMENT CHECKS
       
   149 //
       
   150 
       
   151 //
       
   152 // MAIN API INITIALIZATION
       
   153 //
       
   154 
       
   155 // The first thing we need to do is start the database connection. At this point, for all we know, Enano might not
       
   156 // even be installed. If this connection attempt fails and it's because of a missing or corrupt config file, the
       
   157 // user will be redirected (intelligently) to install.php.
   116 $db = new mysql();
   158 $db = new mysql();
   117 dc_here('common: calling $db->connect();');
   159 $db->connect();
   118 $db->connect(); // Redirects to install.php if an installation is not detected
   160 
   119 
   161 // The URL separator is the character appended to contentPath + url_title type strings.
   120 if(strstr(contentPath, '?')) $sep = '&';
   162 // If the contentPath has a ? in it, this should be an ampersand; else, it should be a
   121 else $sep = '?';
   163 // question mark.
       
   164 $sep = ( strstr(contentPath, '?') ) ? '&' : '?';
   122 define('urlSeparator', $sep);
   165 define('urlSeparator', $sep);
   123 unset($sep); // save 10 bytes of memory...
   166 unset($sep); // save 10 bytes of memory...
   124 
   167 
   125 // See if any diagnostic actions have been requested
   168 // Sometimes there are critical failures triggered by initialization functions in the Enano API that are recurring
       
   169 // and cannot be fixed except for manual intervention. This is where that code should go.
   126 if ( isset($_GET['do']) && $_GET['do'] == 'diag' && isset($_GET['sub']) )
   170 if ( isset($_GET['do']) && $_GET['do'] == 'diag' && isset($_GET['sub']) )
   127 {
   171 {
   128   switch($_GET['sub'])
   172   switch($_GET['sub'])
   129   {
   173   {
   130     case 'cookie_destroy':
   174     case 'cookie_destroy':
   135       break;
   179       break;
   136   }
   180   }
   137 }
   181 }
   138 
   182 
   139 // Select and fetch the site configuration
   183 // Select and fetch the site configuration
   140 dc_here('common: selecting global config data');
       
   141 $e = $db->sql_query('SELECT config_name, config_value FROM '.table_prefix.'config;');
   184 $e = $db->sql_query('SELECT config_name, config_value FROM '.table_prefix.'config;');
   142 if(!$e) $db->_die('Some critical configuration information could not be selected.');
   185 if ( !$e )
   143 else define('ENANO_CONFIG_FETCHED', ''); // Used in die_semicritical to figure out whether to call getConfig() or not
   186 {
   144 
   187   $db->_die('Some critical configuration information could not be selected.');
   145 dc_here('common: fetching $enano_config');
   188 }
       
   189 // Used in die_semicritical to figure out whether to call getConfig() or not
       
   190 define('ENANO_CONFIG_FETCHED', '');
       
   191 
       
   192 // Initialize and fetch the site configuration array, which is used to cache the config
   146 $enano_config = Array();
   193 $enano_config = Array();
   147 while($r = $db->fetchrow())
   194 while($r = $db->fetchrow())
   148 {
   195 {
   149   $enano_config[$r['config_name']] = $r['config_value'];
   196   $enano_config[$r['config_name']] = $r['config_value'];
   150 }
   197 }
   151 
   198 
   152 $db->free_result();
   199 $db->free_result();
   153 
   200 
   154 if(enano_version(false, true) != $version)
   201 // Now that we have the config, check the Enano version.
       
   202 if ( enano_version(false, true) != $version )
   155 {
   203 {
   156   grinding_halt('Version mismatch', '<p>It seems that the Enano release we\'re trying to run ('.$version.') is different from the version specified in your database ('.enano_version().'). Perhaps you need to <a href="'.scriptPath.'/upgrade.php">upgrade</a>?</p>');
   204   grinding_halt('Version mismatch', '<p>It seems that the Enano release we\'re trying to run ('.$version.') is different from the version specified in your database ('.enano_version().'). Perhaps you need to <a href="'.scriptPath.'/upgrade.php">upgrade</a>?</p>');
   157 }
   205 }
   158 
   206 
   159 //
   207 //
   232     table_prefix.'page_groups',
   280     table_prefix.'page_groups',
   233     table_prefix.'page_group_members',
   281     table_prefix.'page_group_members',
   234     table_prefix.'tags'
   282     table_prefix.'tags'
   235   );
   283   );
   236 
   284 
   237 dc_here('common: initializing base classes');
   285 // Load plugin manager
   238 $plugins = new pluginLoader();
   286 $plugins = new pluginLoader();
   239 
   287 
   240 // So where does the majority of Enano get executed? How about the next nine lines of code :)
   288 //
   241 dc_here('common: ok, we\'re set up, starting mainstream execution');
   289 // Mainstream API boot-up
   242 
   290 //
       
   291 
       
   292 // Obtain list of plugins
   243 $plugins->loadAll();
   293 $plugins->loadAll();
   244 dc_here('common: loading plugins');
   294 
   245   global $plugins;
   295 global $plugins;
   246   foreach($plugins->load_list as $f) { include_once $f; } // Can't be in object context when this is done
   296 
   247 
   297 // Load plugins from common because we can't give plugins full abilities in object context
       
   298 foreach ( $plugins->load_list as $f )
       
   299 {
       
   300   include_once $f;
       
   301 }
       
   302 
       
   303 // Three fifths of the Enano API gets the breath of life right here.
   248 $session = new sessionManager();
   304 $session = new sessionManager();
   249 $paths = new pathManager();
   305 $paths = new pathManager();
   250 $template = new template();
   306 $template = new template();
   251 $email = new EmailEncryptor();
   307 $email = new EmailEncryptor();
   252 
   308 
       
   309 // We've got the five main objects - flick on the switch so if a problem occurs, we can have a "friendly" UI
   253 define('ENANO_BASE_CLASSES_INITIALIZED', '');
   310 define('ENANO_BASE_CLASSES_INITIALIZED', '');
   254 
   311 
       
   312 // From here on out, none of this functionality is needed during the installer stage.
       
   313 // Once $paths->init() is called, we could be redirected to the main page, so we don't want
       
   314 // that if the installer's running. Don't just go and define IN_ENANO_INSTALL from your
       
   315 // script though, because that will make the DBAL look in the wrong place for the config file.
   255 if ( !defined('IN_ENANO_INSTALL') )
   316 if ( !defined('IN_ENANO_INSTALL') )
   256 {
   317 {
       
   318   // And here you have it, the de facto way to place a hook. Plugins can place hooks and hook
       
   319   // into other plugins. You just never know.
   257   $code = $plugins->setHook('base_classes_initted');
   320   $code = $plugins->setHook('base_classes_initted');
   258   foreach ( $code as $cmd )
   321   foreach ( $code as $cmd )
   259   {
   322   {
   260     eval($cmd);
   323     eval($cmd);
   261   }
   324   }
   262     
   325   
       
   326   // For special and administration pages, sometimes there is a "preloader" function that must be run
       
   327   // before the session manager and/or path manager get the init signal. Call it here.  
   263   $p = RenderMan::strToPageId($paths->get_pageid_from_url());
   328   $p = RenderMan::strToPageId($paths->get_pageid_from_url());
   264   if( ( $p[1] == 'Admin' || $p[1] == 'Special' ) && function_exists('page_'.$p[1].'_'.$p[0].'_preloader'))
   329   if( ( $p[1] == 'Admin' || $p[1] == 'Special' ) && function_exists('page_'.$p[1].'_'.$p[0].'_preloader'))
   265   {
   330   {
   266     @call_user_func('page_'.$p[1].'_'.$p[0].'_preloader');
   331     @call_user_func('page_'.$p[1].'_'.$p[0].'_preloader');
   267   }
   332   }
   269   // One quick security check...
   334   // One quick security check...
   270   if ( !is_valid_ip($_SERVER['REMOTE_ADDR']) )
   335   if ( !is_valid_ip($_SERVER['REMOTE_ADDR']) )
   271   {
   336   {
   272     die('SECURITY: spoofed IP address');
   337     die('SECURITY: spoofed IP address');
   273   }
   338   }
   274   
   339 
       
   340   // All checks passed! Start the main components up.  
   275   $session->start();
   341   $session->start();
   276   $paths->init();
   342   $paths->init();
   277   
   343   
       
   344   // We're ready for whatever life throws us now.
   278   define('ENANO_MAINSTREAM', '');
   345   define('ENANO_MAINSTREAM', '');
   279   
   346   
   280   // If the site is disabled, bail out, unless we're trying to log in or administer the site
   347   // If the site is disabled, bail out, unless we're trying to log in or administer the site
   281   if(getConfig('site_disabled') == '1' && $session->user_level < USER_LEVEL_ADMIN)
   348   if(getConfig('site_disabled') == '1' && $session->user_level < USER_LEVEL_ADMIN)
   282   {
   349   {
   297       </div>';
   364       </div>';
   298       $paths->wiki_mode = 0;
   365       $paths->wiki_mode = 0;
   299       die_semicritical('Site disabled', $text);
   366       die_semicritical('Site disabled', $text);
   300     }
   367     }
   301   }
   368   }
   302   else if(getConfig('site_disabled') == '1' && $session->user_level >= USER_LEVEL_ADMIN)
   369   else if ( getConfig('site_disabled') == '1' && $session->user_level >= USER_LEVEL_ADMIN )
   303   {
   370   {
       
   371     // If the site is disabled but the user has admin rights, allow browsing
       
   372     // and stuff, but display the orange box notifying the admin.
   304     $template->site_disabled = true;
   373     $template->site_disabled = true;
   305   }
   374   }
   306   
   375   
       
   376   // A better name for this hook would be common_post. At this point
       
   377   // all of Enano is fully initialized and running and you're ready
       
   378   // to do whatever you want.
   307   $code = $plugins->setHook('session_started');
   379   $code = $plugins->setHook('session_started');
   308   foreach ( $code as $cmd )
   380   foreach ( $code as $cmd )
   309   {
   381   {
   310     eval($cmd);
   382     eval($cmd);
   311   }
   383   }
   312   
   384   
   313   if(isset($_GET['noheaders'])) $template->no_headers = true;
   385   if ( isset($_GET['noheaders']) )
   314 }
   386     $template->no_headers = true;
       
   387 }
       
   388 
       
   389 // That's the end. Enano should be loaded now :-)
   315 
   390 
   316 ?>
   391 ?>