kernel
[ class tree: kernel ] [ index: kernel ] [ all elements ]

Source for file BitSystem.php

Documentation is available at BitSystem.php

  1. <?php
  2. /**
  3.  * Main bitweaver systems functions
  4.   *
  5.  * @version $Header$
  6.  *
  7.  *  Copyright (c) 2004 bitweaver.org
  8.  *  All Rights Reserved. See below for details and a complete list of authors.
  9.  *  Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See http://www.gnu.org/copyleft/lesser.html for details
  10.  *
  11.  *  Virtual base class (as much as one can have such things in PHP) for all
  12.  *  derived tikiwiki classes that require database access.
  13.  *
  14.  *  created 2004/8/15
  15.  *
  16.  * @author spider <spider@steelsun.com>
  17.  * @package  kernel
  18.  */
  19.  
  20. /**
  21.  * required setup
  22.  */
  23. require_onceKERNEL_PKG_PATH 'BitSingleton.php' );
  24. require_onceKERNEL_PKG_PATH 'BitDate.php' );
  25. require_onceTHEMES_PKG_PATH 'BitSmarty.php' );
  26. require_onceKERNEL_PKG_PATH 'HttpStatusCodes.php' );
  27.  
  28. define'DEFAULT_PACKAGE''kernel' );
  29. define'CENTER_COLUMN''c' );
  30. define'HOMEPAGE_LAYOUT''home' );
  31.  
  32. /**
  33.  * kernel::BitSystem
  34.  *
  35.  * Purpose:
  36.  *
  37.  *     This is the main system class that does the work of seeing bitweaver has an
  38.  *     operable environment and has methods for modifying that environment.
  39.  *
  40.  *     Currently gBitSystem derives from this class for backward compatibility sake.
  41.  *     Ultimate goal is to put system code from BitBase here, and base code from
  42.  *     gBitSystem (code that ALL features need) into BitBase and code gBitSystem that
  43.  *     is Package specific should be moved into that package
  44.  *
  45.  * @author spider <spider@steelsun.com>
  46.  *
  47.  * @package kernel
  48.  */
  49. class BitSystem extends BitSingleton {
  50.  
  51.     // Initiate class variables
  52.  
  53.     // Essential information about packages
  54.     var $mPackages = array();
  55.  
  56.     // Cross Reference Package Directory Name => Package Key used as index into $mPackages
  57.     var $mPackagesDirNameXref = array();
  58.  
  59.     // Contains site style information
  60.     var $mStyle = array();
  61.  
  62.     // Information about package menus used in all menu modules and top bar
  63.     var $mAppMenu = array();
  64.  
  65.     // The currently active page
  66.     var $mActivePackage;
  67.  
  68.     // Modules that need to be inserted during installation
  69.     var $mInstallModules = array();
  70.  
  71.     // Javascript to be added to the <body onload> attribute
  72.     var $mOnload = array();
  73.  
  74.     // Javascript to be added to the <body onunload> attribute
  75.     var $mOnunload = array();
  76.  
  77.     // Used by packages to register notification events that can be subscribed to.
  78.     var $mNotifyEvents = array();
  79.  
  80.     // Used to store contents of kernel_config
  81.     var $mConfig;
  82.  
  83.     // Used to monitor if ::registerPackage() was called. This is used to determine whether to auto-register a package
  84.     var $mRegisterCalled;
  85.  
  86.     // The name of the package that is currently being processed
  87.     var $mPackageFileName;
  88.  
  89.     // Content classes.
  90.     var $mContentClasses = array();
  91.  
  92.     // Debug HTML to be displayed just after the HTML headers
  93.     var $mDebugHtml = "";
  94.  
  95.     // Output http status
  96.     var $mHttpStatus = HttpStatusCodes::HTTP_OK;
  97.  
  98.     protected static $singleton null;
  99.     protected static function getSingleInstance({
  100.         return static::$singleton;
  101.     }
  102.  
  103.     // === BitSystem constructor
  104.     /**
  105.      * base constructor, auto assigns member db variable
  106.      *
  107.      * @access public
  108.      */
  109.     // Constructor receiving a PEAR::Db database object.
  110.     function __construct({
  111.         global $gBitTimer;
  112.         // Call DB constructor which will create the database member variable
  113.         parent::__construct();
  114.  
  115.         $this->mAppMenu = array();
  116.  
  117.         $this->mTimer $gBitTimer;
  118.         $this->mServerTimestamp new BitDate();
  119.  
  120.         $this->loadConfig();
  121.  
  122.         // Critical Preflight Checks
  123.         $this->checkEnvironment();
  124.  
  125.         $this->mRegisterCalled = FALSE;
  126.  
  127.         // Set the separator for PHP generated tags to be &amp; instead of &
  128.         // This is necessary for XHTML compliance
  129.         ini_set"arg_separator.output""&amp;" );
  130.         // Remove automatic quotes added to POST/COOKIE by PHP
  131.         ifget_magic_quotes_gpc() ) {
  132.             foreach$_REQUEST as $k => $v {
  133.                 if!is_array$_REQUEST[$k) ) {
  134.                     $_REQUEST[$kstripslashes$v );
  135.                 }
  136.             }
  137.         }
  138.  
  139.         $this->defineTempDir();
  140.  
  141.     }
  142.  
  143.     public static function loadFromCache$pCacheKey {
  144.         if$ret parent::loadFromCache$pCacheKey ) ) {
  145.             $ret->setHttpStatusHttpStatusCodes::HTTP_OK );
  146.             $ret->mTimer->start();
  147.             $ret->mOnload array();
  148.             $ret->mAppMenu array();
  149.             $ret->defineTempDir();
  150.         }
  151.         return $ret;
  152.     }
  153.  
  154.     
  155.  
  156.     /**
  157.      * Load all preferences and store them in $this->mConfig
  158.      *
  159.      * @param $pPackage optionally get preferences only for selected package
  160.      */
  161.     function loadConfig$pPackage NULL {
  162.         $queryVars array();
  163.         $whereClause '';
  164.  
  165.         if$pPackage {
  166.             array_push$queryVars$pPackage );
  167.             $whereClause ' WHERE `package`=? ';
  168.         }
  169.  
  170.         if empty$this->mConfig ) ) {
  171.             $this->mConfig = array();
  172.             $query "SELECT `config_name` ,`config_value`, `package` FROM `" BIT_DB_PREFIX "kernel_config` " $whereClause;
  173.             if$rs $this->mDb->query$query$queryVars-1-) ) {
  174.                 while$row $rs->fetchRow() ) {
  175.                     $this->mConfig[$row['config_name']] $row['config_value'];
  176.                 }
  177.             }
  178.         }
  179.         return count$this->mConfig );
  180.     }
  181.  
  182.     // <<< getConfig
  183.     /**
  184.      * Add getConfig / setConfig for more uniform handling of config variables instead of spreading global vars.
  185.      * easily get the value of any given preference stored in kernel_config
  186.      *
  187.      * @access public
  188.      ***/
  189.     function getConfig$pName$pDefault NULL {
  190.         ifempty$this->mConfig ) ) {
  191.             $this->loadConfig();
  192.         }
  193.         returnempty$this->mConfig[$pName$pDefault $this->mConfig[$pName);
  194.     }
  195.  
  196.     // <<< getConfigMatch
  197.     /**
  198.      * retreive a group of config variables
  199.      *
  200.      * @access public
  201.      ***/
  202.     function getConfigMatch$pPattern$pSelectValue="" {
  203.         ifempty$this->mConfig ) ) {
  204.             $this->loadConfig();
  205.         }
  206.  
  207.         $matching_keys preg_grep$pPatternarray_keys$this->mConfig ));
  208.         $new_array array();
  209.         foreach$matching_keys as $key=>$value {
  210.             if empty$pSelectValue || !empty$pSelectValue && $this->mConfig[$value== $pSelectValue )) {
  211.                 $new_array[$value$this->mConfig[$value];
  212.             }
  213.         }
  214.         return$new_array );
  215.     }
  216.  
  217.     /**
  218.      * storeConfigMatch set a group of config variables
  219.      *
  220.      * @param string $pPattern Perl regular expression
  221.      * @param string $pSelectValue only manipulate settings with this value set
  222.      * @param string $pNewValue New value that should be set for the matching settings (NULL will remove the entries from the DB)
  223.      * @param string $pPackage Package for which the settings are
  224.      * @access public
  225.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  226.      */
  227.     function storeConfigMatch$pPattern$pSelectValue ""$pNewValue NULL$pPackage NULL {
  228.         ifempty$this->mConfig ) ) {
  229.             $this->loadConfig();
  230.         }
  231.  
  232.         $matchingKeys preg_grep$pPatternarray_keys$this->mConfig ));
  233.         foreach$matchingKeys as $key => $config_name {
  234.             ifempty$pSelectValue || !empty$pSelectValue && $this->mConfig[$config_name== $pSelectValue )) {
  235.                 $this->storeConfig$config_name$pNewValue$pPackage );
  236.             }
  237.         }
  238.     }
  239.  
  240.     /**
  241.      * Set a hash value in the mConfig hash. This does *NOT* store the value in
  242.      * the database. It does no checking for existing or duplicate values. the
  243.      * main point of this function is to limit direct accessing of the mConfig
  244.      * hash. I will probably make mConfig private one day.
  245.      *
  246.      * @param string Hash key for the mConfig value
  247.      * @param string Value for the mConfig hash key
  248.      */
  249.     function setConfig$pName$pValue {
  250.         $this->mConfig[$pName$pValue;
  251.         returnTRUE );
  252.     }
  253.  
  254.     // <<< storeConfig
  255.     /**
  256.      * bitweaver needs lots of settings just to operate.
  257.      * loadConfig assigns itself the default preferences, then loads just the differences from the database.
  258.      * In storeConfig (and only when storeConfig is called) we make a second copy of defaults to see if
  259.      * preferences you are changing is different from the default.
  260.      * if it is the same, don't store it!
  261.      * So instead updating the whole prefs table, only updat "delta" of the changes delta from defaults.
  262.      *
  263.      * @access public
  264.      ***/
  265.     function storeConfig$pName$pValue$pPackage NULL {
  266.         global $gMultisites;
  267.         //stop undefined offset error being thrown after packages are installed
  268.         if!empty$this->mConfig )) {
  269.             // store the pref if we have a value _AND_ it is different from the default
  270.             if( ( empty$this->mConfig[$pName|| $this->mConfig[$pName!= $pValue ))) {
  271.                 // make sure the value doesn't exceede database limitations
  272.                 $pValue substr$pValue0250 );
  273.  
  274.                 // store the preference in multisites, if used
  275.                 if$this->isPackageActive'multisites' && @BitBase::verifyId$gMultisites->mMultisiteId && isset$gMultisites->mConfig[$pName)) {
  276.                     $query "UPDATE `".BIT_DB_PREFIX."multisite_preferences` SET `config_value`=? WHERE `multisite_id`=? AND `config_name`=?";
  277.                     $result $this->mDb->query$queryarrayempty$pValue '' $pValue$gMultisites->mMultisiteId$pName ) );
  278.                 else {
  279.                     $this->mDb->StartTrans();
  280.                     $query "DELETE FROM `".BIT_DB_PREFIX."kernel_config` WHERE `config_name`=?";
  281.                     $result $this->mDb->query$queryarray$pName ) );
  282.                     // make sure only non-empty values get saved, including '0'
  283.                     ifisset$pValue && !empty$pValue || is_numeric$pValue ))) {
  284.                         $query "INSERT INTO `".BIT_DB_PREFIX."kernel_config`(`config_name`,`config_value`,`package`) VALUES (?,?,?)";
  285.                         $result $this->mDb->query$queryarray$pName$pValuestrtolower$pPackage )));
  286.                     }
  287.                     $this->mDb->CompleteTrans();
  288.                 }
  289.  
  290.                 // Force the ADODB cache to flush
  291.                 $isCaching $this->mDb->isCachingActive();
  292.                 $this->mDb->setCachingFALSE );
  293.                 $this->loadConfig();
  294.                 $this->mDb->setCaching$isCaching );
  295.                 $this->clearFromCache();
  296.             }
  297.         }
  298.         $this->setConfig$pName$pValue );
  299.         return TRUE;
  300.     }
  301.  
  302.     // <<< expungePackageConfig
  303.     /**
  304.      * Delete all prefences for the given package
  305.      * @access public
  306.      ***/
  307.     function expungePackageConfig$pPackageName {
  308.         if!empty$pPackageName ) ) {
  309.             $query "DELETE FROM `".BIT_DB_PREFIX."kernel_config` WHERE `package`=?";
  310.             $result $this->mDb->query$queryarraystrtolower$pPackageName ) ) );
  311.             // let's force a reload of the prefs
  312.             unset$this->mConfig );
  313.             $this->loadConfig();
  314.         }
  315.     }
  316.  
  317.     // === hasValidSenderEmail
  318.     /**
  319.      * Determines if this site has a legitimate sender address set.
  320.      *
  321.      * @param  $mid the name of the template for the page content
  322.      * @access public
  323.      */
  324.     function hasValidSenderEmail$pSenderEmail=NULL {
  325.         ifempty$pSenderEmail ) ) {
  326.             $pSenderEmail $this->getConfig'site_sender_email' );
  327.         }
  328.         return!empty$pSenderEmail && !preg_match'/.*localhost$/'$pSenderEmail ) );
  329.     }
  330.  
  331.     // === getErrorEmail
  332.     /**
  333.      * Smartly determines where error emails should go
  334.      *
  335.      * @access public
  336.      */
  337.     function getErrorEmail({
  338.         ifdefined('ERROR_EMAIL') ) {
  339.             $ret ERROR_EMAIL;
  340.         elseif$this->getConfig'site_sender_email' ) ) {
  341.             $ret $this->getConfig'site_sender_email' );
  342.         elseif!empty$_SERVER['SERVER_ADMIN') ) {
  343.             $ret $_SERVER['SERVER_ADMIN'];
  344.         else {
  345.             $ret 'root@localhost';
  346.         }
  347.     }
  348.  
  349.     // === sendEmail
  350.     /**
  351.      * centralized function for send emails
  352.      *
  353.      * @param  $mid the name of the template for the page content
  354.      * @access public
  355.      */
  356.     function sendEmail$pMailHash {
  357.         $extraHeaders '';
  358.         if$this->getConfig'bcc_email' ) ) {
  359.             $extraHeaders "Bcc: ".$this->getConfig'bcc_email' )."\r\n";
  360.         }
  361.         if!empty$pMailHash['Reply-to') ) {
  362.             $extraHeaders "Reply-to: ".$pMailHash['Reply-to']."\r\n";
  363.         }
  364.  
  365.         $fromEmail !empty$pMailHash['from'$pMailHash['from'$this->getConfig'site_sender_email' );
  366.  
  367.         mail($pMailHash['email'],
  368.             $pMailHash['subject'].' '.$_SERVER["SERVER_NAME"],
  369.             $pMailHash['body'],
  370.             "From: ".$fromEmail."\r\nContent-type: text/plain;charset=utf-8\r\n$extraHeaders"
  371.         );
  372.     }
  373.  
  374.  
  375.     /**
  376.      * Set the http status, most notably for 404 not found for deleted content
  377.      *
  378.      * @param  $pHttpStatus numerical HTTP status, most typically 404 (not found) or 403 (forbidden)
  379.      * @access public
  380.      */
  381.     function setHttpStatus$pHttpStatus {
  382.         $this->mHttpStatus = $pHttpStatus;
  383.     }
  384.  
  385.  
  386.     public function outputHeader({
  387.         // see if we have a custom status other than 200 OK
  388.         header$_SERVER["SERVER_PROTOCOL"].' '.HttpStatusCodes::getMessageForCode$this->mHttpStatus ) );
  389.     }
  390.  
  391.     /**
  392.      * Display the main page template
  393.      *
  394.      * @param  $mid the name of the template for the page content
  395.      * @param  $browserTitle a string to be displayed in the top browser bar
  396.      * @param  $format the output format - xml, ajax, content, full - relays to setRenderFormat
  397.      * @access public
  398.      */
  399.     function display$pMid$pBrowserTitle NULL$pOptionsHash array() ) {
  400.         global $gBitSmarty$gBitThemes$gContent;
  401.         $gBitSmarty->verifyCompileDir();
  402.  
  403.         $this->outputHeader();
  404.         if$this->mHttpStatus != 200 {
  405. //            error_log( "HTTP/1.0 ".HttpStatusCodes::getMessageForCode( $this->mHttpStatus )." http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'] );
  406.         }
  407.  
  408.         // set the correct headers if it hasn't been done yet
  409.         ifempty$gBitThemes->mFormatHeader )) {
  410.             // display is the last thing we call and therefore we need to set a default
  411.             $gBitThemes->setFormatHeader!empty$pOptionsHash['format'$pOptionsHash['format''html' );
  412.         }
  413.  
  414.         // set the desired display mode - this lets bitweaver know what type of page we are viewing
  415.         ifempty$gBitThemes->mDisplayMode )) {
  416.             // display is the last thing we call and therefore we need to set a default
  417.             $gBitThemes->setDisplayMode!empty$pOptionsHash['display_mode'$pOptionsHash['display_mode''display' );
  418.         }
  419.  
  420.         if$pMid == 'error.tpl' {
  421.             $this->setBrowserTitle!empty$pBrowserTitle $pBrowserTitle tra'Error' ) );
  422.             $pMid 'bitpackage:kernel/error.tpl';
  423.         }
  424.  
  425.         // only using the default html header will print modules and all the rest of it.
  426.         if$gBitThemes->mFormatHeader != 'html' {
  427.             $gBitSmarty->display$pMid );
  428.             return;
  429.         }
  430.  
  431.         if!empty$pBrowserTitle )) {
  432.             $this->setBrowserTitle$pBrowserTitle );
  433.         }
  434.  
  435.         // populate meta description with something useful so you are not penalized/ignored by web crawlers
  436.         ifis_object$gContent && $gContent->isValid() ) {
  437.             if$summary $gContent->getField'summary' ) ) {
  438.                 $desc $gContent->parseData$summary );
  439.             elseif$desc $gContent->getField'parsed' ) ) {
  440.             elseif$summary $gContent->getField'data' ) ) {
  441.                 $desc $gContent->parseData$summary );
  442.             }
  443.             if!empty$desc ) ) {
  444.                 $desc preg_replace'/\s+/'' '$desc);  // $gContent->getContentTypeName().': '.
  445.                 $gBitSmarty->assign'metaDescription'substrstrip_tags$desc )0256 ) );
  446.             }
  447.         }
  448.  
  449.         $this->preDisplay$pMid );
  450.         $gBitSmarty->assign'mid'$pMid );
  451.         ifdefined'ROLE_MODEL' ) ) {
  452.             $gBitSmarty->assign'role_model'TRUE );
  453.         }
  454.         // Make sure that the gBitSystem symbol available to templates is correct and up-to-date.
  455.         print $gBitSmarty->fetch'bitpackage:kernel/html.tpl' );
  456.         $this->postDisplay$pMid );
  457.     }
  458.  
  459.  
  460.     // === preDisplay
  461.     /**
  462.      * Take care of any processing that needs to happen just before the template is displayed
  463.      *
  464.      * @param none 
  465.      * @access private
  466.      */
  467.     function preDisplay$pMid {
  468.         global $gCenterPieces$gBitSmarty$gBitThemes$gDefaultCenter;
  469.         if!defined'JSCALENDAR_PKG_URL' ) ) {
  470.             define'JSCALENDAR_PKG_URL'UTIL_PKG_URL.'javascript/libs/dynarch/jscalendar/' );
  471.         }
  472.  
  473.         $gBitThemes->loadLayout();
  474.  
  475.         // check to see if we are working with a dynamic center area
  476.         if$pMid == 'bitpackage:kernel/dynamic.tpl' {
  477.             $gBitSmarty->assign_by_ref'gCenterPieces'$gCenterPieces );
  478.         }
  479.  
  480.         $gBitThemes->preLoadStyle();
  481.  
  482.         /* @TODO - fetch module php files before rendering tpls.
  483.          * The basic problem here is center_list and module files are
  484.          * processed during page rendering, which means code in those
  485.          * files can not set <head> information before rendering. Kinda sucks.
  486.          *
  487.          * So what this does is, this calls on a service function allowing any
  488.          * package to check if its center or other module file is going to be
  489.          * called and gives it a chance to set any information for <head> first.
  490.          *
  491.          * Remove when TODO is complete. -wjames5
  492.          */
  493.         global $gBitUser;
  494.         ifisset$gBitUser )) {
  495.             //SMARTY3 $gBitUser->invokeServices( 'module_display_function' );
  496.         }
  497.  
  498.         // process layout
  499.         // SMARTY3 require_once( THEMES_PKG_PATH.'modules_inc.php' );
  500.  
  501.         $gBitThemes->loadStyle();
  502.  
  503.         /* force the session to close *before* displaying. Why? Note this very important comment from http://us4.php.net/exec
  504.             edwin at bit dot nl
  505.             23-Jan-2002 04:47
  506.                 If you are using sessions and want to start a background process, you might
  507.                 have the following problem:
  508.                 The first time you call your script everything goes fine, but when you call it again
  509.                 and the process is STILL running, your script seems to "freeze" until you kill the
  510.                 process you started the first time.
  511.  
  512.                 You'll have to call session_write_close(); to solve this problem. It has something
  513.                 to do with the fact that only one script/process can operate at once on a session.
  514.                 (others will be lockedout until the script finishes)
  515.  
  516.                 I don't know why it somehow seems to be influenced by background processes,
  517.                 but I tried everything and this is the only solution. (i had a perl script that
  518.                 "daemonized" it's self like the example in the perl manuals)
  519.  
  520.                 Took me a long time to figure out, thanks ian@virtisp.net! :-)
  521.  
  522.             ... and a similar issue can happen for very long display times.
  523.          */
  524.         session_write_close();
  525.     }
  526.  
  527.     // === postDisplay
  528.     /**
  529.      * Take care of any processing that needs to happen just after the template is displayed
  530.      *
  531.      * @param none 
  532.      * @access private
  533.      */
  534.     function postDisplay$pMid {
  535.     }
  536.  
  537.     // === setHelpInfo
  538.     /**
  539.      * Set the smarty variables needed to display the help link for a page.
  540.      *
  541.      * @param  $package Package Name
  542.      * @param  $context Context of the help within the package
  543.      * @param  $desc Description of the help link (not the help itself)
  544.      * @access private
  545.      */
  546.     function setHelpInfo$package$context$desc {
  547.         global $gBitSmarty;
  548.         $gBitSmarty->assign'TikiHelpInfo'array'URL' => 'http://doc.bitweaver.org/wiki/index.php?page=' $package $context 'Desc' => $desc ) );
  549.     }
  550.  
  551.     // === getPackageStatus
  552.     /**
  553.      * find out a packages installation status
  554.      * @param $pPackageName the name of the package to test
  555.      *         where the package name is in the form used to index $mPackages
  556.      * @return char where
  557.      *               'i' is installed but not active
  558.      *               'y' is installed and active
  559.      *               'n' is not installed
  560.      * @access public
  561.      */
  562.     function getPackageStatus$pPackageName {
  563.  
  564.         // A package is installed if
  565.         //    $this->getConfig('package_'.$name) == 'i'
  566.         // or $this->getConfig('package_'.$name) == 'y'
  567.         //
  568.         // A package is installed and active if
  569.         //     <package name>_PKG_NAME is defined
  570.         // and $this->getConfig('package_'.$name) == 'y'
  571.  
  572.         $ret 'n';
  573.         ifdefinedstrtoupper$pPackageName ).'_PKG_NAME' ) ) {
  574.             if$name strtolower@constant(( strtoupper$pPackageName ).'_PKG_NAME' )))) {
  575.                 // kernel always active
  576.                 if$name == 'kernel' {
  577.                     $ret 'y';
  578.                 else {
  579.                     // we have migrated the old tikiwiki feature_<pac
  580.                     $ret $this->getConfig'package_'.$name'n' );
  581.                 }
  582.             }
  583.         }
  584.  
  585.         return$ret );
  586.     }
  587.  
  588.     // === isPackageActive
  589.     /**
  590.      * check's if a package is active.
  591.      * @param $pPackageName the name of the package to test
  592.      *         where the package name is in the form used to index $mPackages
  593.      *         See comments in scanPackages for more information
  594.      * @return boolean 
  595.      * @access public
  596.      */
  597.     function isPackageActive$pPackageName {
  598.  
  599.         return$this->getPackageStatus$pPackageName == 'y' );
  600.     }
  601.  
  602.     // === isPackageActiveEarly
  603.     /**
  604.      * check if a package is active; but only do this after making sure a package
  605.      * has had it's bit_setup_inc loaded if possible.  This func exists for use in
  606.      * other packages bit_setup_inc's to avoid dependency on load order and ugly code
  607.      * @param $pPackageName the name of the package to test
  608.      *         where the package name is in the form used to index $mPackages
  609.      *         See comments in scanPackages for more information
  610.      * @return boolean 
  611.      * @access public
  612.      */
  613.     function isPackageActiveEarly$pPackageName {
  614.  
  615.         $ret FALSE;
  616.         $pkgname_l strtolower$pPackageName );
  617.         ifis_file(BIT_ROOT_PATH.$pkgname_l.'/bit_setup_inc.php') ) {
  618.             require_once(BIT_ROOT_PATH.$pkgname_l.'/bit_setup_inc.php');
  619.             $ret $this->isPackageActive$pPackageName );
  620.         elseif$pkgname_l == 'kernel' {
  621.             $ret TRUE;
  622.         }
  623.  
  624.         return$ret );
  625.     }
  626.  
  627.     // === isPackageInstalled
  628.     /**
  629.      * check's if a package is Installed
  630.      * @param $pPackageName the name of the package to test
  631.      *         where the package name is in the form used to index $mPackages
  632.      *         See comments in scanPackages for more information
  633.      * @return boolean 
  634.      * @access public
  635.      */
  636.     function isPackageInstalled$pPackageName {
  637.  
  638.         $pkgstatus $this->getPackageStatus$pPackageName );
  639.  
  640.         return( ( $pkgstatus == 'y' || $pkgstatus == 'i' ) );
  641.     }
  642.  
  643.     // === verifyPackage
  644.     /**
  645.      * It will verify that the given package is active or it will display the error template and die()
  646.      * @param $pPackageName the name of the package to test
  647.      *         where the package name is in the form used to index $mPackages
  648.      *         See comments in scanPackages for more information
  649.      * @return boolean 
  650.      * @access public
  651.      */
  652.     function verifyPackage$pPackageName {
  653.         if!$this->isPackageActive$pPackageName ) ) {
  654.             $this->fatalErrortra("This package is disabled").": package_$pPackageName);
  655.         }
  656.  
  657.         returnTRUE );
  658.     }
  659.  
  660.     // === getPermissionInfo
  661.     /**
  662.      * It will get information about a permissions
  663.      * @param $pPermission value of a given permission
  664.      * @return none 
  665.      * @access public
  666.      */
  667.     function getPermissionInfo$pPermission NULL$pPackageName NULL {
  668.         $ret NULL;
  669.         $bindVars array();
  670.         $sql 'SELECT * FROM `'.BIT_DB_PREFIX.'users_permissions` ';
  671.         if!empty$pPermission ) ) {
  672.             $sql .= ' WHERE `perm_name`=? ';
  673.             array_push$bindVars$pPermission );
  674.         elseif!empty$pPackageName ) ) {
  675.             $sql .= ' WHERE `package` = ? ';
  676.             array_push$bindVarssubstr($pPackageName,0,100));
  677.         }
  678.         $ret $this->mDb->getAssoc$sql$bindVars );
  679.         return $ret;
  680.     }
  681.  
  682.     // === verifyPermission
  683.     /**
  684.      * DEPRECATED - this function has been moved into BitPermUser, use that
  685.      */
  686.     function verifyPermission$pPermission$pMsg NULL {
  687.         global $gBitUser;
  688.         return $gBitUser->verifyPermission$pPermission$pMsg );
  689.     }
  690.  
  691.     // === fatalPermission
  692.     /**
  693.      * Interupt code execution and show a permission denied message.
  694.      * This does not show a big nasty denied message if user is simply not logged in.
  695.      * This *could* lead to a user seeing a denied message twice, however this is
  696.      * unlikely as logic permission checks should prevent access to non-permed page REQUEST in the first place
  697.      * @param $pPermission value of a given permission
  698.      * @param $pMsg optional additional information to present to user
  699.      * @return none 
  700.      * @access public
  701.      */
  702.     function fatalPermission$pPermission$pMsg=NULL {
  703.         global $gBitUser$gBitSmarty$gBitThemes;
  704.         if!$gBitUser->isRegistered() ) {
  705.             $gBitSmarty->assign'template''bitpackage:users/login_inc.tpl' );
  706.         else {
  707.             $title 'Oops!';
  708.             ifempty$pMsg ) ) {
  709.                 $pMsg $this->getPermissionDeniedMessage$pPermission );
  710.             }
  711.             $gBitSmarty->assign'fatalTitle'tra"Permission denied." ) );
  712.         }
  713. // bit_error_log( "PERMISSION DENIED: $pPermission $pMsg" );
  714.         $gBitSmarty->assign'msg'tra$pMsg ) );
  715.         $this->setHttpStatusHttpStatusCodes::HTTP_NOT_FOUND );
  716.         $this->display"error.tpl" );
  717.         die;
  718.     }
  719.  
  720.     function getPermissionDeniedMessage$pPermission {
  721.         $permDesc $this->getPermissionInfo$pPermission );
  722.         $ret "You do not have the required permissions";
  723.         if!empty$permDesc[$pPermission]['perm_desc') ) {
  724.             ifpreg_match'/administrator,/i'$permDesc[$pPermission]['perm_desc') ) {
  725.                 $ret .= preg_replace'/^administrator, can/i'' to '$permDesc[$pPermission]['perm_desc');
  726.             else {
  727.                 $ret .= preg_replace'/^can /i'' to '$permDesc[$pPermission]['perm_desc');
  728.             }
  729.         }
  730.         return $ret;
  731.     }
  732.  
  733.     /**
  734.      * This code was duplicated _EVERYWHERE_ so here is an easy template to cut that down.
  735.      * @param $pFormHash documentation needed
  736.      * @param $pMsg documentation needed
  737.      * @return none 
  738.      * @access public
  739.      */
  740.     function confirmDialog$pFormHash$pMsg {
  741.         global $gBitSmarty;
  742.         if!empty$pMsg ) ) {
  743.             $pageTitle self::getParameter$pMsg'label''Please Confirm' );
  744.             ifempty$pParamHash['cancel_url') ) {
  745.                 $gBitSmarty->assign'backJavascript''onclick="history.back();"' );
  746.             }
  747.             if!empty$pFormHash['input') ) {
  748.                 $gBitSmarty->assign'inputFields'$pFormHash['input');
  749.                 unset$pFormHash['input');
  750.             }
  751.             $gBitSmarty->assign'msgFields'$pMsg );
  752.             $gBitSmarty->assign_by_ref'hiddenFields'$pFormHash );
  753.             $this->display'bitpackage:kernel/confirm.tpl'$pageTitlearray'display_mode' => 'edit' ));
  754.             die;
  755.         }
  756.     }
  757.  
  758.     // === isFeatureActive
  759.     /**
  760.      * check's if the specfied feature is active
  761.      *
  762.      * @param  $pKey hash key
  763.      * @return none 
  764.      * @access public
  765.      */
  766.     function isFeatureActive$pFeatureName {
  767.         $ret FALSE;
  768.         if$pFeatureName {
  769.             $featureValue $this->getConfig($pFeatureName);
  770.             $ret !empty$featureValue && $featureValue != 'n' );
  771.         }
  772.  
  773.         return$ret );
  774.     }
  775.  
  776.     // === verifyFeature
  777.     /**
  778.      * It will verify that the given feature is active or it will display the error template and die()
  779.      * @param $pFeatureName the name of the package to test
  780.      * @return none 
  781.      * @access public
  782.      *
  783.      * @param  $pKey hash key
  784.      */
  785.     function verifyFeature$pFeatureName {
  786.         if!$this->isFeatureActive$pFeatureName ) ) {
  787.             $this->fatalErrortra("This feature is disabled")."$pFeatureName);
  788.         }
  789.  
  790.         returnTRUE );
  791.     }
  792.  
  793.     // === registerPackage
  794.     /**
  795.      * Define name, location and url DEFINE's
  796.      *
  797.      * @param  $pKey hash key
  798.      * @return none 
  799.      * @access public
  800.      */
  801.     function registerPackage$pRegisterHash {
  802.         if!isset$pRegisterHash['package_name')) {
  803.             $this->fatalErrortra("Package name not set in ")."registerPackage: $this->mPackageFileName" );;
  804.         else {
  805.             $name $pRegisterHash['package_name'];
  806.         }
  807.  
  808.         if!isset$pRegisterHash['package_path')) {
  809.             $this->fatalErrortra("Package path not set in ")."registerPackage: $this->mPackageFileName" );;
  810.         else {
  811.             $path $pRegisterHash['package_path'];
  812.         }
  813.  
  814.         $this->mRegisterCalled = TRUE;
  815.         ifempty$this->mPackages )) {
  816.             $this->mPackages = array();
  817.         }
  818.         $pkgName str_replace' ''_'strtoupper$name ));
  819.         $pkgNameKey strtolower$pkgName );
  820.  
  821.         // Some package settings
  822.         $this->mPackages[$pkgNameKey]['homeable'!empty$pRegisterHash['homeable');
  823.         $this->mPackages[$pkgNameKey]['required'!empty$pRegisterHash['required_package');
  824.         $this->mPackages[$pkgNameKey]['service']  !empty$pRegisterHash['service'$pRegisterHash['service'FALSE;
  825.         $this->mPackages[$pkgNameKey]['status']   $this->getConfig'package_'.$pkgNameKey'n');
  826.  
  827.         # y = Active
  828.         # i = Installed
  829.         # n (or empty/null) = Not Active and Not Installed
  830.  
  831.         // set package installed and active flag
  832.         if$this->mPackages[$pkgNameKey]['status'== 'a' || $this->mPackages[$pkgNameKey]['status'== 'y' {
  833.             $this->mPackages[$pkgNameKey]['active_switch'TRUE;
  834.         else {
  835.             $this->mPackages[$pkgNameKey]['active_switch'FALSE;
  836.         }
  837.  
  838.         // set package installed flag (can be installed but not active)
  839.         if$this->mPackages[$pkgNameKey]['active_switch'|| $this->mPackages[$pkgNameKey]['status'== 'i' {
  840.             $this->mPackages[$pkgNameKey]['installed'TRUE;
  841.         else {
  842.             $this->mPackages[$pkgNameKey]['installed'FALSE;
  843.         }
  844.  
  845.         // Define <PACKAGE>_PKG_PATH
  846.         $pkgDefine $pkgName.'_PKG_PATH';
  847.         if!defined$pkgDefine )) {
  848.             define$pkgDefineBIT_ROOT_PATH basename$path '/' );
  849.         }
  850.         $this->mPackages[$pkgNameKey]['url']  BIT_ROOT_URL basename$path '/';
  851.         $this->mPackages[$pkgNameKey]['path']  BIT_ROOT_PATH basename$path '/';
  852.  
  853.         // Define <PACKAGE>_PKG_URL
  854.         $pkgDefine $pkgName.'_PKG_URL';
  855.         if!defined$pkgDefine )) {
  856.             // Force full URI's for offline or exported content (newsletters, etc.)
  857.             $root !empty$_REQUEST['uri_mode'BIT_BASE_URI BIT_ROOT_URL BIT_ROOT_URL;
  858.             define$pkgDefine$root basename$path '/' );
  859.         }
  860.  
  861.         // Define <PACKAGE>_PKG_URI
  862.         $pkgDefine $pkgName.'_PKG_URI';
  863.         if!defined$pkgDefine && defined'BIT_BASE_URI' )) {
  864.             define$pkgDefineBIT_BASE_URI BIT_ROOT_URL basename$path '/' );
  865.         }
  866.  
  867.         // Define <PACKAGE>_PKG_NAME
  868.         $pkgDefine $pkgName.'_PKG_NAME';
  869.         if!defined$pkgDefine )) {
  870.             define$pkgDefine$name );
  871.             $this->mPackages[$pkgNameKey]['activatable']  = isset$pRegisterHash['activatable'$pRegisterHash['activatable'TRUE;
  872.         }
  873.         $this->mPackages[$pkgNameKey]['name'$name;
  874.  
  875.         // Define <PACKAGE>_PKG_DIR
  876.         $package_dir_name basename$path );
  877.         $pkgDefine $pkgName.'_PKG_DIR';
  878.         if!defined$pkgDefine )) {
  879.             define$pkgDefine$package_dir_name );
  880.         }
  881.         $this->mPackages[$pkgNameKey]['dir'$package_dir_name;
  882.         $this->mPackagesDirNameXref[$package_dir_name$pkgNameKey;
  883.  
  884.         // Define <PACKAGE>_PKG_TITLE
  885.         $pkgDefine $pkgName.'_PKG_TITLE';
  886.         if!defined$pkgDefine )) {
  887.             define$pkgDefineucfirstconstant$pkgName.'_PKG_DIR' ) ) );
  888.         }
  889.         $this->mPackages[$pkgNameKey]['dir'$package_dir_name;
  890.  
  891.         // Work around for old versions of IIS that do not support $_SERVER['SCRIPT_FILENAME'] - wolff_borg
  892.         if!array_key_exists'SCRIPT_FILENAME'$_SERVER )) {
  893.             //remove double-backslashes and return
  894.             $_SERVER['SCRIPT_FILENAME'=  str_replace('\\\\''\\'$_SERVER['PATH_TRANSLATED');
  895.         }
  896.  
  897.         // Define the package we are currently in
  898.         // I tried strpos instead of preg_match here, but it didn't like strings that begin with slash?! - spiderr
  899.         $scriptDir basenamedirname$_SERVER['SCRIPT_FILENAME') ) );
  900.         if!defined'ACTIVE_PACKAGE' && $scriptDir == constant$pkgName.'_PKG_DIR' || isset$_SERVER['ACTIVE_PACKAGE'|| preg_match'!/'.$this->mPackages[$pkgNameKey]['dir'].'/!'$_SERVER['SCRIPT_NAME'|| preg_match'!/'.$pkgNameKey.'/!'$_SERVER['SCRIPT_NAME'))) {
  901.             ifisset$_SERVER['ACTIVE_PACKAGE')) {
  902.                 // perhaps the webserver told us the active package (probably because of mod_rewrites)
  903.                 $pkgNameKey $_SERVER['ACTIVE_PACKAGE'];
  904.             }
  905.             define'ACTIVE_PACKAGE'$pkgNameKey );
  906.             $this->mActivePackage = $pkgNameKey;
  907.         }
  908.     }
  909.  
  910.     // === registerAppMenu
  911.     /**
  912.      * Register global system menu. Due to the startup nature of this method, it need to belong in BitSystem instead of BitThemes, where it would more naturally fit.
  913.      *
  914.      * @param  $pKey hash key
  915.      * @return none 
  916.      * @access public
  917.      */
  918.     function registerAppMenu$pMenuHash$pMenuTitle NULL$pTitleUrl NULL$pMenuTemplate NULL$pAdminPanel FALSE {
  919.         $menuType (!empty$pMenuHash['menu_type'$pMenuHash['menu_type''bar');
  920.         ifis_array$pMenuHash ) ) {
  921.             // shorthand
  922.             $pkg $pMenuHash['package_name'];
  923.  
  924.             // prepare hash
  925.             $pMenuHash['style']       'display:'.( ( isset$_COOKIE[$pkg.'menu'&& $_COOKIE[$pkg.'menu'== 'o' ) ) 'block;' 'none;' );
  926.             $pMenuHash['is_disabled'$this->getConfig'menu_'.$pkg == 'n' );
  927.             $pMenuHash['menu_title']  $this->getConfig$pkg.'_menu_text',
  928.                 !empty$pMenuHash['menu_title')
  929.                 ? $pMenuHash['menu_title']
  930.                 : ucfirstconstantstrtoupper$pkg ).'_PKG_DIR' )))
  931.             );
  932.             $pMenuHash['menu_position'$this->getConfig$pkg.'_menu_position',
  933.                 !empty$pMenuHash['menu_position')
  934.                 ? $pMenuHash['menu_position']
  935.                 : NULL )
  936.             );
  937.  
  938.             $this->mAppMenu[$menuType][$pkg$pMenuHash;
  939.         else {
  940.             deprecated'Please use a menu registration hash instead of individual parameters: $gBitSystem->registerAppMenu( $menuHash )' );
  941.             $this->mAppMenu[$menuType][strtolower$pMenuHash )array(
  942.                 'menu_title'    => $pMenuTitle,
  943.                 'is_disabled'   => $this->getConfig'menu_'.$pMenuHash == 'n' ),
  944.                 'index_url'     => $pTitleUrl,
  945.                 'menu_template' => $pMenuTemplate,
  946.                 'admin_panel'   => $pAdminPanel,
  947.                 'style'         => 'display:'.empty$pMenuTitle || isset$_COOKIE[$pMenuHash.'menu'&& $_COOKIE[$pMenuHash.'menu'== 'o' ) ) 'block;' 'none;' )
  948.             );
  949.         }
  950.         uasort$this->mAppMenu[$menuType]'bit_system_menu_sort' );
  951.     }
  952.  
  953.     /**
  954.      * registerNotifyEvent
  955.      *
  956.      * @param array $pEventHash 
  957.      * @access public
  958.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  959.      */
  960.     function registerNotifyEvent$pEventHash {
  961.         $this->mNotifyEvents = array_merge$this->mNotifyEvents$pEventHash );
  962.     }
  963.  
  964.     // === fatalError
  965.     /**
  966.      * If an unrecoverable error has occurred, this method should be invoked. script exist occurs
  967.      *
  968.      * @param string pMsg error message to be displayed
  969.      * @param string template file used to display error
  970.      * @param string error dialog title. default gets site_error_title config, passing '' will result in no title
  971.      * @return none this function will DIE DIE DIE!!!
  972.      * @access public
  973.      */
  974.     function fatalError$pMsg$pTemplate=NULL$pErrorTitle=NULL$pHttpStatus 200  {
  975.         global $gBitSmarty$gBitThemes;
  976.         ifis_null$pErrorTitle ) ) {
  977.             $pErrorTitle $this->getConfig'site_error_title''' );
  978.         }
  979.  
  980.         ifempty$pTemplate ) ) {
  981.             $pTemplate 'error.tpl';
  982.         }
  983.  
  984.         $gBitSmarty->assign'fatalTitle'tra$pErrorTitle ) );
  985.         $gBitSmarty->assign'msg'$pMsg );
  986.         // if mHttpStatus is set, we can assume this was an expected fatal, such as a 404 or 403
  987.         if!isset$this->mHttpStatus ) ) {
  988.             error_log"Fatal Error: $pMsg http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI');
  989.         }
  990.  
  991.         $this->setHttpStatus$pHttpStatus );
  992.         if$gBitThemes->isAjaxRequest() ) {
  993.             $gBitSmarty->display'bitpackage:kernel/'.$pTemplate );
  994.         else {
  995.             $gBitSmarty->assign'metaNoIndex');
  996.             $this->display$pTemplate );
  997.         }
  998.         die;
  999.     }
  1000.  
  1001.     // === loadPackage
  1002.     /**
  1003.      * Loads a package
  1004.      *
  1005.      * @param string pkgDir = Directory Name of package to load
  1006.      * @param string pScanFile file to be looked for
  1007.      * @param string autoRegister - TRUE = autoregister any packages that don't register on their own, FALSE = don't
  1008.      * @param string pOnce - TRUE = do include_once to load file FALSE = do include to load the file
  1009.      * @return none 
  1010.      * @access public
  1011.      */
  1012.     function loadPackage$pPkgDir$pScanFile$pAutoRegister=TRUE$pOnce=TRUE {
  1013.         #check if already loaded, loading again won't work with 'include_once' since
  1014.         #no register call will be done, so don't auto register.
  1015.         if$pAutoRegister && !empty$this->mPackagesDirNameXref[$pPkgDir) ) {
  1016.             $pAutoRegister FALSE;
  1017.         }
  1018.  
  1019.         $this->mRegisterCalled = FALSE;
  1020.         $scanFile BIT_ROOT_PATH.$pPkgDir.'/'.$pScanFile;
  1021.         $file_exists 0;
  1022.  
  1023.         iffile_exists$scanFile ) ) {
  1024.             $file_exists 1;
  1025.             global $gBitSystem$gLibertySystem$gBitSmarty$gBitUser$gBitLanguage;
  1026.             $this->mPackageFileName = $scanFile;
  1027.             if$pOnce {
  1028.                 include_once$scanFile );
  1029.             else {
  1030.                 include$scanFile );
  1031.             }
  1032.         }
  1033.  
  1034.         if( ( $file_exists || $pPkgDir == 'kernel' && $pAutoRegister && !$this->mRegisterCalled ) ) {
  1035.             $registerHash array(
  1036.                 #for auto registered packages Registration Package Name = Package Directory Name
  1037.                 'package_name' => $pPkgDir,
  1038.                 'package_path' => BIT_ROOT_PATH.$pPkgDir.'/',
  1039.                 'activatable' => FALSE,
  1040.             );
  1041.             if$pPkgDir == 'kernel' {
  1042.                 $registerHash array_merge$registerHasharray'required_package'=>TRUE ) );
  1043.             }
  1044.             $this->registerPackage$registerHash );
  1045.         }
  1046.     }
  1047.  
  1048.     // === scanPackages
  1049.     /**
  1050.      *
  1051.      * scan all available packages. This is an *expensive* function. DO NOT call this functionally regularly , or arbitrarily. Failure to comply is punishable by death by jello suffication!
  1052.      *
  1053.      * @param string pScanFile file to be looked for
  1054.      * @param string pOnce - TRUE = do include_once to load file FALSE = do include to load the file
  1055.      * @param string pSelect - empty or 'all' = load all packages, 'installed' = load installed, 'active' = load active, 'x' = load packages with status x
  1056.      * @param string autoRegister - TRUE = autoregister any packages that don't register on their own, FALSE = don't
  1057.      * @param string fileSystemScan - TRUE = scan file system for packages to load, False = don't
  1058.      * @return none 
  1059.      *
  1060.      *  Packages have three different names:
  1061.      *     The directory name where they reside on disk
  1062.      *     The Name they register themselves as when they call registerPackage
  1063.      *     The Key for the array $this->mPackages
  1064.      *
  1065.      *  Example:
  1066.      *     A package in directory 'stars' that registers itself with a name of 'Star Ratings'
  1067.      *     would have these three names:
  1068.      *
  1069.      *     Directory Name: 'stars'
  1070.      *     Registered Name: Star Ratings'
  1071.      *     $this->mPackages key: 'star_ratings'
  1072.      *
  1073.      *     Of course, its possible for all three names to be the same if the registered name
  1074.      *     is all lower case without spaces and is the same as the diretory name.
  1075.      *
  1076.      *     Functions that expect a package name as a parameter should make clear which form
  1077.      *     of the name they expect.
  1078.      *
  1079.      * @access public
  1080.      */
  1081.     function scanPackages$pScanFile 'bit_setup_inc.php'$pOnce=TRUE$pSelect=''$pAutoRegister=TRUE {
  1082.         global $gPreScan;
  1083.         if!empty$gPreScan && is_array$gPreScan )) {
  1084.             // gPreScan may hold a list of packages that must be loaded first
  1085.             foreach$gPreScan as $pkgDir {
  1086.                 $loadPkgs[$pkgDir;
  1087.             }
  1088.         }
  1089.  
  1090.         // load lib configs
  1091.         if$pkgDir opendirBIT_ROOT_PATH )) {
  1092.             whileFALSE !== $dirName readdir$pkgDir ))) {
  1093.                 if$dirName != '..'  && $dirName != '.' && is_dirBIT_ROOT_PATH '/' $dirName && $dirName != 'CVS' && preg_match'/^\w/'$dirName )) {
  1094.                     $loadPkgs[$dirName;
  1095.                 }
  1096.             }
  1097.         }
  1098.         $loadPkgs array_unique$loadPkgs );
  1099.  
  1100.         // load the list of pkgs in the right order
  1101.         foreach$loadPkgs as $loadPkg {
  1102.             $this->loadPackage$loadPkg$pScanFile$pAutoRegister$pOnce );
  1103.         }
  1104.  
  1105.         if!defined'BIT_STYLES_PATH' && defined'THEMES_PKG_PATH' )) {
  1106.             define'BIT_STYLES_PATH'THEMES_PKG_PATH.'styles/' );
  1107.         }
  1108.  
  1109.         if!defined'BIT_STYLES_URL' && defined'THEMES_PKG_URL' )) {
  1110.             define'BIT_STYLES_URL'THEMES_PKG_URL.'styles/' );
  1111.         }
  1112.     }
  1113.  
  1114.     /**
  1115.      * getDefaultPage
  1116.      *
  1117.      * @access public
  1118.      * @return URL of site homepage
  1119.      */
  1120.     function getDefaultPage({
  1121.         return $this->getIndexPage$this->getConfig"bit_index" ) );
  1122.     }
  1123.  
  1124.     /**
  1125.      * getIndexPage
  1126.      *
  1127.      * Returns the page for the given type
  1128.      * defaults to the site homepage
  1129.      *
  1130.      * @access public
  1131.      * @return URL of page by index type
  1132.      */
  1133.     function getIndexPage$pIndexType NULL ){
  1134.         global $userlib$gBitUser$gBitSystem;
  1135.         $pIndexType !is_null$pIndexType )$pIndexType $this->getConfig"bit_index" );
  1136.         $url '';
  1137.         if$pIndexType == 'role_home'{
  1138.             // See if we have first a user assigned default group id, and second a group default system preference
  1139.             if!$gBitUser->isRegistered(&& $role_home $gBitUser->getHomeRoleANONYMOUS_TEAM_ID ))) {
  1140.             elseif@$this->verifyId$gBitUser->mInfo['default_role_id'&& $role_home $gBitUser->getHomeRole$gBitUser->mInfo['default_role_id'))) {
  1141.             elseif$this->getConfig'default_home_role' && $role_home $gBitUser->getHomeRole$this->getConfig'default_home_role' )))) {
  1142.             }
  1143.  
  1144.             if!empty$role_home )) {
  1145.                 if$this->verifyId$role_home ) ) {
  1146.                     $url BIT_ROOT_URL."index.php".!empty$role_home "?content_id=".$role_home "" );
  1147.                 // wiki dependence - NO bad idea
  1148.                 // } elseif( strpos( $group_home, '/' ) === FALSE ) {
  1149.                 //     $url = BitPage::getDisplayUrl( $group_home );
  1150.                 elseif(  strpos$role_home'http://' === FALSE ){
  1151.                     $url BIT_ROOT_URL.$role_home;
  1152.                 else {
  1153.                     $url $role_home;
  1154.                 }
  1155.             }
  1156.         elseif$pIndexType == 'group_home'{
  1157.             // See if we have first a user assigned default group id, and second a group default system preference
  1158.             if!$gBitUser->isRegistered(&& $group_home $gBitUser->getGroupHomeANONYMOUS_GROUP_ID ))) {
  1159.             elseif@$this->verifyId$gBitUser->mInfo['default_group_id'&& $group_home $gBitUser->getGroupHome$gBitUser->mInfo['default_group_id'))) {
  1160.             elseif$this->getConfig'default_home_group' && $group_home $gBitUser->getGroupHome$this->getConfig'default_home_group' )))) {
  1161.             }
  1162.  
  1163.             if!empty$group_home )) {
  1164.                 if$this->verifyId$group_home ) ) {
  1165.                     $url BIT_ROOT_URL."index.php".!empty$group_home "?content_id=".$group_home "" );
  1166.                 // wiki dependence - NO bad idea
  1167.                 // } elseif( strpos( $group_home, '/' ) === FALSE ) {
  1168.                 //     $url = BitPage::getDisplayUrl( $group_home );
  1169.                 elseif(  strpos$group_home'http://' === FALSE ){
  1170.                     $url BIT_ROOT_URL.$group_home;
  1171.                 else {
  1172.                     $url $group_home;
  1173.                 }
  1174.             }
  1175.         elseif$pIndexType == 'my_page' || $pIndexType == 'my_home' || $pIndexType == 'user_home'  {
  1176.             // TODO: my_home is deprecated, but was the default for BWR1. remove in DILLINGER - spiderr
  1177.             if$gBitUser->isRegistered() ) {
  1178.                 if!$gBitUser->isRegistered() ) {
  1179.                     $url USERS_PKG_URL.'login.php';
  1180.                 else {
  1181.                     if$pIndexType == 'my_page' {
  1182.                         $url $gBitSystem->getConfig'users_login_homepage'USERS_PKG_URL.'my.php' );
  1183.                         if$url != USERS_PKG_URL.'my.php' && strpos$url'http://' === FALSE ){
  1184.                             // the safe assumption is that a custom path is a subpath of the site
  1185.                             // append the root url unless we have a fully qualified uri
  1186.                             $url BIT_ROOT_URL.$url;
  1187.                         }
  1188.                     elseif$pIndexType == 'user_home' {
  1189.                         $url $gBitUser->getDisplayUrl();
  1190.                     else {
  1191.                         $users_homepage $gBitUser->getPreference'users_homepage' );
  1192.                         ifisset$users_homepage && !empty$users_homepage )) {
  1193.                             ifstrpos($users_homepage'/'=== FALSE {
  1194.                                 $url BitPage::getDisplayUrlFromHasharray'title' => $users_homepage ) );
  1195.                             else {
  1196.                                 $url $users_homepage;
  1197.                             }
  1198.                         }
  1199.                     }
  1200.                 }
  1201.             else {
  1202.                 $url USERS_PKG_URL 'login.php';
  1203.             }
  1204.         elseifin_array$pIndexTypearray_keys$gBitSystem->mPackages ) ) ) {
  1205.             $work strtoupper$pIndexType ).'_PKG_URL';
  1206.             if (defined("$work")) {
  1207.                 $url constant$work );
  1208.             }
  1209.  
  1210.             /* this was commented out with the note that this can send requests to inactive packages -
  1211.              * that should only happen if the admin chooses to point to an inactive pacakge.
  1212.              * commenting this out however completely breaks the custom uri home page feature, so its
  1213.              * turned back on and caviate admin - if the problem is more severe than it seems then
  1214.              * get in touch on irc and we'll work out a better solution than commenting things on and off -wjames5
  1215.              */
  1216.         elseif!empty$pIndexType ) ) {
  1217.             $url BIT_ROOT_URL.$pIndexType;
  1218.         }
  1219.  
  1220.         // if no special case was matched above, default to users' my page
  1221.         ifempty$url ) ) {
  1222.             if$this->isPackageActive'wiki' ) ) {
  1223.                 $url WIKI_PKG_URL;
  1224.             elseif!$gBitUser->isRegistered() ) {
  1225.                 $url USERS_PKG_URL 'login.php';
  1226.             else {
  1227.                 $url USERS_PKG_URL 'my.php';
  1228.             }
  1229.         }
  1230.  
  1231.         ifstrpos$url'http://' === FALSE {
  1232.             $url preg_replace"#//#""/"$url );
  1233.         }
  1234.  
  1235.         return $url;
  1236.     }
  1237.     // === setOnloadScript
  1238.     /**
  1239.      * add javascript to the <body onload> attribute
  1240.      *
  1241.      * @param string $pJavascript javascript to be added
  1242.      * @return none 
  1243.      * @access public
  1244.      */
  1245.     function setOnloadScript$pJavscript {
  1246.         array_push$this->mOnload$pJavscript );
  1247.     }
  1248.     // === setOnunloadScript
  1249.     /**
  1250.      * add javascript to the <body onunload> attribute
  1251.      *
  1252.      * @param string $pJavascript javascript to be added
  1253.      * @return none 
  1254.      * @access public
  1255.      */
  1256.     function setOnunloadScript$pJavscript {
  1257.         array_push$this->mOnunload$pJavscript );
  1258.     }
  1259.     // === getBrowserTitle
  1260.     /**
  1261.      * get the title of the browser
  1262.      *
  1263.      * @return title string
  1264.      * @access public
  1265.      */
  1266.     function getBrowserTitle({
  1267.         global $gPageTitle;
  1268.         return$gPageTitle );
  1269.     }
  1270.  
  1271.     // === setBrowserTitle
  1272.     /**
  1273.      * set the title of the browser
  1274.      *
  1275.      * @param string pTitle title to be used
  1276.      * @return none 
  1277.      * @access public
  1278.      */
  1279.     function setBrowserTitle$pTitle {
  1280.         global $gBitSmarty$gPageTitle;
  1281.         $gPageTitle $pTitle;
  1282.         $gBitSmarty->assign'browserTitle'$pTitle );
  1283.         $gBitSmarty->assign'gPageTitle'$pTitle );
  1284.     }
  1285.  
  1286.     // === setCanonicalLink
  1287.     /**
  1288.      * set the canonical page title
  1289.      *
  1290.      * @param string pTitle title to be used
  1291.      * @return none 
  1292.      * @access public
  1293.      */
  1294.     function setCanonicalLink$pRelativeUrl {
  1295.         global $gBitSmarty;
  1296.         $baseUri defined'CANONICAL_BASE_URI' CANONICAL_BASE_URI BIT_BASE_URI
  1297.         $gBitSmarty->assign'canonicalLink'$baseUri.$pRelativeUrl );
  1298.     }
  1299.  
  1300.     /*static*/
  1301.     static function genPass({
  1302.         $vocales "aeiou";
  1303.         $consonantes "bcdfghjklmnpqrstvwxyz123456789";
  1304.         $r '';
  1305.         for$i 0$i 8$i++ {
  1306.             if$i {
  1307.                 $r .= $vocales{rand0strlen$vocales )};
  1308.             else {
  1309.                 $r .= $consonantes{rand0strlen$consonantes )};
  1310.             }
  1311.         }
  1312.         return $r;
  1313.     }
  1314.  
  1315.     // === lookupMimeType
  1316.     /**
  1317.      * given an extension, return the mime type
  1318.      *
  1319.      * @param string $pExtension is the extension of the file or the complete file name
  1320.      * @return mime type of entry and populates $this->mMimeTypes with existing mime types
  1321.      * @access public
  1322.      */
  1323.     function lookupMimeType$pExtension {
  1324.  
  1325.         $this->loadMimeTypes();
  1326.         ifpreg_match"#\.[0-9a-z]+$#i"$pExtension )) {
  1327.             $pExtension substr$pExtensionstrrpos$pExtension'.' ));
  1328.         }
  1329.         // rfc1341 - mime types are case insensitive.
  1330.         $pExtension strtolower$pExtension );
  1331.  
  1332.         return!empty$this->mMimeTypes[$pExtension$this->mMimeTypes[$pExtension'application/binary' );
  1333.     }
  1334.  
  1335.     // === loadMimeTypes
  1336.     /**
  1337.      * given an extension, return the mime type
  1338.      *
  1339.      * @param string $pExtension is the extension of the file or the complete file name
  1340.      * @return mime type of entry and populates $this->mMimeTypes with existing mime types
  1341.      * @access public
  1342.      */
  1343.     function loadMimeTypes({
  1344.         ifempty$this->mMimeTypes )) {
  1345.             // use bitweavers mime.types file to ensure everyone has our set unless user forces his own.
  1346.             ifdefined'MIME_TYPES' && is_fileMIME_TYPES )) {
  1347.                 $mimeFile MIME_TYPES;
  1348.             else {
  1349.                 $mimeFile KERNEL_PKG_PATH.'admin/mime.types';
  1350.             }
  1351.  
  1352.             $this->mMimeTypes array();
  1353.             if$fp fopen$mimeFile,"r" ) ) {
  1354.                 whileFALSE != $line fgets$fp4096 ) ) ) {
  1355.                     if!preg_match"/^\s*(?!#)\s*(\S+)\s+(?=\S)(.+)/"$line$match ) ) {
  1356.                         continue;
  1357.                     }
  1358.                     $tmp preg_split"/\s/",trim$match[2) );
  1359.                     foreach$tmp as $type {
  1360.                         $this->mMimeTypes[strtolower$type )$match[1];
  1361.                     }
  1362.                 }
  1363.                 fclose$fp );
  1364.             }
  1365.         }
  1366.     }
  1367.  
  1368.     // === verifyFileExtension
  1369.     /**
  1370.      * given a file and optionally desired name, return the correctly extensioned file and mime type
  1371.      *
  1372.      * @param string $pFile is the actual file to inspect for magic numbers to determine type
  1373.      * @param string $pFileName is the desired name the file. This is optional in the even the pFile is non-extensioned, as is the case with file uploads
  1374.      * @return corrected file name and mime type
  1375.      * @access public
  1376.      */
  1377.     function verifyFileExtension$pFile$pFileName=NULL {
  1378.         $this->loadMimeTypes();
  1379.         ifempty$pFileName ) ) {
  1380.             $pFileName basename$pFile );
  1381.             $ret $pFile;
  1382.         else {
  1383.             $ret $pFileName;
  1384.         }
  1385.         $verifyMime $this->verifyMimeType$pFile );
  1386.         ifstrrpos$pFileName'.' ) ) {
  1387.             $extension substr$pFileNamestrrpos$pFileName'.' );
  1388.             $lookupMime $this->lookupMimeType$extension );
  1389.         else {
  1390.             // extensionless file uploaded, get ready to add an extension
  1391.             $lookupMime '';
  1392.             $pFileName .= '.';
  1393.         }
  1394.  
  1395.         // if $verifyMime turns out to be 'octet-stream' and the lookupMimeType is a video file, we'll allow the video filetype and extenstion
  1396.         // if we don't do this, most uploaded videos are changed to have a '.bin' extenstion which is very annoying.
  1397.         if$verifyMime == 'application/octet-stream' && preg_match"/^video/"$lookupMime )) {
  1398.             $verifyMime $lookupMime;
  1399.         elseif$lookupMime != $verifyMime {
  1400.             if$verifyExt $this->getMimeExtension$verifyMime ) ) {
  1401.                 $ret substr$pFileName0strrpos$pFileName'.' ).$verifyExt;
  1402.             }
  1403.         }
  1404.  
  1405.         // if we still don't have an extension, we'll simply append a 'bin'
  1406.         ifpreg_match"/\.$/"$pFileName )) {
  1407.             $pFileName .= "bin";
  1408.         }
  1409.  
  1410.         return array$ret$verifyMime );
  1411.     }
  1412.  
  1413.  
  1414.     // === verifyMimeType
  1415.     /**
  1416.      * given a file, return the mime type
  1417.      *
  1418.      * @param string $pExtension is the extension of the file or the complete file name
  1419.      * @return mime type of entry and populates $this->mMimeTypes with existing mime types
  1420.      * @access public
  1421.      */
  1422.     function verifyMimeType$pFile {
  1423.         $mime NULL;
  1424.         iffile_exists$pFile ) ) {
  1425.             iffunction_exists'finfo_open' ) ) {
  1426.                 ifis_windows(&& defined'PHP_MAGIC_PATH' && is_readablePHP_MAGIC_PATH )) {
  1427.                     $finfo finfo_openFILEINFO_MIMEPHP_MAGIC_PATH );
  1428.                 else {
  1429.                     $finfo finfo_openFILEINFO_MIME );
  1430.                 }
  1431.                 $mime finfo_file$finfo$pFile );
  1432.                 finfo_close$finfo );
  1433.             else {
  1434.                 iffunction_enabled"escapeshellarg" && function_enabled"exec" )) {
  1435.                     $mime exectrim'file -bi ' escapeshellarg$pFile )));
  1436.                 }
  1437.             }
  1438.  
  1439.             ifempty$mime ) ) {
  1440.                 $mime $this->lookupMimeTypesubstr$pFilestrrpos$pFile'.' ) );
  1441.             }
  1442.             if$len strpos$mime';' )) {
  1443.                 $mime substr$mime0$len );
  1444.             }
  1445.         }
  1446.         return $mime;
  1447.     }
  1448.  
  1449.     function getMimeExtension$pMimeType {
  1450.         $ret '';
  1451.  
  1452.         if$pMimeType == 'image/jpeg' {
  1453.             $ret 'jpg'// jpeg has three options, .jpg is the most common
  1454.         else {
  1455.             $this->loadMimeTypes();
  1456.             if!($ret array_search$pMimeType$this->mMimeTypes )) ) {
  1457.                 // not present in mMimeTypes, here are some custom types
  1458.                 switch$pMimeType {
  1459.                     case 'image/bmp':
  1460.                         $ret 'bmp'break;
  1461.                     case 'image/pipeg':
  1462.                         $ret 'jfif'break;
  1463.                     case 'image/vnd.adobe.photoshop':
  1464.                         $ret 'psd'break;
  1465.                     case 'image/x-cmx':
  1466.                         $ret 'cmx'break;
  1467.                     case 'image/x-jps':
  1468.                         $ret 'jps'break;
  1469.                     case 'image/x-freehand':
  1470.                         $ret 'fh'break;
  1471.                 }
  1472.             }
  1473.         }
  1474.         return $ret;
  1475.     }
  1476.  
  1477.     /**
  1478.      * * Prepend $pPath to the include path
  1479.      * \static
  1480.      */
  1481.     public static function prependIncludePath$pPath {
  1482.         if!function_exists"get_include_path" ) ) {
  1483.             include_onceUTIL_PKG_PATH "PHP_Compat/Compat/Function/get_include_path.php" );
  1484.         }
  1485.         if!defined"PATH_SEPARATOR" ) ) {
  1486.             include_onceUTIL_PKG_PATH "PHP_Compat/Compat/Constant/PATH_SEPARATOR.php" );
  1487.         }
  1488.         if!function_exists"set_include_path" ) ) {
  1489.             include_onceUTIL_PKG_PATH "PHP_Compat/Compat/Function/set_include_path.php" );
  1490.         }
  1491.  
  1492.         $include_path get_include_path();
  1493.         if$include_path {
  1494.             $include_path $pPath PATH_SEPARATOR $include_path;
  1495.         else {
  1496.             $include_path $pPath;
  1497.         }
  1498.         return set_include_path$include_path );
  1499.     }
  1500.  
  1501.     /**
  1502.      * * Append $pPath to the include path
  1503.      * \static
  1504.      */
  1505.     function appendIncludePath$pPath {
  1506.         if!function_exists"get_include_path" ) ) {
  1507.             include_once(UTIL_PKG_PATH "PHP_Compat/Compat/Function/get_include_path.php");
  1508.         }
  1509.         if!defined("PATH_SEPARATOR" ) ) {
  1510.             include_once(UTIL_PKG_PATH "PHP_Compat/Compat/Constant/PATH_SEPARATOR.php");
  1511.         }
  1512.         if!function_exists"set_include_path" ) ) {
  1513.             include_once(UTIL_PKG_PATH "PHP_Compat/Compat/Function/set_include_path.php");
  1514.         }
  1515.  
  1516.         $include_path get_include_path();
  1517.         if$include_path {
  1518.             $include_path .= PATH_SEPARATOR $pPath;
  1519.         else {
  1520.             $include_path $pPath;
  1521.         }
  1522.         return set_include_path$include_path );
  1523.     }
  1524.  
  1525.     private function defineTempDir({
  1526.         // allow for overridden TEMP_PKG_PATH
  1527.         if!defined'TEMP_PKG_PATH' ) ) {
  1528.             $tempDir $this->getConfig'site_temp_dir'self::getDefaultTempDir() );
  1529.             ifstrrpos$tempDir'/' != strlen$tempDir ) ) {
  1530.                 $tempDir .= '/';
  1531.             }
  1532.  
  1533.             define'TEMP_PKG_PATH'$tempDir );
  1534.             define'TEMP_PKG_URL'BIT_ROOT_URL.'temp/' );
  1535.             if!file_exists$tempDir ) ) {
  1536.                 mkdir$tempDir0777TRUE );
  1537.             }
  1538.         }
  1539.     }
  1540.  
  1541.     public function getDefaultTempDir({
  1542.         return sys_get_temp_dir().'/bitweaver/'.$_SERVER['SERVER_NAME'].'/';
  1543.     }
  1544.  
  1545.     /* Check that everything is set up properly
  1546.      * \static
  1547.      */
  1548.     function checkEnvironment({
  1549.         static $checked$gTempDirs;
  1550.  
  1551.         if$checked {
  1552.             return;
  1553.         }
  1554.  
  1555.         $errors '';
  1556.  
  1557.         $docroot BIT_ROOT_PATH;
  1558.  
  1559.         /*    this seems to prevent bw from running on servers where sessions work perfectly,
  1560.             yet /var/lib/php/ is writeable only by php, not by bw (which is better)
  1561.             it seems to be enough to set temp in config/kernel/config_inc.php for a writable dir
  1562.             if session *actually* don't work - other problem
  1563.             the installer has similar code which is also not used anymore
  1564.  
  1565.         if( ini_get( 'session.save_handler' ) == 'files' ) {
  1566.             $save_path = ini_get( 'session.save_path' );
  1567.  
  1568.             if( empty( $save_path ) ) {
  1569.                 $errors .= "The session.save_path variable is not setup correctly (its empty).\n";
  1570.             } else {
  1571.                 if( strpos( $save_path, ";" ) !== FALSE ) {
  1572.                     $save_path = substr( $save_path, strpos( $save_path, ";" )+1 );
  1573.                 }
  1574.                 $open = ini_get( 'open_basedir' );
  1575.                 if( !@is_dir( $save_path ) && empty( $open ) ) {
  1576.                     $errors .= "The directory '$save_path' does not exist or PHP is not allowed to access it (check open_basedir entry in php.ini).\n";
  1577.                 } elseif( !bw_is_writeable( $save_path ) ) {
  1578.                     $errors .= "The directory '$save_path' is not writeable.\n";
  1579.                 }
  1580.             }
  1581.  
  1582.             if( $errors ) {
  1583.                 $save_path = get_temp_dir();
  1584.  
  1585.                 if( is_dir( $save_path ) && bw_is_writeable( $save_path ) ) {
  1586.                     ini_set( 'session.save_path', $save_path );
  1587.  
  1588.                     $errors = '';
  1589.                 }
  1590.             }
  1591.         }
  1592.         */
  1593.  
  1594.         $wwwuser '';
  1595.         $wwwgroup '';
  1596.  
  1597.         ifis_windows() ) {
  1598.             ifstrpos$_SERVER["SERVER_SOFTWARE"],"IIS" && isset$_SERVER['COMPUTERNAME') ) {
  1599.                 $wwwuser 'IUSR_'.$_SERVER['COMPUTERNAME'];
  1600.                 $wwwgroup 'IUSR_'.$_SERVER['COMPUTERNAME'];
  1601.             else {
  1602.                 $wwwuser 'SYSTEM';
  1603.                 $wwwgroup 'SYSTEM';
  1604.             }
  1605.         }
  1606.  
  1607.         iffunction_exists'posix_getuid' ) ) {
  1608.             $userhash @posix_getpwuid@posix_getuid() );
  1609.             $group @posix_getpwuid@posix_getgid() );
  1610.             $wwwuser $userhash $userhash['name'FALSE;
  1611.             $wwwgroup $group $group['name'FALSE;
  1612.         }
  1613.  
  1614.         if!$wwwuser {
  1615.             $wwwuser 'nobody (or the user account the web server is running under)';
  1616.         }
  1617.  
  1618.         if!$wwwgroup {
  1619.             $wwwgroup 'nobody (or the group account the web server is running under)';
  1620.         }
  1621.  
  1622.         ifdefined'TEMP_PKG_PATH' ) ) {
  1623.             $this->setConfig'site_temp_dir'TEMP_PKG_PATH );
  1624.             $permFiles[TEMP_PKG_PATH;
  1625.         else {
  1626.             $permFiles[$this->getConfig'site_temp_dir'self::getDefaultTempDir() );
  1627.         }
  1628.         $permFiles[STORAGE_PKG_PATH;
  1629.  
  1630.         foreach$permFiles as $file {
  1631.             $present FALSE;
  1632.             // Create directories as needed
  1633.             $target $file;
  1634.             ifpreg_match'/.*\/$/'$target ) ) {
  1635.                 // we have a directory
  1636.                 if!is_dir$target ) ) {
  1637.                     mkdir$target02775TRUE );
  1638.                 }
  1639.                 // Check again and report problems
  1640.                 if!is_dir$target ) ) {
  1641.                     if!is_windows() ) {
  1642.                         $errors .= "
  1643.                             <p>The directory <strong style='color:red;'>$target</strong> does not exist. To create the directory, execute a command such as:</p>
  1644.                             <pre>\$ mkdir -m 777 $target</pre>
  1645.                             ";
  1646.                     else {
  1647.                         $errors .= "<p>The directory <strong style='color:red;'>$target</strong> does not exist. Create the directory $target before proceeding</p>";
  1648.                     }
  1649.                 else {
  1650.                     $present TRUE;
  1651.                 }
  1652.             elseif!file_exists$target ) ) {
  1653.                 if!is_windows() ) {
  1654.                     $errors .= "<p>The file <b style='color:red;'>$target</b> does not exist. To create the file, execute a command such as:</p>
  1655.                         <pre>
  1656.                         \$ touch $target
  1657.                         \$ chmod 777 $target
  1658.                         </pre>
  1659.                         ";
  1660.                 else {
  1661.                     $errors .= "<p>The file <b style='color:red;'>$target</b> does not exist. Create a blank file $target before proceeding</p>";
  1662.                 }
  1663.             else {
  1664.                 $present TRUE;
  1665.             }
  1666.  
  1667.             // chmod( $target, 02775 );
  1668.             if$present && !bw_is_writeable$target ))) {
  1669.                 if!is_windows() ) {
  1670.                     $errors .= "<p><strong style='color:red;'>$target</strong> is not writeable by $wwwuser. To give $wwwuser write permission, execute a command such as:</p>
  1671.                     <pre>\$ chmod 777 $target</pre>";
  1672.                 else {
  1673.                     $errors .= "<p><b style='color:red;'>$target</b> is not writeable by $wwwuser. Check the security of the file $target before proceeding</p>";
  1674.                 }
  1675.             }
  1676.             //if (!is_dir("$docroot/$dir")) {
  1677.             //    $errors .= "The directory '$docroot$dir' does not exist.\n";
  1678.             //} else if (!bw_is_writeable("$docroot/$dir")) {
  1679.             //    $errors .= "The directory '$docroot$dir' is not writeable by $wwwuser.\n";
  1680.             //}
  1681.         }
  1682.  
  1683.         if$errors {
  1684.             $PHP_CONFIG_FILE_PATH PHP_CONFIG_FILE_PATH;
  1685.  
  1686.             ob_start();
  1687.             phpinfo (INFO_MODULES);
  1688.             $httpd_conf 'httpd.conf';
  1689.  
  1690.             ifpreg_match'/Server Root<\/b><\/td><td\s+align="left">([^<]*)</'ob_get_contents()$m )) {
  1691.                 $httpd_conf $m[1'/' $httpd_conf;
  1692.             }
  1693.  
  1694.             ob_end_clean();
  1695.  
  1696.             print "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"DTD/xhtml1-strict.dtd\">
  1697. <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
  1698.     <head>
  1699.         <title>bitweaver setup problems</title>
  1700.         <meta http-equiv=\"Pragma\" content=\"no-cache\" />
  1701.         <meta http-equiv=\"Expires\" content=\"-1\" />
  1702.     </head>
  1703.     <body>
  1704.         <h1 style=\"color:red;\">bitweaver is not properly set up:</h1>
  1705.         <blockquote>
  1706.             $errors
  1707.         </blockquote>";
  1708.             if!$this->isLive() ) {
  1709.                 if!is_windows() ) {
  1710.                     print "<p>Proceed to the installer <strong>at <a href=\"".BIT_ROOT_URL."install/install.php\">".BIT_ROOT_URL."install/install.php</a></strong> after you run the command.";
  1711.                 else {
  1712.                     print "<p>Proceed to the installer <strong>at <a href=\"".BIT_ROOT_URL."install/install.php\">".BIT_ROOT_URL."install/install.php</a></strong> after you have corrected the identified problems.";
  1713.                 }
  1714.                 print "<br />Consult the bitweaver <a href='http://www.bitweaver.org/wiki/index.php?page=Technical_Documentation'>Technical Documentation</a> if you need more help.</p></body></html>";
  1715.             }
  1716.  
  1717.             exit;
  1718.         }
  1719.  
  1720.         $checked TRUE;
  1721.     }
  1722.  
  1723.     /**
  1724.      * isLive returns status of the IS_LIVE constant from config/kernel/config_inc.php
  1725.      *
  1726.      * @access public
  1727.      * @return TRUE if IS_LIVE is defined and set to a non empty value, else FALSE
  1728.      */
  1729.     function isLive({
  1730.         return( (defined'IS_LIVE' && IS_LIVE&& !$this->isFeatureActive'site_hidden' ) );
  1731.     }
  1732.  
  1733.     // {{{=========================== Installer related methods ==============================
  1734.     // Keep these methods in BitSystem that we can call verifyInstalledPackages() and other
  1735.     // mthods without the need for an install/ package to be present.
  1736.     /**
  1737.      * registerSchemaTable
  1738.      *
  1739.      * @param array $pPackage 
  1740.      * @param array $pTableName 
  1741.      * @param array $pDataDict 
  1742.      * @param array $pRequired 
  1743.      * @param array $pTableOptions 
  1744.      * @access public
  1745.      * @return void 
  1746.      */
  1747.     function registerSchemaTable$pPackage$pTableName$pDataDict$pRequired=FALSE$pTableOptions=NULL {
  1748.         $pPackage strtolower$pPackage )// lower case for uniformity
  1749.         if!empty$pTableName ) ) {
  1750.             $this->mPackages[$pPackage]['tables'][$pTableName$pDataDict;
  1751.             if!empty$pTableOptions ) ) {
  1752.                 $this->mPackages[$pPackage]['tables']['options'][$pTableName$pTableOptions;
  1753.             }
  1754.         }
  1755.     }
  1756.  
  1757.     /**
  1758.      * registerSchemaConstraints
  1759.      *
  1760.      * @param array $pPackage 
  1761.      * @param array $pTableName 
  1762.      * @param array $pConstraints 
  1763.      * @access public
  1764.      * @return void 
  1765.      */
  1766.     function registerSchemaConstraints$pPackage$pTableName$pConstraints {
  1767.         $pPackage strtolower$pPackage);
  1768.         if!empty$pTableName ) ) {
  1769.             $this->mPackages[$pPackage]['constraints'][$pTableName$pConstraints;
  1770.         }
  1771.     }
  1772.  
  1773.     /**
  1774.      * registerUserPermissions
  1775.      *
  1776.      * @param array $pPackagedir 
  1777.      * @param array $pUserpermissions 
  1778.      * @access public
  1779.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1780.      */
  1781.     function registerUserPermissions$pPackagedir$pUserpermissions {
  1782.         foreach$pUserpermissions as $perm {
  1783.             $this->mPermHash[$perm[0]] $perm;
  1784.             $this->mPermHash[$perm[0]]['sql'"INSERT INTO `".BIT_DB_PREFIX."users_permissions` (`perm_name`, `perm_desc`, `perm_level`, `package`) VALUES ('$perm[0]', '$perm[1]', '$perm[2]', '$perm[3]')";
  1785.             $this->registerSchemaDefault$pPackagedir,
  1786.                 "INSERT INTO `".BIT_DB_PREFIX."users_permissions` (`perm_name`, `perm_desc`, `perm_level`, `package`) VALUES ('$perm[0]', '$perm[1]', '$perm[2]', '$perm[3]')");
  1787.         }
  1788.     }
  1789.  
  1790.     /**
  1791.      * registerConfig
  1792.      *
  1793.      * @param array $pPackagedir 
  1794.      * @param array $pPreferences 
  1795.      * @access public
  1796.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1797.      */
  1798.     function registerConfig$pPackagedir$pPreferences {
  1799.         foreach$pPreferences as $pref {
  1800.             $this->registerSchemaDefault$pPackagedir,
  1801.                 "INSERT INTO `".BIT_DB_PREFIX."kernel_config`(`package`,`config_name`,`config_value`) VALUES ('$pref[0]', '$pref[1]','$pref[2]')");
  1802.         }
  1803.     }
  1804.  
  1805.     /**
  1806.      * registerPreferences
  1807.      *
  1808.      * @param array $pPackagedir 
  1809.      * @param array $pPreferences 
  1810.      * @access public
  1811.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1812.      */
  1813.     function registerPreferences$pPackagedir$pPreferences {
  1814.         foreach$pPreferences as $prefHash {
  1815.             $this->mPackages[$pPackagedir]['default_prefs'][array'package' => $prefHash[0]'name' => $prefHash[1]'value' => $prefHash[2);
  1816.         }
  1817.     }
  1818.  
  1819.     /**
  1820.      * registerModules
  1821.      *
  1822.      * @param array $pModuleHash 
  1823.      * @access public
  1824.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1825.      */
  1826.     function registerModules$pModuleHash {
  1827.         $this->mInstallModules = array_merge$this->mInstallModules$pModuleHash );
  1828.     }
  1829.  
  1830.     /**
  1831.      * registerContentObjects
  1832.      *
  1833.      * @param string $pPackageName the package name
  1834.      * @param hash $pClassesHash [$className => $pathToClassFile]
  1835.      * @access public
  1836.      */
  1837.     function registerContentObjects$pPackageName$pClassesHash {
  1838.         $this->mContentClasses[$pPackageName$pClassesHash;
  1839.     }
  1840.  
  1841.     /**
  1842.      * registerPackageInfo
  1843.      *
  1844.      * @param array $pPackage 
  1845.      * @param array $pInfoHash 
  1846.      * @access public
  1847.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1848.      */
  1849.     function registerPackageInfo$pPackage$pInfoHash {
  1850.         $pPackage strtolower$pPackage )// lower case for uniformity
  1851.         if!empty$this->mPackages[$pPackage]['info')) {
  1852.             $this->mPackages[$pPackage]['info'array_merge$this->mPackages[$pPackage]['info']$pInfoHash );
  1853.         else {
  1854.             $this->mPackages[$pPackage]['info'$pInfoHash;
  1855.         }
  1856.         $this->mPackages[$pPackage]['info']['version'$this->getVersion$pPackage );
  1857.         $upgrade $this->getLatestUpgradeVersion$pPackage );
  1858.         if!empty$upgrade && version_compare$upgrade$this->getVersion$pPackage )'>' )) {
  1859.             if$this->mPackages[$pPackage]['installed'{
  1860.                 $this->mPackages[$pPackage]['info']['upgrade'$upgrade;
  1861.             else {
  1862.                 $this->mPackages[$pPackage]['info']['version'$upgrade;
  1863.             }
  1864.         }
  1865.     }
  1866.  
  1867.     /**
  1868.      * registerSchemaSequences
  1869.      *
  1870.      * @param array $pPackage 
  1871.      * @param array $pSeqHash 
  1872.      * @access public
  1873.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1874.      */
  1875.     function registerSchemaSequences$pPackage$pSeqHash {
  1876.         $pPackage strtolower$pPackage )// lower case for uniformity
  1877.         $this->mPackages[$pPackage]['sequences'$pSeqHash;
  1878.     }
  1879.  
  1880.     /**
  1881.      * registerSchemaIndexes
  1882.      *
  1883.      * @param array $pPackage 
  1884.      * @param array $pIndexHash 
  1885.      * @access public
  1886.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1887.      */
  1888.     function registerSchemaIndexes$pPackage$pIndexHash {
  1889.         $pPackage strtolower$pPackage )// lower case for uniformity
  1890.         $this->mPackages[$pPackage]['indexes'$pIndexHash;
  1891.     }
  1892.  
  1893.     /**
  1894.      * registerSchemaDefault
  1895.      *
  1896.      * @param array $pPackage 
  1897.      * @param array $pMixedDefaultSql 
  1898.      * @access public
  1899.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  1900.      */
  1901.     function registerSchemaDefault$pPackage$pMixedDefaultSql {
  1902.         $pPackage strtolower$pPackage )// lower case for uniformity
  1903.         ifempty$this->mPackages[$pPackage]['defaults') ) {
  1904.             $this->mPackages[$pPackage]['defaults'array();
  1905.         }
  1906.         ifis_array$pMixedDefaultSql ) ) {
  1907.             foreach$pMixedDefaultSql as $def {
  1908.                 $this->mPackages[$pPackage]['defaults'][$def;
  1909.             }
  1910.         elseifis_string$pMixedDefaultSql ) ) {
  1911.             array_push$this->mPackages[$pPackage]['defaults']$pMixedDefaultSql );
  1912.         }
  1913.     }
  1914.  
  1915.     /**
  1916.      * storeVersion will store the version number of a given package
  1917.      *
  1918.      * @param array $pPackage Name of package - if not given, bitweaver_version will be stored
  1919.      * @param array $pVersion Version number
  1920.      * @access public
  1921.      * @return TRUE on success, FALSE on failure
  1922.      */
  1923.     function storeVersion$pPackage NULL$pVersion {
  1924.         global $gBitSystem;
  1925.         $ret FALSE;
  1926.         if!empty$pVersion && $this->validateVersion$pVersion )) {
  1927.             ifempty$pPackage )) {
  1928.                 $gBitSystem->storeConfig"bitweaver_version"$pVersion'kernel' );
  1929.                 $ret TRUE;
  1930.             elseif!empty$gBitSystem->mPackages[$pPackage)) {
  1931.                 $gBitSystem->storeConfig"package_".$pPackage."_version"$pVersion$pPackage );
  1932.                 $ret TRUE;
  1933.             }
  1934.         }
  1935.         return $ret;
  1936.     }
  1937.  
  1938.     /**
  1939.      * getVersion will fetch the version number of a given package
  1940.      *
  1941.      * @param array $pPackage Name of package - if not given, bitweaver_version will be stored
  1942.      * @param array $pVersion Version number
  1943.      * @access public
  1944.      * @return version number on success
  1945.      */
  1946.     function getVersion$pPackage NULL$pDefault '0.0.0' {
  1947.         global $gBitSystem;
  1948.         ifempty$pPackage )) {
  1949.             $config 'bitweaver_version';
  1950.         else {
  1951.             $config "package_".$pPackage."_version";
  1952.         }
  1953.  
  1954.         return $gBitSystem->getConfig$config$pDefault );
  1955.     }
  1956.  
  1957.     /**
  1958.      * getLatestUpgradeVersion will fetch the greatest upgrade number for a given package
  1959.      *
  1960.      * @param array $pPackage package we want to fetch the latest version number for
  1961.      * @access public
  1962.      * @return string greatest upgrade number for a given package
  1963.      */
  1964.     function getLatestUpgradeVersion$pPackage {
  1965.         $ret '0.0.0';
  1966.         if!empty$pPackage )) {
  1967.             $dir constantstrtoupper$pPackage )."_PKG_PATH" )."admin/upgrades/";
  1968.             ifis_dir$dir && $upDir opendir$dir )) {
  1969.                 whileFALSE !== $file readdir$upDir ))) {
  1970.                     ifis_file$dir.$file )) {
  1971.                         $upVersion str_replace".php"""$file );
  1972.                         // we only want to update $ret if the version of the file is greater than the previous one
  1973.                         if$this->validateVersion$upVersion && version_compare$ret$upVersion"<" )) {
  1974.                             $ret $upVersion;
  1975.                         }
  1976.                     }
  1977.                 }
  1978.             }
  1979.         }
  1980.         return(( $ret == '0.0.0' FALSE $ret );
  1981.     }
  1982.  
  1983.     /**
  1984.      * registerPackageVersion Holds the package version
  1985.      *
  1986.      * @param array $pPackage 
  1987.      * @param array $pVersion 
  1988.      * @access public
  1989.      * @return void 
  1990.      */
  1991.     function registerPackageVersion$pPackage$pVersion {
  1992.         if!empty$pPackage && $this->validateVersion$pVersion )) {
  1993.             $pPackage strtolower$pPackage );
  1994.             $this->mPackages[$pPackage]['version'$pVersion;
  1995.         }
  1996.     }
  1997.  
  1998.     /**
  1999.      * validateVersion
  2000.      *
  2001.      * @param array $pVersion 
  2002.      * @access public
  2003.      * @return TRUE on success, FALSE on failure
  2004.      */
  2005.     function validateVersion$pVersion {
  2006.         returnpreg_match"/^(\d+\.\d+\.\d+)(-dev|-alpha|-beta|-pl|-RC\d+)?$/"$pVersion ));
  2007.     }
  2008.  
  2009.     /**
  2010.      * registerRequirements
  2011.      *
  2012.      * @param array $pParams 
  2013.      * @param array $pReqHash 
  2014.      * @access public
  2015.      * @return void 
  2016.      */
  2017.     function registerRequirements$pPackage$pReqHash {
  2018.         if!empty$pPackage && $this->verifyRequirements$pReqHash )) {
  2019.             $pPackage strtolower$pPackage );
  2020.             $this->mRequirements[$pPackage$pReqHash;
  2021.  
  2022.             // and we display the info
  2023.             $this->mPackages[$pPackage]['info']['requirements''';
  2024.             foreach$pReqHash as $req => $version {
  2025.                 //$this->mPackages[$req]['is_requirement'] = TRUE;
  2026.  
  2027.                 $this->mPackages[$pPackage]['info']['requirements'.= '<a class="external" href="http://www.bitweaver.org/wiki/'.ucfirst$req ).'Package">'.ucfirst$req ).'</a>';
  2028.                 $max !empty$version['max'" - ".$version['max''' );
  2029.                 if$version['min'!= '0.0.0' {
  2030.                     $this->mPackages[$pPackage]['info']['requirements'.= " (".$version['min'].$max.")";
  2031.                 }
  2032.                 $this->mPackages[$pPackage]['info']['requirements'.= ", ";
  2033.             }
  2034.             // remove trailing ,
  2035.             $this->mPackages[$pPackage]['info']['requirements'rtrimtrim$this->mPackages[$pPackage]['info']['requirements')"," );
  2036.         }
  2037.     }
  2038.  
  2039.     /**
  2040.      * verifyRequirements
  2041.      *
  2042.      * @param array $pReqHash 
  2043.      * @access public
  2044.      * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
  2045.      */
  2046.     function verifyRequirements&$pReqHash {
  2047.         if!empty$pReqHash && is_array$pReqHash )) {
  2048.             foreach$pReqHash as $pkg => $versions {
  2049.                 ifempty$versions['min')) {
  2050.                     $this->mErrors['version_min'"You have to provide a minimum version number for the $pkg requirement. If you just want the required package to be present, please use 0.0.0 as minimum version.";
  2051.                 elseif!$this->validateVersion$versions['min')) {
  2052.                     $this->mErrors['version_min'"Please make sure you use a valid minimum version number for the $pkg requirement.";
  2053.                 elseif!empty$versions['max')) {
  2054.                     if!$this->validateVersion$versions['max')) {
  2055.                         $this->mErrors['version_max'"Please make sure you use a valid maximum version number for the $pkg requirement.";
  2056.                     elseifversion_compare$versions['min']$versions['max']'>=' )) {
  2057.                         $this->mErrors['version_max'"Please make sure the maximum version is greater than the minimum version for the $pkg requirement.";
  2058.                     }
  2059.                 }
  2060.             }
  2061.         else {
  2062.             $this->mErrors['deps'"If you want to register requirements, please do so with a valid requirement hash.";
  2063.         }
  2064.  
  2065.         // since this should only show up when devs are working, we'll simply display the output:
  2066.         if!empty$this->mErrors )) {
  2067.             vd$this->mErrors );
  2068.             bt();
  2069.         }
  2070.  
  2071.         returncount$this->mErrors == );
  2072.     }
  2073.  
  2074.     /**
  2075.      * getRequirements
  2076.      *
  2077.      * @param array $pPackage 
  2078.      * @access public
  2079.      * @return array of package requirements
  2080.      */
  2081.     function getRequirements$pPackage {
  2082.         $ret array();
  2083.         if!empty$pPackage )) {
  2084.             $pPackage strtolower$pPackage );
  2085.             if!empty$this->mRequirements[$pPackage)) {
  2086.                 return $this->mRequirements[$pPackage];
  2087.             }
  2088.         }
  2089.         return $ret;
  2090.     }
  2091.  
  2092.     /**
  2093.      * calculateRequirements will calculate all requirements and return a hash of the results
  2094.      *
  2095.      * @param boolean $pInstallVersion Use the actual installed version instead of the version that will be in bitweaver after the upgrade
  2096.      * @access public
  2097.      * @return boolean TRUE on success, FALSE on failure - mErrors will contain reason for failure
  2098.      */
  2099.     function calculateRequirements$pInstallVersion FALSE {
  2100.         $ret array();
  2101.         // first we gather all version information.
  2102.         foreacharray_keys$this->mPackages as $package {
  2103.             if$this->isPackageInstalled$package )) {
  2104.  
  2105.                 // get the latest upgrade version, since this is the version the package will be at after install
  2106.                 if$pInstallVersion || !$version $this->getLatestUpgradeVersion$package )) {
  2107.                     $version $this->getVersion$package );
  2108.                 }
  2109.                 $installed[$package$version;
  2110.  
  2111.                 if$this->isPackageActive$package )) {
  2112.                     if$deps $this->getRequirements$package )) {
  2113.                         $requirements[$package$deps;
  2114.                     }
  2115.                     $inactive[$packageFALSE;
  2116.                 else {
  2117.                     $inactive[$packageTRUE;
  2118.                 }
  2119.             }
  2120.         }
  2121.  
  2122.         if!empty$requirements )) {
  2123.             foreach$requirements as $package => $deps {
  2124.                 foreach$deps as $depPackage => $depVersion {
  2125.                     $hash array(
  2126.                         'package'          => $package,
  2127.                         'package_version'  => $installed[$package],
  2128.                         'requires'         => $depPackage,
  2129.                         'required_version' => $depVersion,
  2130.                     );
  2131.  
  2132.                     if!empty$installed[$depPackage)) {
  2133.                         $hash['version']['available'$installed[$depPackage];
  2134.                     }
  2135.  
  2136.                     ifempty$installed[$depPackage)) {
  2137.                         $hash['result''missing';
  2138.                     elseifversion_compare$depVersion['min']$installed[$depPackage]'>' )) {
  2139.                         $hash['result''min_dep';
  2140.                     elseif!empty$depVersion['max'&& version_compare$depVersion['max']$installed[$depPackage]'<' )) {
  2141.                         $hash['result''max_dep';
  2142.                     elseifisset$inactive[$depPackage&& $inactive[$depPackage{
  2143.                         $hash['result''inactive';
  2144.                     else {
  2145.                         $hash['result''ok';
  2146.                     }
  2147.  
  2148.                     $ret[$hash;
  2149.                 }
  2150.             }
  2151.         }
  2152.  
  2153.         return $ret;
  2154.     }
  2155.  
  2156.     /**
  2157.      * drawRequirementsGraph Will draw a requirement graph if PEAR::Image_GraphViz is installed
  2158.      *
  2159.      * @param boolean $pInstallVersion Use the actual installed version instead of the version that will be in bitweaver after the upgrade
  2160.      * @param string $pFormat dot output format
  2161.      * @param string $pCommand dot or neato
  2162.      * @access public
  2163.      * @return boolean TRUE on success, FALSE on failure - mErrors will contain reason for failure
  2164.      */
  2165.     function drawRequirementsGraph$pInstallVersion FALSE$pFormat 'png'$pCommand 'dot' {
  2166.         global $gBitSmarty$gBitThemes;
  2167.  
  2168.         // only do this if we can load PEAR GraphViz interface
  2169.         if@include_once'Image/GraphViz.php' )) {
  2170.             ksort$this->mPackages );
  2171.             $deps $this->calculateRequirements$pInstallVersion );
  2172.             $delKeys $matches array();
  2173.  
  2174.             // crazy manipulation of hash to remove duplicate version matches.
  2175.             // we do this that we can use double headed arrows in the graph below.
  2176.             foreach$deps as $key => $req {
  2177.                 foreach$deps as $k => $d {
  2178.                     if$req['requires'== $d['package'&& $req['package'== $d['requires'&& $req['result'== 'ok' && $d['result'== 'ok' {
  2179.                         $deps[$key]['dir''both';
  2180.                         $matches[$key$k;
  2181.                     }
  2182.                 }
  2183.             }
  2184.  
  2185.             // get duplicates
  2186.             foreach$matches as $key => $match {
  2187.                 unset$delKeys[$match);
  2188.                 $delKeys[$key$match;
  2189.             }
  2190.  
  2191.             // remove dupes from hash
  2192.             foreach$delKeys as $key {
  2193.                 unset$deps[$key);
  2194.             }
  2195.  
  2196.             // start drawing stuff
  2197.             $graph new Image_GraphVizTRUE$gBitThemes->getGraphvizGraphAttributes()'Requirements'TRUE );
  2198.  
  2199.             $fromattributes $toattributes $gBitThemes->getGraphvizNodeAttributes();
  2200.  
  2201.             foreach$deps as $node {
  2202.                 //$fromNode = ucfirst( $node['package'] )."\n".$node['package_version'];
  2203.                 //$toNode   = ucfirst( $node['requires'] )."\n".$node['required_version']['min'];
  2204.  
  2205.                 $fromNode ucfirst$node['package');
  2206.                 $toNode   ucfirst$node['requires');
  2207.  
  2208.                 switch$node['result'{
  2209.                 case 'max_dep':
  2210.                     $edgecolor 'chocolate3';
  2211.                     $label     'Maximum version\nexceeded';
  2212.                     $toNode   .= "\n".$node['required_version']['min']." - ".$node['required_version']['max'];
  2213.                     $toattributes['fillcolor''khaki';
  2214.                     break;
  2215.                 case 'min_dep':
  2216.                     $edgecolor 'crimson';
  2217.                     $label     'Minimum version\nnot met';
  2218.                     $toNode   .= "\n".$node['required_version']['min'];
  2219.                     if!empty$node['required_version']['max')) {
  2220.                         $toNode .= " - ".$node['required_version']['max'];
  2221.                     }
  2222.                     $toattributes['fillcolor''pink';
  2223.                     break;
  2224.                 case 'missing':
  2225.                     $edgecolor 'crimson';
  2226.                     $label     'Not installed\nor activated';
  2227.                     $toNode   .= "\n".$node['required_version']['min'];
  2228.                     if!empty$node['required_version']['max')) {
  2229.                         $toNode .= " - ".$node['required_version']['max'];
  2230.                     }
  2231.                     $toattributes['fillcolor''pink';
  2232.                     break;
  2233.                 default:
  2234.                     $edgecolor '';
  2235.                     $label     '';
  2236.                     $toattributes['fillcolor''white';
  2237.                     break;
  2238.                 }
  2239.  
  2240.                 $fromattributes['URL'"http://www.bitweaver.org/wiki/".ucfirst$node['package')."Package";
  2241.                 $graph->addNode$fromNode$fromattributes );
  2242.  
  2243.                 $toattributes['URL'"http://www.bitweaver.org/wiki/".ucfirst$node['requires')."Package";
  2244.                 $graph->addNode$toNode$toattributes );
  2245.  
  2246.                 $graph->addEdge(
  2247.                     array$fromNode => $toNode ),
  2248.                     $gBitThemes->getGraphvizEdgeAttributesarray(
  2249.                         'dir'       => !empty$node['dir'$node['dir''' ),
  2250.                         'color'     => $edgecolor,
  2251.                         'fontcolor' => $edgecolor,
  2252.                         'label'     => $label,
  2253.                     ))
  2254.                 );
  2255.             }
  2256.  
  2257.             ifpreg_match"#(png|gif|jpe?g|bmp|svg|tif)#i"$pFormat )) {
  2258.                 $graph->image$pFormat$pCommand );
  2259.             else {
  2260.                 return $graph->fetch$pFormat$pCommand );
  2261.             }
  2262.         else {
  2263.             return FALSE;
  2264.         }
  2265.     }
  2266.  
  2267.     /**
  2268.      * verifyInstalledPackages scan all available packages
  2269.      *
  2270.      * @param string pScanFile file to be looked for
  2271.      * @return none 
  2272.      * @access public
  2273.      */
  2274.     function verifyInstalledPackages$pSelect='installed' {
  2275.         global $gBitDbType;
  2276.         #load in any admin/schema_inc.php files that exist for each package
  2277.         $this->scanPackages'admin/schema_inc.php'TRUE$pSelectFALSETRUE );
  2278.         $ret array();
  2279.  
  2280.         if$this->isDatabaseValid() ) {
  2281.             ifstrlenBIT_DB_PREFIX {
  2282.                 $lastQuote strrposBIT_DB_PREFIX'`' );
  2283.                 if$lastQuote != FALSE {
  2284.                     $lastQuote++;
  2285.                 }
  2286.                 $prefix substrBIT_DB_PREFIX$lastQuote );
  2287.             else {
  2288.                 $prefix '';
  2289.             }
  2290.  
  2291.             $showTables $prefix $prefix.'%' NULL );
  2292.             $unusedTables array();
  2293.             if$dbTables $this->mDb->MetaTables'TABLES'FALSE$showTables ) ) {
  2294.                 // make a copy that we can keep track of what tables have been used
  2295.                 $unusedTables $dbTables;
  2296.                 foreacharray_keys$this->mPackages as $package {
  2297.                     // Default to TRUE, &= will FALSE out
  2298.                     $this->mPackages[$package]['installed'TRUE;
  2299.                     if!empty$this->mPackages[$package]['tables') ) {
  2300.                         $this->mPackages[$package]['db_tables_found'TRUE;
  2301.                         foreacharray_keys$this->mPackages[$package]['tables'as $table {
  2302.                             // painful hardcoded exception for bitcommerce
  2303.                             if$package == 'bitcommerce' {
  2304.                                 $fullTable $table;
  2305.                             else {
  2306.                                 $fullTable $prefix.$table;
  2307.                             }
  2308.                             $tablePresent in_array$fullTable$dbTables );
  2309.                             if$tablePresent {
  2310.                                 $ret['present'][$package][$table;
  2311.                             else {
  2312.                                 $ret['missing'][$package][$table;
  2313.                                 // This is a crude but highly effective means of blurting out a very bad situation when an installed package is missing a table
  2314.                                 if!$this->isLive(&& $this->isPackageActive$package ) ) {
  2315. // This needs hiding during install so disabled for now
  2316. //                                     vd( "Table Missing => $package : $table" );
  2317.                                 }
  2318.                             }
  2319.  
  2320.                             // lets also return the tables that are not in use by bitweaver
  2321.                             // this is useful when we want to remove old tables or upgrade tables
  2322.                             if(( $key array_search$fullTable$dbTables )) !== FALSE {
  2323.                                 unset$unusedTables[$key);
  2324.                             }
  2325.  
  2326.                             $this->mPackages[$package]['installed'&= $tablePresent;
  2327.                             $this->mPackages[$package]['db_tables_found'&= $tablePresent;
  2328.                         }
  2329.                     else {
  2330.                         $this->mPackages[$package]['db_tables_found'FALSE;
  2331.                         if!$this->getConfig'package_'.strtolower$package ) ) ){
  2332.                             $this->mPackages[$package]['installed'FALSE;
  2333.                         }
  2334.                     }
  2335.  
  2336.                     $this->mPackages[$package]['active_switch'$this->getConfig'package_'.strtolower$package ) );
  2337.                     if!empty$this->mPackages[$package]['required'&& $this->mPackages[$package]['active_switch'!= 'y' {
  2338.                         // we have a disabled required package. turn it back on!
  2339.                         $this->storeConfig'package_' $package'y'$package );
  2340.                         $this->mPackages[$package]['active_switch'$this->getConfig'package_' $package );
  2341.                     elseif!empty$this->mPackages[$package]['required'&& $this->mPackages[$package]['installed'&&  $this->getConfig'package_'.$package != 'i' &&  $this->getConfig'package_'.$package != 'y' {
  2342.                         $this->storeConfig'package_' $package'i'$package );
  2343.                     elseif!empty$this->mPackages[$package]['installed'&& !$this->isFeatureActive'package_'.strtolower$package ) ) ) {
  2344.                         // set package to i if it is installed but not isFeatureActive (common when re-installing packages)
  2345.                         $this->storeConfig'package_' $package'i'$package );
  2346.                         if$version $this->getLatestUpgradeVersion$package ) ) {
  2347.                             $this->storeVersion$package$version );
  2348.                             $this->registerPackageVersion$package$version );
  2349.                             $this->mPackages[$package]['info']['version'$version;
  2350.                             unset$this->mPackages[$package]['info']['upgrade');
  2351.                         }
  2352.                     }
  2353.                 }
  2354.             }
  2355.             $ret['unused'$unusedTables;
  2356.         }
  2357.         return $ret;
  2358.     }
  2359.     // }}}
  2360.  
  2361.     // {{{=========================== Date and time methods ==============================
  2362.     /**
  2363.      * Retrieve a current UTC timestamp
  2364.      * Simple map to BitDate object allowing tidy display elsewhere
  2365.      */
  2366.     function getUTCTime({
  2367.         return    $this->mServerTimestamp->getUTCTime();
  2368.     }
  2369.  
  2370.     /**
  2371.      * Retrieve a current UTC ISO timestamp
  2372.      * Simple map to BitDate object allowing tidy display elsewhere
  2373.      */
  2374.     function getUTCTimestamp({
  2375.         return    $this->mServerTimestamp->getUTCTimestamp();
  2376.     }
  2377.  
  2378.     /**
  2379.      * Retrieves the user's preferred offset for displaying dates.
  2380.      */
  2381.     function get_display_offset$pUser FALSE {
  2382.         return $this->mServerTimestamp->get_display_offset$pUser );
  2383.     }
  2384.  
  2385.     /**
  2386.      * Retrieves the user's preferred long date format for displaying dates.
  2387.      */
  2388.     function get_long_date_format({
  2389.         static $site_long_date_format FALSE;
  2390.  
  2391.         if!$site_long_date_format {
  2392.             $site_long_date_format $this->getConfig'site_long_date_format''%A %d of %B, %Y' );
  2393.         }
  2394.  
  2395.         return $site_long_date_format;
  2396.     }
  2397.  
  2398.     /**
  2399.      * Retrieves the user's preferred short date format for displaying dates.
  2400.      */
  2401.     function get_short_date_format({
  2402.         static $site_short_date_format FALSE;
  2403.  
  2404.         if!$site_short_date_format {
  2405.             $site_short_date_format $this->getConfig'site_short_date_format''%d %b %Y' );
  2406.         }
  2407.  
  2408.         return $site_short_date_format;
  2409.     }
  2410.  
  2411.     /**
  2412.      * Retrieves the user's preferred long time format for displaying dates.
  2413.      */
  2414.     function get_long_time_format({
  2415.         static $site_long_time_format FALSE;
  2416.  
  2417.         if!$site_long_time_format {
  2418.             $site_long_time_format $this->getConfig'site_long_time_format''%H:%M:%S %Z' );
  2419.         }
  2420.  
  2421.         return $site_long_time_format;
  2422.     }
  2423.  
  2424.     /**
  2425.      * Retrieves the user's preferred short time format for displaying dates.
  2426.      */
  2427.     function get_short_time_format({
  2428.         static $site_short_time_format FALSE;
  2429.  
  2430.         if!$site_short_time_format {
  2431.             $site_short_time_format $this->getConfig'site_short_time_format''%H:%M %Z' );
  2432.         }
  2433.  
  2434.         return $site_short_time_format;
  2435.     }
  2436.  
  2437.     /**
  2438.      * Retrieves the user's preferred long date/time format for displaying dates.
  2439.      */
  2440.     function get_long_datetime_format({
  2441.         static $long_datetime_format FALSE;
  2442.  
  2443.         if!$long_datetime_format {
  2444.             $long_datetime_format $this->getConfig'site_long_datetime_format''%A %d of %B, %Y (%H:%M:%S %Z)' );
  2445.         }
  2446.  
  2447.         return $long_datetime_format;
  2448.     }
  2449.  
  2450.     /**
  2451.      * Retrieves the user's preferred short date/time format for displaying dates.
  2452.      */
  2453.     function get_short_datetime_format({
  2454.         static $short_datetime_format FALSE;
  2455.  
  2456.         if!$short_datetime_format {
  2457.             $short_datetime_format $this->getConfig'site_short_datetime_format''%a %d of %b, %Y (%H:%M %Z)' );
  2458.         }
  2459.  
  2460.         return $short_datetime_format;
  2461.     }
  2462.  
  2463.     /*
  2464.      * Only used in rang_lib.php which needs tidying up to use smarty templates
  2465.      */
  2466.     function get_long_datetime$pTimestamp$pUser FALSE {
  2467.         return $this->mServerTimestamp->strftime$this->get_long_datetime_format()$pTimestamp$pUser );
  2468.     }
  2469.     // }}}
  2470.     /**
  2471.      * getBitVersion will fetch the version of bitweaver as set in kernel/config_defaults_inc.php
  2472.      *
  2473.      * @param boolean $pIncludeLevel Return bitweaver version including BIT_LEVEL
  2474.      * @access public
  2475.      * @return string bitweaver version set in kernel/config_defaults_inc.php
  2476.      */
  2477.     function getBitVersion$pIncludeLevel TRUE {
  2478.         $ret BIT_MAJOR_VERSION.".".BIT_MINOR_VERSION.".".BIT_SUB_VERSION;
  2479.         if$pIncludeLevel && definedBIT_LEVEL && BIT_LEVEL != '' {
  2480.             $ret .= '-'.BIT_LEVEL;
  2481.         }
  2482.         return $ret;
  2483.     }
  2484.  
  2485.     /**
  2486.      * checkBitVersion Check for new version of bitweaver
  2487.      *
  2488.      * @access public
  2489.      * @return returns an array with information on bitweaver version
  2490.      */
  2491.     function checkBitVersion({
  2492.         $local $this->getBitVersionFALSE );
  2493.         $ret['local'$local;
  2494.  
  2495.         $error['number'0;
  2496.         $error['string'$data '';
  2497.  
  2498.         // cache the bitversion.txt file locally and update only once a day
  2499.         // if you don't have a connection to bitweaver.org, you can set a cronjob to 'touch' this file once a day to avoid waiting for a timeout.
  2500.         if!is_fileTEMP_PKG_PATH.'bitversion.txt' || time(filemtimeTEMP_PKG_PATH.'bitversion.txt' )) 86400 {
  2501.             if$h fopenTEMP_PKG_PATH.'bitversion.txt''w' )) {
  2502.                 $data bit_http_request'http://www.bitweaver.org/bitversion.txt' );
  2503.                 if!preg_match"/not found/i"$data )) {
  2504.                     fwrite$h$data );
  2505.                     fclose$h );
  2506.                 }
  2507.             }
  2508.         }
  2509.  
  2510.         ifis_readableTEMP_PKG_PATH.'bitversion.txt' ) ) {
  2511.             $h fopenTEMP_PKG_PATH.'bitversion.txt''r' );
  2512.             ifisset$h ) ) {
  2513.                 $data fread$h1024 );
  2514.                 fclose$h );
  2515.             }
  2516.  
  2517.             // nuke all lines that don't just contain a version number
  2518.             $lines explode"\n"$data );
  2519.             foreach$lines as $line {
  2520.                 ifpreg_match"/^\d+\.\d+\.\d+$/"$line ) ) {
  2521.                     $versions[$line;
  2522.                 }
  2523.             }
  2524.  
  2525.             if!empty$data && !empty$versions && preg_match"/\d+\.\d+\.\d+/"$versions[0) ) {
  2526.                 sort$versions );
  2527.                 foreach$versions as $version {
  2528.                     ifpreg_match"/^".BIT_MAJOR_VERSION."\./"$version ) ) {
  2529.                         $ret['compare'version_compare$local$version );
  2530.                         $ret['upgrade'$version;
  2531.                         $ret['page'preg_replace"/\.\d+$/"""$version );
  2532.                     }
  2533.                 }
  2534.                 // check if there have been any major releases
  2535.                 $release explode'.'array_pop$versions ) );
  2536.                 if$release[0BIT_MAJOR_VERSION {
  2537.                     $ret['release'implode'.'$release );
  2538.                     $ret['page'$release[0].'.'.$release[1];
  2539.                 elseif$release[0BIT_MAJOR_VERSION {
  2540.                     $ret['compare'version_compare$local$version );
  2541.                     $ret['upgrade'$version;
  2542.                 }
  2543.             else {
  2544.                 $error['number'1;
  2545.                 $error['string'tra'No version information available. Check your connection to bitweaver.org' );
  2546.             }
  2547.         }
  2548.         // append any release level
  2549.         $ret['local'.= ' '.BIT_LEVEL;
  2550.         $ret['error'$error;
  2551.         return $ret;
  2552.     }
  2553.  
  2554.     // should be moved somewhere else. unbreaking things for now - 25-JUN-2005 - spiderr
  2555.     // \TODO remove html hardcoded in diff2
  2556.     function diff2$page1$page2 {
  2557.         $page1 split"\n"$page1 );
  2558.         $page2 split"\n"$page2 );
  2559.         $z new WikiDiff$page1$page2 );
  2560.         if$z->isEmpty() ) {
  2561.             $html '<hr /><br />['.tra("Versions are identical").']<br /><br />';
  2562.         else {
  2563.             //$fmt = new WikiDiffFormatter;
  2564.             $fmt new WikiUnifiedDiffFormatter;
  2565.             $html $fmt->format$z$page1 );
  2566.         }
  2567.         return $html;
  2568.     }
  2569.  
  2570.     /**
  2571.      * getIncludeFiles will get a set of available files with a given filename
  2572.      *
  2573.      * @param array $pPhpFile name of php file
  2574.      * @param array $pTplFile name of tpl file
  2575.      * @access public
  2576.      * @return array of includable files
  2577.      */
  2578.     function getIncludeFiles$pPhpFile NULL$pTplFile NULL {
  2579.         $ret array();
  2580.         global $gBitSystem;
  2581.         foreach$gBitSystem->mPackages as $package {
  2582.             if$gBitSystem->isPackageActive$package['name')) {
  2583.                 if!empty$pPhpFile )) {
  2584.                     $php_file $package['path'].$pPhpFile;
  2585.                     ifis_readable$php_file ))  {
  2586.                         $ret[$package['name']]['php'$php_file;
  2587.                     }
  2588.                 }
  2589.  
  2590.                 if!empty$pTplFile )) {
  2591.                     $tpl_file $package['path'].'templates/'.$pTplFile;
  2592.                     ifis_readable$tpl_file )) {
  2593.                         $ret[$package['name']]['tpl''bitpackage:'.$package['name'].'/'.$pTplFile;
  2594.                     }
  2595.                 }
  2596.             }
  2597.         }
  2598.         return $ret;
  2599.     }
  2600. }
  2601.  
  2602. /* Function for sorting AppMenu by menu_position */
  2603. function bit_system_menu_sort$a$b {
  2604.     $pa empty$a['menu_position'$a['menu_position'];
  2605.     $pb empty$b['menu_position'$b['menu_position'];
  2606.  
  2607.     if$pa == && $pb == {
  2608.         returnstrcmp$pb['menu_title']$pa['menu_title'));
  2609.     }
  2610.     return $pa $pb;
  2611. }
  2612.  
  2613. /* vim: :set fdm=marker : */
  2614. ?>

Documentation generated on Wed, 29 Jul 2015 13:56:02 +0000 by phpDocumentor 1.5.0-lsces