| // +----------------------------------------------------------------------+ // | Authors: John Luxford | // +----------------------------------------------------------------------+ // // Sitellite Content Server // // $Id: index,v 1.2 2003/07/25 06:32:25 lux Exp $ // // This script is used to generate all of the pages in your site. It is // the base index file that you should have people default to seeing when // they hit your domain. This can be accomplished using a simple redirect, // or through Apache directives, having a static splash page link to this // one, or by renaming this file accordingly, although there may be // consequences to some of these possibilities. Our recommendation is to // use Apache directives to add this to the DirectoryIndex list, and to // use a ForceType directive to make the server aware that this is a PHP // file. For more information, see the INSTALL file and the .htaccess // file that come with this file. // // This script implements the Controller component of the // Model-View-Controller (MVC) design pattern. For more information about // MVC application design, please read the Sitellite Content Server // Developer Manual. // /*************************************************************************/ /* SET OLDER VERSION REFERENCES */ /*************************************************************************/ // We can use these by calling $_SERVER instead of $HTTP_SERVER_VARS, but // we have to be mindful to call global $_SERVER, just in case we're using // a version below 4.1.0. if (PHP_VERSION < '4.1.0') { $_SERVER =& $HTTP_SERVER_VARS; $_GET =& $HTTP_GET_VARS; $_POST =& $HTTP_POST_VARS; $_COOKIE =& $HTTP_COOKIE_VARS; $_FILES =& $HTTP_POST_FILES; $_ENV =& $HTTP_ENV_VARS; $_REQUEST = false; $_SESSION =& $HTTP_SESSION_VARS; } /*************************************************************************/ /*************************************************************************/ /* Create Global $conf Array */ /*************************************************************************/ $conf = parse_ini_file ('inc/conf/config.ini.php', true); // split values which should be arrays $conf['Cache']['cacheable'] = preg_split ('/, ?/', $conf['Cache']['cacheable']); /*************************************************************************/ /*************************************************************************/ /* Send Sitellite HTTP Header */ /*************************************************************************/ // We send a Sitellite HTTP header to track which version of the software // is being run. This will produce a header in the form: // X-Powered-By: Sitellite/x.0.x include_once ('inc/conf/version.php'); if ($conf['Server']['send_version_header']) { header ('X-Powered-By: Sitellite/' . SITELLITE_VERSION); } /*************************************************************************/ /*************************************************************************/ /* Initialize Library Loader */ /*************************************************************************/ // This simply imports the saf/init.php file. // This file also creates global $loader, $cgi, and $simple objects, // of the types Loader, CGI, and SimpleTemplate, respectively. include_once ($conf['Site']['safpath'] . '/init.php'); /*************************************************************************/ /*************************************************************************/ /* Cache Evaluation */ /*************************************************************************/ // If duration is 0, cache is turned off if ($conf['Cache']['duration'] > 0) { // Load Cache class $loader->import ('saf.Cache'); // Set the $uri variable if ((empty ($_SERVER['REQUEST_URI'])) || (! eregi ('[a-z]', $_SERVER['REQUEST_URI']))) { $uri = '/' . __FILE__; } else { $uri = $_SERVER['REQUEST_URI']; } // Create a Cache object and tell it where to cache files (directory, // berkeley database, or via proxy/caching) $cache = new Cache ($conf['Cache']['location']); if ( // Make sure page is cacheable $cache->is_cacheable ($uri, $conf['Cache']['cacheable']) && // Make sure no POST variables were sent (can't cache POSTed pages) count ($_POST) == 0 ) { // If the cached copy has not expired, use it. if (! $cache->expired ($uri, $conf['Cache']['duration'])) { // Display page from cache. //echo 'using cached copy'; echo $cache->show ($uri); exit; } else { //echo $uri; // Let the script carry its course, and cache the data before // it is sent to the visitor. //echo 'generating new copy: ' . $cache->serialize ($uri); } } else { //echo $uri; // Page is not cacheable, carry on //echo 'page not cacheable'; } // Below is essentially the else to the cache system. // Remember, if we're caching the page, we need to hold // all the data in an output buffer, then output it to // the user and to the file. } /*************************************************************************/ /*************************************************************************/ /* Auto-Detect Values For $conf['Site'] */ /*************************************************************************/ // set domain $conf['Site']['domain'] =& $_SERVER['HTTP_HOST']; $_df = dirname (__FILE__); // set docroot if (empty ($conf['Site']['docroot'])) { if ($conf['Site']['usedocroot']) { $conf['Site']['docroot'] =& $_SERVER['DOCUMENT_ROOT']; } else { $conf['Site']['docroot'] =& $_df; } } // set appdir $conf['Site']['appdir'] =& $conf['Site']['docroot']; // set prefix list ($null, $conf['Site']['prefix']) = explode ($conf['Site']['docroot'], $_df); // set webpath and adminpath if (empty ($conf['Site']['prefix'])) { $conf['Site']['webpath'] = '/'; } else { $conf['Site']['webpath'] =& $conf['Site']['prefix']; } //set level $c = substr_count ($conf['Site']['prefix'], '/'); if ($c > 0) { // '/(\/)/', $conf['Site']['prefix'], $regs)) { $conf['Site']['level'] = $c - 1; } else { $conf['Site']['level'] = 0; } /*************************************************************************/ /*************************************************************************/ /* Import Libraries */ /*************************************************************************/ // Import libraries and config files (initializes variables and establishes // the database connection) $loader->import ('saf.I18n'); $loader->import ('saf.CGI.Cookie'); $loader->import ('saf.Database.Manager'); $loader->import ('saf.Date'); $loader->import ('saf.Site'); $loader->import ('saf.Session'); $loader->import ('saf.Template'); $loader->import ('saf.MailForm.Functions'); // If you load files that contain more than classes (variables, functions, etc.), // they will be declared in the Loader namespace. /*************************************************************************/ /*************************************************************************/ /* Create Global Objects */ /*************************************************************************/ $site = new Site ($conf['Site']); // holds configuration info $cookie = new Cookie; // holds cookie info $tpl = new Template ('inc/html'); // XT template engine $intl = new I18n ($conf['I18n']['directory'], $conf['I18n']['negotiate']); // translation object $intl->method = $conf['I18n']['serialize']; $dbm = new DBM (); if (! $dbm->add ($conf['Database']['connection_name'], $conf['Database']['driver'] . ':' . $conf['Database']['hostname'] . ':' . $conf['Database']['database'], $conf['Database']['username'], $conf['Database']['password'], $conf['Database']['persistent'])) { echo '

Database connection object not found!

'; echo '

This is the result of a misconfiguration or syntax error in the configuration file. Please verify that your configurations in inc/conf/config.php are correct.

'; echo '

DBM Error Message: ' . $dbm->error . '

'; exit; } $dbm->setCurrent ($conf['Database']['connection_name']); /*************************************************************************/ /*************************************************************************/ /* Member Session Handling */ /*************************************************************************/ // Create session now, if they've signed in or are already so // this will include multiple session configurations dynamically // in a fashion similar to the box setup. if ($dh = opendir ('inc/sessions')) { while (($file = readdir ($dh)) !== false) { if (@file_exists ('inc/sessions/' . $file . '/index.php')) { include_once ('inc/sessions/' . $file . '/index.php'); } } } closedir ($dh); // turn off url rewriting by the PHP session trans sid, as this causes // problems with Sitellite's own url rewriting, and also poses extra // security risks. ini_set ('url_rewriter.tags', ''); /*************************************************************************/ /*************************************************************************/ /* Global Properties */ /*************************************************************************/ // Load the global application properties from inc/conf/properties.php // and $app/conf/properties.php as well. if (@file_exists ('inc/conf/properties.php')) { include_once ('inc/conf/properties.php'); } //if (@file_exists ('inc/app/' . $app . '/conf/properties.php')) { // include_once ('inc/app/' . $app . '/conf/properties.php'); //} /*************************************************************************/ // NOTE: THIS WILL CHANGE VERY SHORTLY /*************************************************************************/ /* Menu Initializations */ /*************************************************************************/ // to make requests where no menu object is instantiated (useful for // services that simply output XML content such as RDF/RSS or XML-RPC), // simply add /nomenu.true to the request URI. if (! isset ($cgi->nomenu)) { $loader->import ('saf.GUI.Menu'); $menu = new Menu ('sitellite_page', 'id', 'title', 'below_page', 'include', 'is_section'); $menu->sitelliteAllowed = true; $menu->getTree (); } /*************************************************************************/ /*************************************************************************/ /* CGI Request Data Handling */ /*************************************************************************/ // tell cgi object to parse the URI for variables. option is used // to get variables that were passed as directories so as to fake // out the search engines. this method avoids the use of ? and &, // which searches tend not to like, and uses a . (looks like a file // extension to me!) in place of = to denote key/value pairs. $extras = $cgi->parseUri (); // backward-compatibility stuff, and we still use $cgi->mode in determining // which template to use. // if $cgi->page is empty, default to 'index' if (empty ($cgi->page)) { $cgi->page = $extras[$conf['Site']['level']]; $_GET['page'] = $cgi->page; } if (empty ($cgi->page) || strstr ($cgi->page, '..')) { $cgi->page = $conf['Server']['default_handler']; $_GET['page'] = $cgi->page; } // if $cgi->mode is empty, default to 'html' if (empty ($cgi->mode)) { $cgi->mode = $extras[$conf['Site']['level'] + 1]; $_GET['mode'] = $cgi->mode; } if (empty ($cgi->mode) || strstr ($cgi->mode, '..') || ($cgi->mode != 'preview' && ! @file_exists (getcwd () . '/' . $tpl->path . '/' . $cgi->mode . '.tpl'))) { $cgi->mode = 'html'; $_GET['mode'] = $cgi->mode; } /*************************************************************************/ /*************************************************************************/ /* Determine Request Type */ /*************************************************************************/ // This stage determines how to call the Model and the View in order to // retrieve the request data structure (from the Model) and the output // template (from the View). if ($conf['Site']['level'] > 0) { array_splice ($extras, 0, $conf['Site']['level']); } if (count ($extras) == 0) { $request = $conf['Server']['default_handler']; $type = $conf['Server']['default_handler_type']; } else { $request = array_shift ($extras); if (strlen ($request) > 7 && strrpos ($request, '-action') == (strlen ($request) - 7)) { $request = str_replace ('-', '/', substr ($request, 0, -7)); $type = 'box'; } elseif (strlen ($request) > 6 && strrpos ($request, '-form') == (strlen ($request) - 5)) { $request = str_replace ('-', '/', substr ($request, 0, -5)); $type = 'form'; } elseif (strlen ($request) > 4 && strrpos ($request, '-app') == (strlen ($request) - 4)) { $request = str_replace ('-', '/', substr ($request, 0, -4)); $type = 'app'; } else { $type = 'document'; } } $loader->app =& $conf['Server']['default_app']; //if ($type != 'document') { // determine $app before settling on the default //$app = $loader->getApp ($request); //$request = $loader->removeApp ($request, $app); //} /*************************************************************************/ /*************************************************************************/ /* Document Creation */ /*************************************************************************/ // At this stage, we are ready to ask the Model for our response data // structure. This is stored in a $page object. loader_import ('saf.Misc.Document'); $page = new Document; loader_import ('saf.Misc.Ini'); $ini = new Ini; $page->body = false; while (! $page->id) { switch ($type) { case 'app': if (! @file_exists ('inc/app/' . $request . '/conf/config.ini.php')) { $request = $conf['Server']['error_handler']; $type = $conf['Server']['error_handler_type']; $errno = E_NOT_FOUND; break; } $appconf = $ini->parse ('inc/app/' . $request . '/conf/config.ini.php', false); $request = $request . '/' . $appconf['default_handler']; $type = $appconf['default_handler_type']; break; case 'box': if (! $template = loader_box_allowed ($request, 'action')) { $request = $conf['Server']['error_handler']; $type = $conf['Server']['error_handler_type']; $errno = E_NOT_FOUND; break; } $page->id = $cgi->page; $page->template = $template; $page->set (loader_box ($request, get_object_vars ($cgi), 'action')); break; case 'form': if (! $template = loader_form_allowed ($request, 'action')) { $request = $conf['Server']['error_handler']; $type = $conf['Server']['error_handler_type']; $errno = E_NOT_FOUND; break; } $page->id = $cgi->page; $page->template = $template; $page->set (loader_form ($request, 'action')); break; case 'document': if ($cgi->mode == 'preview') { // preview mode is a special case where request variables can replace page elements, // even if the requested page doesn't exist. if (! $pg) { $pg = new StdClass; } $pg->id = $request; $pg->title = $cgi->title; $pg->body = $cgi->body; $pg->preview = true; $cgi->mode = 'html'; } else { $pg = db_fetch ('select * from sitellite_page where id = ? and ' . session_allowed_sql (), $request); if (! $pg) { $request = $conf['Server']['error_handler']; $type = $conf['Server']['error_handler_type']; $errno = E_NOT_FOUND; break; } } $page->set ($pg); $tpl->buildToc = true; $page->body = template_xt (template_wrap (template_convert_entities ($page->body))); if (template_error ()) { // display original (unparsed for boxes/forms) with the error appended as a comment $page->body = $pg->body . NEWLINEx2 . ''; } $page->_toc = $tpl->toc; $page->toc = template_toc (); $tpl->buildToc = false; break; } // end switch ($type) } // end while (! $page->id) /*************************************************************************/ /*************************************************************************/ /* Compile Response */ /*************************************************************************/ // Here the $page object, which now has the response data structure, // calls the View so that the data can be expanded into a template to // put it in the requested output mode, or format. $response = $page->compile (); /*************************************************************************/ /*************************************************************************/ /* Cache Cleanup */ /*************************************************************************/ // Perform a little last-minute cache magic... if ($conf['Cache']['duration'] > 0 && $cache->set) { $cache->file ($uri, $response); $cache->shutdown (); } // Respond. echo $response; // And they lived happily ever after. /*************************************************************************/ ?>