8cad34652f19e81b084877e902a4aadd5079e761
[pear] / HTML / FlexyFramework.php
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4: */
3 // +----------------------------------------------------------------------+
4 // | PHP Version 4                                                        |
5 // +----------------------------------------------------------------------+
6 // | Copyright (c) 1997-2002 The PHP Group                                |
7 // +----------------------------------------------------------------------+
8 // | This source file is subject to version 2.02 of the PHP license,      |
9 // | that is bundled with this package in the file LICENSE, and is        |
10 // | available at through the world-wide-web at                           |
11 // | http://www.php.net/license/2_02.txt.                                 |
12 // | If you did not receive a copy of the PHP license and are unable to   |
13 // | obtain it through the world-wide-web, please send a note to          |
14 // | license@php.net so we can mail you a copy immediately.               |
15 // +----------------------------------------------------------------------+
16 // | Authors:  Alan Knowles <alan@akbkhome.com>                           |
17 // +----------------------------------------------------------------------+
18 //
19 // $Id: FlexyFramework.php,v 1.8 2003/02/22 01:52:50 alan Exp $
20 //
21 //  Description
22 //  A Page (URL) to Object Mapper
23 //  Cleaned up version.. - for use on new projects -- not BC!! beware!!!
24
25
26 //-----------------------------------------------------------
27 // Debian APACHE - some idiot disabled AcceptPathInfo - it needs adding back.
28 //-----------------------------------------------------------
29
30  
31  
32 // Initialize Static Options
33 require_once 'PEAR.php';
34 require_once 'HTML/FlexyFramework/Page.php';  
35 require_once 'HTML/FlexyFramework/Error.php';
36 // better done here..
37 require_once 'DB/DataObject.php';
38
39 // To be removed ?? or made optional or something..
40  
41
42 // remove E_ANAL  
43  
44 error_reporting(E_ALL & ~E_STRICT );
45 //ini_set('display_errors','off');
46 //ini_set('log_errors','off');
47
48 //PEAR::setErrorHandling(PEAR_ERROR_TRIGGER, E_USER_ERROR);
49
50
51
52
53 /**
54 * The URL to Object Mapper
55 *
56 * Usage:
57 * Create a index.php and add these lines.
58 *  
59 * ini_set("include_path", "/path/to/application"); 
60 * require_once 'HTML/FlexyFramework.php';
61 * HTML_FlexyFramework::factory(array("dir"=>"/where/my/config/dir/is");
62 *
63 *
64 * the path could include pear's path, if you dont install all the pear 
65 * packages into the development directory.
66 *
67 * It attempts to load a the config file from the includepath, 
68 * looks for ConfigData/default.ini
69 * or ConfigData/{hostname}.ini
70 * if your file is called staging.php rather than index.php 
71 * it will try staging.ini
72 *
73 */
74 #[AllowDynamicProperties]
75 class HTML_FlexyFramework {
76     
77     /**
78      * Confirgurable items..
79      * If we set them to 'true', they must be set, otherwise they are optional.
80      */
81     var $project; // base class name
82     var $database; // set to true even if nodatabase=true
83     
84     // optional
85     var $debug = false;
86     var $enable = false; // modules
87     var $disable = false; // modules or permissions
88     var $appName = false;
89     var $appNameShort = false; // appname (which has templates)
90     var $version = false; // give it a version name. (appended to compile dir)
91     var $nodatabase = false; // set to true to block db config and testing.
92     var $fatalAction = false; // page to redirct to on failure. (eg. databse down etc.)
93     var $charset = false; // default UTF8
94     var $dataObjectsCache = true;  // use dataobjects ini cache.. - let's try this as the default behaviour...
95     var $dataObjectsCacheExpires = 72000; // 20 hours..
96     var $languages = false; // language settings -- see _handlelanguage
97     var $projectExtends = false; // if this is an array, it's a fallback of 'Projects' that can be called
98     var $database_is_readonly = false;
99      
100
101     
102     // derived.
103     var $cli = false; // from cli 
104     var $run = false; // from cli
105     var $enableArray = false; // from enable.
106     var $classPrefix = false; // from prject.
107     var $baseDir = false ; // (directory+project)
108     var $rootDir = false ; // (directory that index.php is in!)
109     
110     var $baseURL = false;
111     var $rootURL = false ; // basename($baseURL)
112     
113     var $page = false; // active page..
114     var $timer = false; // the debug timer
115     var $calls = false; // the number of calls made to run!
116     var $start = false; // the start tiem.
117     
118     var $baseRequest = '';
119     var $ext; // the striped extention.
120     
121     var $dataObjectsOriginalIni = ''; // 1 houre..
122     
123     // used to be $_GLOBALS[__CLASS__]
124     
125     static $singleton; 
126     
127     
128     /**
129      * 
130      * Constructor - with assoc. array of props as option
131      * called by index.php usually, and runs the app code,
132      *
133      * uses 'universal construcor' format, so the argument relates directly to properties of this object.
134      * 
135      */
136     
137     
138     function __construct($config)
139     {
140         if (isset(self::$singleton)) {
141             trigger_error("FlexyFramework Construct called twice!", E_ERROR);
142         }
143         
144         self::$singleton = $this;
145         
146         $this->calls = 0;
147
148         $m = explode(' ',microtime());
149         $this->start = $m[0] + $m[1];
150         
151         $config = $this->loadModuleConfig($config);
152         
153         foreach($config as $k=>$v) {
154             $this->$k = $v;
155         }
156         $this->_parseConfig();
157
158         // echo '<PRE>'; print_r($this);exit;
159         if ($this->cli) {
160             $args = $_SERVER['argv'];
161             array_shift($args );
162             array_shift($args );
163             $this->_run($this->run,false,$args);
164             return;
165         }
166
167         // handle apache mod_rewrite..
168         // it looks like this might not work anymore..
169         
170         /*
171          *
172 <IfModule mod_rewrite.c>
173 RewriteEngine On
174 RewriteBase /
175 RewriteRule ^/web.hpasite/index\.local.php$ - [L]
176 RewriteCond %{REQUEST_FILENAME} !-f
177 RewriteCond %{REQUEST_FILENAME} !-d
178 RewriteRule ^(.+)$ /web.hpasite/index.local.php [L,NC,E=URL:$1]
179 </IfModule>
180 */ 
181         
182         if (!empty($_SERVER['REDIRECT_STATUS'])  && !empty($_SERVER['REDIRECT_URL'])) {
183           // phpinfo();exit;
184             $sn = $_SERVER['SCRIPT_NAME'];
185             $sublen = strlen(substr($sn , 0,  strlen($sn) - strlen(basename($sn)) -1));
186             //var_dump(array($sn,$subdir,basename($sn)));exit;
187           
188             //var_dump($_SERVER['SCRIPT_NAME'] . substr($_SERVER['REDIRECT_URL'],$sublen));
189             $this->_run($_SERVER['SCRIPT_NAME'] .  substr($_SERVER['REDIRECT_URL'], $sublen),false);
190             return ;
191         }
192         // eg... /web.hpasite/index.local.php/Projects
193          $this->_run($_SERVER['REQUEST_URI'],false);
194             
195         
196     }
197     /**
198      * This is the standard way to get information about the application settings.
199      * $ff = HTML_FlexyFramework::get();
200      * if ($ff->SomeVar[...])....
201      *
202      */
203     static function get()
204     {
205         return self::$singleton;
206     }
207     /*
208      * looks for files in the path and load up the default values for config?
209      */
210     function loadModuleConfig($cfg)
211     {
212          
213         $proj = $cfg['project'];
214         $rootDir = realpath(dirname($_SERVER["SCRIPT_FILENAME"]));
215         
216         $cls = $proj.'_Config';
217         
218         
219         
220          if (file_exists($rootDir . '/'.str_replace('_','/', $cls). '.php')) {
221             require_once str_replace('_','/', $cls). '.php';
222             $c = new $cls();
223             if (method_exists($c,'init')) {
224                 $cfg = $c->init($this,$cfg);
225             }
226         }
227         if (empty($cfg['enable'])) {
228             return $cfg;
229         }
230         foreach(explode(',',$cfg['enable']) as $m) {
231             $cls = $proj.'_'. $m . '_Config';
232
233             if (!file_exists($rootDir . '/'.str_replace('_','/', $cls). '.php')) {
234                 continue;
235             }
236             require_once str_replace('_','/', $cls). '.php';
237             $c = new $cls();
238             if (method_exists($c,'init')) {
239                 $cfg = $c->init($this,$cfg);
240             }
241         }
242         return $cfg;
243     }
244     
245   
246     /**
247      * parse the configuration set by the constructor.
248      * 
249      *
250      */
251   
252     function _parseConfig()
253     {
254         
255         // make sure required values are set.. (anything that is not defaulted to false..)
256         foreach(get_class_vars(__CLASS__) as $k =>$v) {
257             if ($v === false && !isset($this->$k)) {
258                 die("$k is not set");
259             }
260         }
261         
262         
263         // enable modules.
264         if (!empty($this->enable)) {
265             $this->enableArray = explode(',', $this->enable);
266             
267             if (!in_array('Core',$this->enableArray ) &&
268                 !in_array('Core', explode(',', $this->disable ? $this->disable : '')))
269             {
270                 $this->enable = 'Core,'. $this->enable ;
271                 $this->enableArray = explode(',', $this->enable);
272             }
273         }
274         // are we running cli?
275         $this->cli = php_sapi_name() == 'cli'; 
276         
277         // will these work ok with cli?
278         $bits = explode(basename($_SERVER["SCRIPT_FILENAME"]), $_SERVER["SCRIPT_NAME"]);
279         if (!$this->cli) {
280             $bits[0] = str_replace('%2F','/',urlencode($bits[0]));
281             $this->baseURL = $bits[0] . basename($_SERVER["SCRIPT_FILENAME"]);
282             // however this is not correct if we are using rewrite..
283             if (!empty($_SERVER['REDIRECT_STATUS'])  && !empty($_SERVER['REDIRECT_URL'])) {
284                 $this->baseURL = substr($bits[0],0,-1); // without the trailing '/' ??
285                 $this->rootURL = $bits[0] == '/' ? '' : $bits[0];
286                 //$this->baseURL = $this->baseURL == '' ? '/' : $this->baseURL;
287                 
288             }
289             //phpinfo();exit;
290             // is this bit used??
291             //if (empty($_SERVER['SCRIPT_NAME'])) {
292                 
293             //    $this->baseURL = ''; // ??? this is if we replace top level...
294             //}
295         }
296         // if cli - you have to have set baseURL...
297         
298         
299         $this->rootDir = realpath(dirname($_SERVER["SCRIPT_FILENAME"]));
300         $this->baseDir = $this->rootDir .'/'. $this->project;
301         if (empty($this->rootURL)) {
302             $this->rootURL = dirname($this->baseURL); 
303             $this->rootURL = ($this->rootURL == '/') ? '' : $this->rootURL;
304         }
305          
306       
307         //var_dump($this->baseURL);
308         
309         if (!isset($this->database) && isset($this->DB_DataObject['database'])) {
310             $this->database = $this->DB_DataObject['database'];
311         }
312         
313          $this->classPrefix   = str_replace('/', '_', $this->project) . '_';
314          // list the available options..
315         if ($this->cli && empty($_SERVER['argv'][1])) {
316             require_once 'HTML/FlexyFramework/Cli.php';
317             $fcli = new HTML_FlexyFramework_Cli($this);
318             $fcli->cliHelp();
319             exit;
320         }
321         
322         
323         // see if it's a framework assignment.
324         $ishelp = false;
325         if ($this->cli) {
326             require_once 'HTML/FlexyFramework/Cli.php';
327             $fcli = new HTML_FlexyFramework_Cli($this);
328             $res = $fcli->parseDefaultOpts();
329             if ($res === true) {
330                 $ishelp = true;
331             }
332              
333         }
334         
335         
336         $this->run = $this->cli ? $_SERVER['argv'][1] : false;
337      
338         
339         $this->_parseConfigDataObjects();
340         if ($this->dataObjectsCache && !$this->nodatabase) {
341             $this->_configDataObjectsCache();
342         }
343         
344         $this->_parseConfigTemplate();
345         $this->_parseConfigMail();
346  
347         //echo '<PRE>';print_r($this);exit;
348         
349         $this->_exposeToPear();
350                 
351
352         $this->_validateEnv();
353         
354         if ($ishelp) {
355             return;
356         }
357
358         $this->_validateDatabase();
359
360         $this->_validateTemplate();
361         
362     }
363     /**
364      *
365      *
366      *'languages' => array(
367             'param' => '_lang',
368             'avail' => array('en','zh_HK', 'zh_CN'),
369             'default' => 'en',
370             'cookie' => 'TalentPricing_lang',
371             'localemap' => array(
372                 'en' => 'en_US.utf8',
373                 'zh_HK' => 'zh_TW.utf8',
374                 'zh_CN' => 'zh_CN.utf8',
375             )
376         ),
377     */
378     
379     function _handleLanguages($request)
380     {
381         if (
382             empty($this->languages) ||
383             (
384                     !isset($this->languages['cookie']) && !isset($this->languages['default'])
385             )
386         ) {
387             return;
388         }
389         
390         $cfg = $this->languages;
391         
392         $default = $cfg['default'];
393         
394         if(!empty($_SERVER["HTTP_ACCEPT_LANGUAGE"])){
395             
396             $brower_langs = explode(",", $_SERVER["HTTP_ACCEPT_LANGUAGE"]);
397             
398             foreach ($brower_langs as $bl) {
399                 $l = preg_replace('/;(.*)/', '', $bl);
400                 
401                 $l = str_replace('-', '_', $l);
402                 
403                 if(!in_array($l, $cfg['avail'])){
404                     continue;
405                 }
406                 
407                 $default = $l;
408                 break;
409             }
410         }
411            
412         $lang = isset($_COOKIE[$cfg['cookie']]) ?  $_COOKIE[$cfg['cookie']] : $default;
413
414         // handle languages in request..
415         $bits = explode('/', $request);
416         $redirect_to = false;
417         if (count($bits) && in_array($bits[0],$cfg['avail'])) {
418             // redirect..
419             $lang = array_shift($bits);
420             $redirect_to = implode('/', $bits);
421         }
422         
423          
424         
425         if (isset($_REQUEST[$cfg['param']])) {
426             $lang = $_REQUEST[$cfg['param']];
427         }
428     
429         if (!in_array($lang, $cfg['avail'])) {
430             $lang = $cfg['default'];
431         }
432         if (isset($cfg['localemap'][$lang])) {
433             setlocale(LC_ALL, $cfg['localemap'][$lang]);
434         }
435         setcookie($cfg['cookie'], $lang, 0, '/');
436         
437         $this->locale = $lang;
438         
439         if (!empty($this->HTML_Template_Flexy)) {
440             $this->HTML_Template_Flexy['locale'] = $lang;   //set a language for template engine
441         }
442         if ($redirect_to !== false) {
443             header('Location: ' . $this->rootURL . '/'.$redirect_to );
444             exit;
445          
446         }
447     }
448     
449     function parseDefaultLanguage($http_accept, $deflang = "en") 
450     {
451         if(isset($http_accept) && strlen($http_accept) > 1)  {
452            # Split possible languages into array
453            $x = explode(",",$http_accept);
454            
455            foreach ($x as $val) {
456               #check for q-value and create associative array. No q-value means 1 by rule
457               if(preg_match("/(.*);q=([0-1]{0,1}.\d{0,4})/i",$val,$matches))
458                  $lang[$matches[1]] = (float)$matches[2];
459               else
460                  $lang[$val] = 1.0;
461            }
462            
463            #return default language (highest q-value)
464            $qval = 0.0;
465            foreach ($lang as $key => $value) {
466               if ($value > $qval) {
467                  $qval = (float)$value;
468                  $deflang = $key;
469               }
470            }
471         }
472         return strtolower($deflang);
473      }
474     
475     /**
476      * overlay array properties..
477      */
478     
479     function applyIf($prop, $ar)
480     {
481         if (!isset($this->$prop)) {
482             $this->$prop = $ar;
483             return;
484         }
485         // add only things that where not set!!!.
486         $this->$prop = array_merge($ar,$this->$prop);
487         
488         return;
489         //foreach($ar as $k=>$v) {
490         //    if (!isset($this->$prop->$k)) {
491          //       $this->$prop->$k = $v;
492           //  }
493        // }
494     }
495     
496     /**
497      * DataObject cache 
498      * - if turned on (dataObjectsCache = true) then 
499      *  a) ini file points to a parsed version of the structure.
500      *  b) links.ini is a merged version of the configured link files.
501      * 
502      * This only will force a generation if no file exists at all.. - after that it has to be called manually 
503      * from the core page.. - which uses the Expires time to determine if regeneration is needed..
504      * 
505      * 
506      */
507     
508     function _configDataObjectsCache()
509     {
510         // cli works under different users... it may cause problems..
511         
512         $this->debug(__METHOD__);
513         
514         if ($this->database === false) {
515             return;
516         }
517         
518         if (function_exists('posix_getpwuid')) {
519             $uinfo = posix_getpwuid( posix_getuid () ); 
520             $user = $uinfo['name'];
521         } else {
522             $user = getenv('USERNAME'); // windows.
523         }
524         
525         
526
527         $iniCache = ini_get('session.save_path') .'/' . 
528                'dbcfg-' . $user . '/'. str_replace('/', '_', $this->project);
529         
530         
531         if ($this->appNameShort) {
532             $iniCache .= '_' . $this->appNameShort;
533         }
534         if ($this->version) {
535             $iniCache .= '.' . $this->version;
536         }
537        
538         
539         $dburl = parse_url($this->database);
540         if (!empty($dburl['path'])) {
541             $iniCache .= '-'.ltrim($dburl['path'],'/');
542         }
543         
544         $iniCache .= '.ini';
545         $this->debug(__METHOD__ . " : ini cache : $iniCache");
546         
547         $dburl = parse_url($this->database);
548         $dbini = 'ini_'. basename($dburl['path']);
549         $this->debug(__METHOD__ . " : ini file : $dbini");
550         //override ini setting... - store original..
551         if (isset($this->DB_DataObject[$dbini])) {
552             $this->dataObjectsOriginalIni = $this->DB_DataObject[$dbini];
553             ///print_r($this->DB_DataObject);exit;
554         }
555           
556          
557         $this->DB_DataObject[$dbini] =   $iniCache;
558         // we now have the configuration file name..
559         
560         
561         if (!file_exists($iniCache) || empty( $this->dataObjectsCacheExpires)) {
562             $this->debug(__METHOD__ . ':calling generate do cache');
563             $this->generateDataobjectsCache(true);
564             return;
565         }
566      
567         
568         
569     }
570     /**
571      *  _generateDataobjectsCache:
572      * 
573      * create xxx.ini and xxx.links.ini 
574      * 
575      * @arg force (boolean) force generation - default false;
576      * 
577      */
578      
579     function generateDataobjectsCache($force = false)
580     {
581         //$this->debug('generateDataobjectsCache: force=' . ($force ? 'yes' : 'no'));
582         if (!$this->dataObjectsCache) { // does not use dataObjects Caching..
583             $this->debug('generateDataobjectsCache: dataObjectsCache - empty');
584             return;
585         }
586         
587         $dburl = parse_url($this->database);
588         $dbini = 'ini_'. basename($dburl['path']);
589         
590         
591         $iniCache = $this->DB_DataObject[$dbini];
592         $this->debug('generateDataobjectsCache:' .dirname($iniCache).'/*.ini');
593         
594         $replace = array();
595         
596         if (file_exists($iniCache)) {
597             $files = glob(dirname($iniCache).'/*.ini');
598             foreach($files as $f) {
599                 $replace[$f] = md5(file_get_contents($f)); // hash it..
600                
601             }
602         }
603         $this->debug('generateDataobjectsCache: DONE ini delete');
604         
605         $iniCacheTmp = $iniCache . '.tmp' .md5(rand());  // random to stop two processes using the same file.
606         // has it expired..
607         $force = ($force ? $force : !file_exists($iniCache)) || !$this->dataObjectsCacheExpires;
608         // $this->debug('generateDataobjectsCache: after check : force=' . ($force ? 'yes' : 'no'));
609          // not force or not expired, do not bother..
610         if (!$force) {
611             if ((filemtime($iniCache) + $this->dataObjectsCacheExpires) >time()) {
612                 return;
613             }
614         }
615         
616         
617         
618          //echo "GENERATE?";
619         
620         // force quoting of column names..
621         // unless it forced off..
622         if (!isset($this->DB_DataObject['quote_identifiers_tableinfo'] )) { 
623             $this->DB_DataObject['quote_identifiers_tableinfo'] = true;
624         }
625         if (!file_exists(dirname($iniCache))) {
626             if (!mkdir(dirname($iniCache),0700, true)) {
627                 die("Failed to make cache directory : $iniCache\n");
628             }
629         }
630         
631         $this->DB_DataObject[$dbini] = $iniCacheTmp;
632         
633         $dl = DB_DataObject::DebugLevel();
634         $this->_exposeToPear(); // this will reset the debug level...
635         DB_DataObject::DebugLevel($dl);
636         
637         $this->debug('generateDataobjectsCache: running generator');
638         // DB_DataObject::debugLevel(1);      
639         require_once 'HTML/FlexyFramework/Generator.php';
640         $generator = new HTML_FlexyFramework_Generator();
641         $generator->start();
642         $this->debug('generateDataobjectsCache: done generator');
643
644         HTML_FlexyFramework_Generator::writeCache($iniCacheTmp, $iniCache, $replace); 
645         // reset the cache to the correct lcoation.
646         $this->DB_DataObject[$dbini] = $iniCache;
647         
648          
649
650         $this->_exposeToPear();
651         DB_DataObject::DebugLevel($dl);
652
653         //$GLOBALS['_DB_DATAOBJECT']['INI'][$this->database] =   parse_ini_file($iniCache, true);
654         //$GLOBALS['_DB_DATAOBJECT']['SEQUENCE']
655         // clear any dataobject cache..
656          
657         
658         //die("done");
659         
660     }
661     /**
662      * DataObject Configuration:
663      * Always in Project/DataObjects
664      * unless enableArray is available...
665      * 
666      * 
667      * 
668      */
669     function _parseConfigDataObjects()
670     {
671         if ($this->nodatabase && !$this->database) {
672             return;
673         }
674         $dburl = parse_url($this->database);
675         $dbini = 'ini_'. basename($dburl['path']);
676                 
677         $dbinis =  array(); //array(dirname(__FILE__) . '/Pman/DataObjects/pman.ini');
678         $dbreq =  array(); //array( dirname(__FILE__) . '/Pman/DataObjects/');
679         $dbcls =  array(); //array('Pman_DataObjects_');
680
681         $project = explode('/',$this->project)[0]; 
682         
683         if (!empty($this->enableArray)) {
684                 
685             $tops = array_merge( array($project), empty($this->projectExtends) ? array() : $this->projectExtends);
686             
687             foreach($tops as $td) {
688                     
689                 $bd = $this->rootDir .'/'.$td;
690                 foreach($this->enableArray as $m) {
691                     // look in Pman/MODULE/DataObjects/*
692                      if (file_exists($bd.'/'.$m.'/DataObjects')) {
693                         $dbinis[] = $bd.'/'.$m.'/DataObjects/'. strtolower($project).'.ini';
694                         $dbcls[] = $td.'_'. $m . '_DataObjects_';
695                         $dbreq[] = $bd.'/'.$m.'/DataObjects';
696                         continue;
697                     }
698                     // look in MODULE/DataObjects ?? DO WE SUPPORT THIS ANYMORE???
699                     if (file_exists($bd.'/../'.$m.'/DataObjects')) {
700                         $dbinis[] = $bd.'/../'.$m.'/DataObjects/'. strtolower($project).'.ini';
701                         $dbcls[] = $td. '_DataObjects_';
702                         $dbreq[] = $bd.'/../'.$m.'/DataObjects';
703                     }
704                         
705                         
706                       
707                 }
708             }     
709         } else {
710             
711             if (isset($this->DB_DataObject['schema_location'])) {
712                 $dbinis[] = $this->DB_DataObject['schema_location'] .'/'.basename($dburl['path']).'.ini';
713             } else {
714                 $dbinis[] = $this->baseDir.'/DataObjects/'.basename($dburl['path']).'.ini';
715             }
716             // non modular.
717             
718             $dbcls[] = $project .'_DataObjects_';
719             $dbreq[] = $this->baseDir.'/DataObjects';
720         }
721             
722         
723         $this->applyIf('DB_DataObject', array(   
724         
725             'class_location' =>  implode(PATH_SEPARATOR,$dbreq),
726             'class_prefix' =>  implode(PATH_SEPARATOR,$dbcls),
727             'database'        => $this->database,    
728             ///'require_prefix' => 
729          //   'schema_location' => dirname(__FILE__) . '/Pman/DataObjects/',
730              $dbini=> implode(PATH_SEPARATOR,$dbinis),
731          
732            //   'debug' => 5,
733         ));
734       //  print_r($this->DB_DataObject);exit;
735     }
736     /**
737      Set up thetemplate
738      * 
739      */
740     function _parseConfigTemplate()
741     {
742         
743         // compile.
744         if (function_exists('posix_getpwuid')) {
745             $uinfo = posix_getpwuid( posix_getuid () ); 
746          
747             $user = $uinfo['name'];
748         } else {
749             $user = getenv('USERNAME'); // windows.
750         }
751         
752         $compileDir = ini_get('session.save_path') .'/' . 
753             $user . '_compiled_templates_' . $this->project;
754         
755         if ($this->appNameShort) {
756             $compileDir .= '_' . $this->appNameShort;
757         }
758         if ($this->version) {
759             $compileDir .= '.' . $this->version;
760         }
761         
762         // templates. -- all this should be cached!!!
763         $src = array();
764          
765         
766         if ($this->appNameShort && !in_array('Core', explode(',', $this->disable ? $this->disable : ''))) {
767             // in app based version, template directory is in Core
768             
769             $src = array(  
770                 $this->baseDir . '/Core/templates'
771             );
772         }
773         
774         if(!empty($this->projectExtends)){
775             foreach ($this->projectExtends as $e){
776                 $add = $this->rootDir . '/' . $e .'/templates';
777                 if (!in_array($add,$src) && file_exists($add)) {
778                     $src[] = $add;
779                 }
780             }
781         }
782         
783         $src[] = $this->baseDir . '/templates';
784         
785         
786         
787         if (!empty($this->enableArray)) {
788              
789             
790             foreach($this->enableArray as $m) {
791                 $add = $this->baseDir . '/' . $m .'/templates';
792                 if (!in_array($add,$src) && file_exists($add) && $this->appNameShort != $m) {
793                     $src[] = $add;
794                 }
795                 
796             }
797             if (!empty($this->projectExtends)  )  {
798                 foreach ($this->projectExtends as $extend){
799                     foreach($this->enableArray as $m) {
800                         $add = $this->rootDir . '/' . $extend . '/' . $m .'/templates';
801                         if (!in_array($add,$src) && file_exists($add) && $this->appNameShort != $m) {
802                             $src[] = $add;
803                         }
804                     }
805                 }
806     
807             }
808         }
809          
810         
811         if ($this->appNameShort) {
812             $src[] =  $this->baseDir . '/'. $this->appNameShort. '/templates';
813         }
814         
815         // images may come from multiple places: - if we have multiple template directories.?
816         // how do we deal with this..?
817         // images/ << should always be mapped to master!
818         // for overridden appdir ones we will have to se rootURL etc.
819         
820         $url_rewrite = 'images/:'. $this->rootURL . '/'. $this->project. '/templates/images/';
821         
822         $this->applyIf('HTML_Template_Flexy', array(
823             'templateDir' => implode(PATH_SEPARATOR, $src),
824             'compileDir' => $compileDir,
825             'multiSource' => true,
826             'forceCompile' => 0,
827             'url_rewrite' => $url_rewrite,
828             'filters' => 'Php,SimpleTags', /// for non-tokenizer version?
829             'debug' => $this->debug ? 1 : 0,
830             'useTokenizer' => 1,
831              
832             
833         
834         
835         ));
836     } 
837     
838     function _parseConfigMail()
839     {
840         $this->applyIf('HTML_Template_Flexy', array(
841            'debug' => 0,
842            'driver' => 'smtp',
843            'host' => 'localhost',
844            'port' => 25,
845         ));
846     }
847     function _exposeToPear()
848     {
849         $cls = array_keys(get_class_vars(__CLASS__));
850         $base = array();
851         
852         // anything that get's set, that's not in our default properties
853         // is assumed to be an option set .
854         foreach(get_object_vars($this) as $k=>$v) {
855             if (in_array($k,$cls)) {
856                 $base[$k] = $v;
857                 continue;
858             }
859             $options = &PEAR::getStaticProperty($k,'options');
860             $options = $v;
861         }
862         $options = &PEAR::getStaticProperty('HTML_FlexyFramework','options');
863         $options = $base;
864          //   apply them..
865     }
866     
867     
868     function _validateEnv() 
869     {
870         /* have I been initialized */
871         
872         
873         if (version_compare(PHP_VERSION, '7.0.0') < 0  && get_magic_quotes_gpc() && !$this->cli) {
874             $this->fatalError(
875                 "magic quotes is enabled add the line<BR>
876                    php_value magic_quotes_gpc 0<BR>
877                    to your .htaccess file <BR>
878                    (Apache has to be configured to &quot;AllowOverride Options AuthConfig&quot; for the directory)
879                    ");
880                 
881         }
882         // set up error handling - 
883         $this->error = new HTML_FlexyFramework_Error();
884         
885         /// fudge work around bugs in PEAR::setErrorHandling(,)
886         $GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_CALLBACK;
887         $GLOBALS['_PEAR_default_error_options'] = array($this->error,'raiseError');
888         
889         
890         
891         if ($this->debug) {
892             require_once 'Benchmark/Timer.php'; 
893             $this->timer = new BenchMark_Timer(true);
894             register_shutdown_function(function() { echo $this->timer->getOutput(); });
895         }
896
897     }
898     
899     function _validateDatabase()
900     {
901         //echo "<PRE>"; print_r($this);
902
903         if ($this->nodatabase) {
904             return;
905         }
906         $options = &PEAR::getStaticProperty('DB_DataObject','options');
907         $dd = empty($options['dont_die']) ? false : true;
908         $options['dont_die'] = true;
909         
910         // database is the only setting - we dont support mult databses?
911           
912             
913         $x = new DB_Dataobject;
914         $x->_database = $this->database;
915         if (PEAR::isError($err = $x->getDatabaseConnection())) {
916                                 
917
918             $this->fatalError("Configuration or Database Error: could not connect to Database, <BR>
919                 Please check the value given to HTML_FlexyFramework, or run with debug on!<BR>
920                  <BR> ".$err->toString());
921         }
922         // only applies to mysql...
923         
924         if (preg_match('/^mysql/', $this->database)) {
925             $res = $err->query("SELECT @@global.read_only as ro");
926             
927             $row = is_a($res, 'DB_Error') ? false : $res->fetchRow(DB_FETCHMODE_ASSOC);
928             if (!$row || !empty($row['ro'])) {
929                 if (empty($options['skip-read-only-check'])) {
930                     $this->fatalError("Database is configured to be read-only - please check database<BR> ".$err->toString());
931                 }
932                 $this->database_is_readonly = true;
933             }
934         }
935         // reset dont die!
936         $options['dont_die'] = $dd ;
937         
938         
939     }
940     function _validateTemplate()
941     {
942         // check that we have a writeable directory for flexy's compiled templates.
943         
944         if (empty($this->HTML_Template_Flexy['compileDir'])) {
945             return;
946         }
947         clearstatcache();
948         if ( !file_exists($this->HTML_Template_Flexy['compileDir']))  {
949             mkdir($this->HTML_Template_Flexy['compileDir'], 0700, true);
950             clearstatcache();
951              
952             if ( !file_exists($this->HTML_Template_Flexy['compileDir']))  {
953             
954                 $this->fatalError("Configuration Error: you specified a directory that does not exist for<BR>
955                     HTML_Template_Flexy => compileDir  {$this->HTML_Template_Flexy['compileDir']}<BR>\n"
956                 );
957             }
958         }
959         
960         if (!is_writeable($this->HTML_Template_Flexy['compileDir'])) {
961             $this->fatalError("Configuration Error: Please make sure the template cache directory is writeable<BR>
962                     eg. <BR>
963                     chmod 700 {$this->HTML_Template_Flexy['compileDir']}<BR>
964                     chgrp apache_user  {$this->HTML_Template_Flexy['compileDir']}<BR>\n"
965             );
966         }
967         //echo "<PRE>";print_R($config);
968         
969         
970          
971           
972         
973         
974     }
975   
976   
977    
978         
979     
980     
981     /**
982     * Quality Redirector
983     *
984     * Usage in a page.:
985     * HTML_FlexyFramework::run('someurl/someother',array('somearg'=>'xxx'));
986     * ...do clean up...
987     * exit; <- dont cary on!!!!
988     *
989     * You should really
990     * 
991     * @param   string           redirect to url 
992     * @param   array Args Optional      any data you want to send to the next page..
993     * 
994     *
995     * @return   false
996     * @access   public
997     * @static
998     */
999   
1000     
1001     static function run($request,$args=array()) 
1002     {
1003         self::$singleton->_run($request,true,$args);
1004         return false;
1005     }
1006     
1007     
1008     /**
1009     * The main execution loop
1010     *
1011     * recursivly self called if redirects (eg. return values from page start methods)
1012     * 
1013     * @param   string from $_REQUEST or redirect from it'self.
1014     * @param   boolean isRedirect  = is the request a redirect 
1015     *
1016     *
1017     * @return   false || other    false indicates no page was served!
1018     * @access   public|private
1019     * @see      see also methods.....
1020     */
1021   
1022     function _run($request,$isRedirect = false,$args = array()) 
1023     {
1024         
1025         // clean the request up.
1026         $this->calls++;
1027         
1028         if ($this->calls > 5) {
1029             // to many redirections...
1030             trigger_error("FlexyFramework:: too many redirects - backtrace me!",E_USER_ERROR);
1031             exit;
1032         }
1033         
1034         $newRequest = $this->_getRequest($request,$isRedirect);
1035         
1036          
1037         // find the class/file to load
1038         list($classname,$subRequest) = $this->requestToClassName($newRequest,FALSE);
1039         
1040         
1041         $this->debug("requestToClassName return = CLASSNAME: $classname SUB REQUEST: $subRequest");
1042         
1043         // assume that this was handled by getclassname ?????
1044         if (!$classname) {
1045             return false;
1046         }
1047         
1048         // make page data/object accessable at anypoint in time using  this
1049         // not sure if this is used anymore - or even works..?
1050         $classobj = &PEAR::getStaticProperty('HTML_FlexyFramework', 'page');
1051         
1052         $classobj =  new  $classname();  // normally do not have constructors.
1053         
1054         
1055         $classobj->baseURL = $this->baseURL;
1056         $classobj->rootURL = $this->rootURL;
1057         $classobj->rootDir = $this->rootDir;
1058         $classobj->bootLoader  = $this;
1059         $classobj->request = $newRequest;
1060         $classobj->timer = &$this->timer;
1061         $classobj->cli = $this->cli;
1062         
1063         $this->page = $classobj;
1064         if ($this->cli && !$isRedirect ) { // redirect always just takes redirect args..
1065             require_once 'HTML/FlexyFramework/Cli.php';
1066             $fcli = new HTML_FlexyFramework_Cli($this);
1067             $nargs = $fcli->cliParse($classname);
1068             $args = $nargs === false ? $args : $nargs; /// replace if found.
1069             $classobj->cli_args = $nargs;
1070         }
1071         
1072         // echo '<PRE>'; print_r($this);exit;
1073         // echo "CHECK GET AUTH?";
1074
1075         if (!method_exists($classobj, 'getAuth')) {
1076         //    echo "NO GET AUTH?";
1077             $this->fatalError("class $classname does not have a getAuth Method");
1078             return false;
1079         }
1080         
1081         /* check auth on the page */
1082         if (is_string($redirect = $classobj->getAuth())) {
1083             $this->debug("GOT AUTH REDIRECT".$redirect);
1084             return $this->_run($redirect,TRUE);
1085         }
1086         // used HTML_FlexyFramework::run();
1087                  
1088
1089         if ($redirect === false) {
1090             $this->debug("GOT AUTH FALSE");    
1091             return false; /// Access deined!!! - 
1092         }
1093      
1094         // allow the page to implement caching (for the full page..)
1095         // although normally it should implement caching on the outputBody() method.
1096         
1097         if (method_exists($classobj,"getCache")) {
1098             if ($result = $classobj->getCache()) {
1099                 return $result;
1100             }
1101         }
1102                     
1103         /* allow redirect from start */
1104         if (method_exists($classobj,"start")) {
1105             if (is_string($redirect = $classobj->start($subRequest,$isRedirect,$args)))  {
1106                 $this->debug("REDIRECT $redirect <BR>");
1107                 return $this->_run($redirect,TRUE);
1108             }
1109             if ($redirect === false) {
1110                 return false;
1111             }
1112         }
1113                 
1114
1115          // used HTML_FlexyFramework::run();
1116         
1117         /* load the modules 
1118          * Modules are common page components like navigation headers etc.
1119          * that can have dynamic code.
1120          * Code has been removed now..
1121          */
1122         
1123         
1124         if ($this->timer) {
1125             $this->timer->setMarker("After $request loadModules Modules"); 
1126         }
1127         
1128         /* output it  - (our base page does not implement output for cli. */
1129         
1130         if ( method_exists($classobj,'output')) {
1131             $classobj->output(); 
1132         }
1133         
1134         
1135         if ($this->timer) {
1136             $this->timer->setMarker("After $request output"); 
1137             $this->timer->stop(); //?? really - yes...
1138            
1139             
1140         }
1141         
1142         if ($this->cli) {
1143             return true;
1144         }
1145         
1146         
1147         exit; /// die here...
1148         
1149     }
1150     
1151     /**
1152     * map the request into an object and run the page.
1153     *
1154     * The core of the work is done here.
1155     * 
1156     * 
1157     * @param   request  the request string
1158     * @param   boolean isRedirect - indicates that it should not attempt to strip the .../index.php from the request.
1159     * 
1160     * @access  private
1161     */
1162   
1163     function _getRequest($request, $isRedirect) 
1164     {
1165         
1166          
1167         if ($this->cli) {
1168             return $request;
1169         }
1170         
1171         $startRequest = $request;
1172         $ra = explode('?', $request);
1173         $request =  array_shift($ra);
1174         $this->debug("INPUT REQUEST $request<BR>");
1175         if (!$isRedirect) {
1176             // check that request forms contains baseurl????
1177             if (!empty($_SERVER['REDIRECT_STATUS'])  && !empty($_SERVER['REDIRECT_URL'])) {
1178                // phpinfo();exit;
1179                 $sn = $_SERVER['SCRIPT_NAME'];
1180                 $sublen = strlen(substr($sn , 0,  strlen($sn) - strlen(basename($sn)) -1 ));
1181                  //var_dump(array($sn,$subdir,basename($sn)));exit;
1182                 $subreq =  $_SERVER['SCRIPT_NAME'];
1183                 $request = substr($_SERVER['REDIRECT_URL'],$sublen);
1184                 
1185                  
1186             } else {
1187                   
1188              
1189                 $subreq = substr($request,0, strlen($this->baseURL));
1190                 if ($subreq != substr($this->baseURL,0,strlen($subreq))) {
1191                     $this->fatalError(
1192                         "Configuration error: Got base of $subreq which does not 
1193                             match configuration of: $this->baseURL} ");
1194                 }
1195                 $request = substr($request,strlen($this->baseURL));
1196                 
1197             }
1198             
1199              
1200         }
1201        // var_Dump(array('req'=>$request,'subreq'=>$subreq));
1202         
1203         // strip front
1204         // echo "REQUEST WAS: $request<BR>";
1205         // $request = preg_replace('/^'.preg_quote($base_url,'/').'/','',trim($request));
1206         // echo "IS NOW: $request<BR>";
1207         // strip end
1208         // strip valid html stuff
1209         //$request = preg_replace('/\/[.]+/','',$request);
1210         
1211
1212         $request = preg_replace('/^[\/]*/','',$request);
1213         $request = preg_replace('/\?.*$/','',$request);
1214         $request = preg_replace('/[\/]*$/','',$request);
1215         $this->baseRequest = $request;
1216         $request = str_replace('&','',$request); // any other invalid characters???
1217         $request = preg_replace('/\.([a-z]+)$/','',$request);
1218         $this->ext = substr($this->baseRequest , strlen($request));
1219         
1220         // REDIRECT ROO to index.php! for example..
1221         
1222         if (!$request && !$isRedirect) {
1223             if ($this->baseURL && (strlen($startRequest) < strlen($this->baseURL))) {
1224                 // needs to handle https + port
1225                 $http = ((!empty($_SERVER["HTTPS"]) && $_SERVER["HTTPS"]  == 'on')) ? 'https' : 'http';
1226                 $sp = '';
1227                 if (!empty($_SERVER['SERVER_PORT'])) {
1228                     if ((($http == 'http') && ($_SERVER['SERVER_PORT'] == 80)) || (($http == 'https') && ($_SERVER['SERVER_PORT'] == 443))) {
1229                         // standard ports..
1230                     } else {
1231                         $sp .= ':'.((int) $_SERVER['SERVER_PORT']);
1232                     }
1233                 }
1234                 // not sure why http host would not be set?
1235                 $host = !empty($_SERVER["HTTP_X_FORWARDED_HOST"]) ? $_SERVER["HTTP_X_FORWARDED_HOST"] :
1236                     (!isset($_SERVER["HTTP_HOST"]) ? 'localhost' : $_SERVER["HTTP_HOST"]);
1237                     
1238                 header('Location: '.$http.'://'.$host .$sp . $this->baseURL);
1239  
1240                 exit;
1241             }
1242             $request = "";
1243         }
1244        // var_dump(array($startRequest,$request, $this->baseRequest));
1245         
1246         $this->debug("OUTPUT REQUEST $request<BR>");
1247         
1248         $this->_handleLanguages($request);
1249
1250         
1251         return $request;
1252     }
1253     
1254    
1255     
1256     
1257     /**
1258     * get the Class name and filename to load
1259     *
1260     * Parses the request and converts that into a File + Classname
1261     * if the class doesnt exist it will attempt to find a file below it, and
1262     * call that one with the data.
1263     * Used by the module loader to determine the location of the modules
1264     *   
1265     * @param   request  the request string
1266     * @param   boolean showError - if false, allows you to continue if the class doesnt exist.
1267     * 
1268     *
1269     * @return   array classname, filepath
1270     * @access   private
1271     * @static
1272     */
1273   
1274     function requestToClassName($request,$showError=TRUE) 
1275     {
1276        // if ($request == "error") {
1277        //     return array("HTML_FlexyFramework_Error","");
1278        // }
1279         
1280         // special classes ::
1281         if ($this->cli && in_array($request, array('DataObjects'))) {
1282             require_once 'HTML/FlexyFramework/'. $request . '.php';
1283             return array('HTML_FlexyFramework_'. $request,'');
1284         }
1285         
1286         
1287         $request_array = explode("/",$request);
1288         $original_request_array = $request_array;
1289         $sub_request_array = array();
1290         $l = count($request_array)-1;
1291         if ($l > 10) { // ?? configurable?
1292             //PEAR::raiseError("Request To Long");
1293             $this->fatalError("Request To Long - " . $request);
1294         }
1295
1296         
1297         $classname='';
1298         // tidy up request array
1299         
1300         if ($request_array) {
1301             foreach(array_keys($request_array) as $i) {
1302                 $request_array[$i] = preg_replace('/[^a-z0-9]/i','_',urldecode($request_array[$i]));
1303             }
1304         }
1305         //echo "<PRE>"; print_r($request_array);
1306         // technically each module should do a check here... similar to this..
1307         
1308         
1309         for ($i=$l;$i >-1;$i--) {
1310             $location = implode('/',$request_array) . ".php";
1311             if ($location == '.php') {
1312                 $this->debug("SKIP first path check, as request str is empty");
1313                 break;
1314             }
1315             
1316             $this->debug("baseDIR = {$this->baseDir}");
1317             
1318             $floc = "{$this->baseDir}/$location";
1319             $this->debug("CHECK LOCATION = $location");
1320             
1321             
1322             
1323             if (!empty($location) && $location != '.php' && @file_exists($floc )) {             // hide? error???
1324                 require_once $floc ;
1325                 $classname = $this->classPrefix . implode('_',$request_array);
1326                 $this->debug("FOUND FILE - SET CLASS = $classname <BR>");
1327                 break;
1328             } 
1329             
1330             // in here check the 'projectExtends' versions..?
1331             
1332             if(!empty($this->projectExtends)){
1333                 $this->debug("Trying project Extends<BR>");
1334                 $has_extend_class = false;
1335                 
1336                 foreach ($this->projectExtends as $e){
1337                     $floc = "{$this->rootDir}/{$e}/$location";
1338                     $this->debug("Trying file: $floc");
1339                     if (!empty($location) && @file_exists($floc)) {             // hide? error???
1340                         require_once $floc ;
1341                         $classname = $e . '_' . implode('_',$request_array);
1342                         $has_extend_class = true;
1343                         $this->debug("FOUND FILE - SET CLASS = $classname <BR>");
1344                         break;
1345                     } 
1346                 }
1347                 
1348                 if(!empty($has_extend_class)){
1349                     break;
1350                 }
1351                 
1352             }
1353             
1354             
1355             $this->debug("$floc  - !!FOUND NOT FILE!!");
1356             
1357             $sub_request_array[] = $original_request_array[$i];
1358             unset($request_array[$i]);
1359             unset($original_request_array[$i]);
1360         }
1361          
1362         // is this really needed here!
1363         
1364         $classname = preg_replace('/[^a-z0-9]/i','_',$classname);
1365         $this->debug("CLASSNAME is '$classname'");
1366         // got it ok.
1367         if ($classname && class_exists($classname)) {
1368             $this->debug("using $classname");
1369             //print_r($sub_request_array);
1370             return array($classname,implode('/',array_reverse($sub_request_array)));
1371         }
1372         // stop looping..
1373         if ($showError) {
1374             $this->fatalError("INVALID REQUEST: \n $request FILE:".$this->baseDir. "/{$location}  CLASS:{$classname}");
1375             
1376         } 
1377         
1378         
1379         $this->debug("Try base {$this->baseDir}.php");   
1380         // try {project name}.php
1381         // this used to be silenced @ - if this fails we are usually pretty fried..
1382         
1383         if (file_exists($this->baseDir.'.php')) {
1384             
1385             
1386             $classname = str_replace('/', '_', $this->project); //   basename($this->baseDir);
1387             
1388             $this->debug("FOUND {$this->baseDir} requring and checking class $classname");   
1389             require_once $this->baseDir.'.php';
1390             $this->debug("require success");
1391             
1392             if (!class_exists($classname)) {
1393                 $this->fatalError( "{$this->baseDir}.php did not contain class $classname");
1394             }
1395         }
1396         // got projectname.php
1397         if ($classname && class_exists($classname)) {
1398             $this->debug("using $classname");
1399             //print_r($sub_request_array);
1400              
1401             return array($classname,implode('/',array_reverse($sub_request_array)));
1402         }    
1403             
1404         
1405         $this->fatalError( "can not find {$this->baseDir}.php"); // dies..
1406               
1407      
1408     }
1409     
1410     /**
1411     * ensure Single CLi process 
1412     * usage:
1413     * HTML_FlexyFramework::ensureSingle(__FILE__, $this);
1414     * @param string filename of running class
1415     * @param object class
1416     */
1417       
1418     static function ensureSingle($sig, $class) 
1419     {
1420         //echo "check single: $sig / ". get_class($class) ."\n";
1421         $ff = HTML_FlexyFramework::get();
1422         if (function_exists('posix_getpwuid')) {
1423             $uinfo = posix_getpwuid( posix_getuid () ); 
1424             $user = $uinfo['name'];
1425         } else {
1426             $user = getenv('USERNAME'); // windows.
1427         }
1428         $fdir = ini_get('session.save_path') .'/' . 
1429                 $user . '_cli_' . $ff->project ;
1430      
1431         
1432         if (!file_exists($fdir)) {
1433             mkdir($fdir, 0777);
1434         }
1435         
1436         $lock = $fdir.'/'. md5($sig) . '.' . get_class($class);
1437         //echo "check single: lock : $lock\n";
1438         if (!file_exists($lock)) {
1439             file_put_contents($lock, getmypid());
1440             //echo "check single: lock : DOES NOT EXIST\n";
1441             return true;
1442         }
1443         $oldpid = file_get_contents($lock);
1444         if (!file_exists('/proc/' . $oldpid)) {
1445             
1446             file_put_contents($lock, getmypid());
1447           //  echo "check single: lock : PROC NOT EXIST\n";
1448             return true;
1449         }
1450         // file exists, but process might not be the same..
1451         $ea = explode('_', get_class($class));
1452         $name = array_pop($ea);
1453         $cmd = file_get_contents('/proc/' . $oldpid.'/cmdline');
1454         if (!preg_match('/php/i',$cmd) || !preg_match('/'.$name.'/i',$cmd)) {
1455             file_put_contents($lock, getmypid());
1456             //echo "check single: lock : CMDLINE !have PHP \n";
1457             return true;
1458         }
1459         die("process " . $sig . " already running\n");
1460         
1461     }
1462     /**
1463      * removes the lock for the applicaiton - use with care...
1464      *
1465      *
1466      */
1467     static function ensureSingleClear($sig, $class)
1468     {
1469         $ff = HTML_FlexyFramework::get();
1470         if (function_exists('posix_getpwuid')) {
1471             $uinfo = posix_getpwuid( posix_getuid () ); 
1472             $user = $uinfo['name'];
1473         } else {
1474             $user = getenv('USERNAME'); // windows.
1475         }
1476         $fdir = ini_get('session.save_path') .'/' . 
1477                 $user . '_cli_' . $ff->project ;
1478      
1479         
1480         if (!file_exists($fdir)) {
1481             mkdir($fdir, 0777);
1482         }
1483         $lock = $fdir.'/'. md5($sig);
1484         if (!file_exists($lock)) {
1485             
1486             return true;
1487         }
1488         unlink($lock);;
1489     }
1490     
1491     
1492     /**
1493     * Debugging 
1494     * 
1495     * @param   string  text to output.
1496     * @access   public
1497     */
1498   
1499     function debug($output) {
1500        
1501         if (empty($this->debug)) {  
1502             return;
1503         }
1504         echo $this->cli ? 
1505               "HTML_FlexyFramework::debug  - ".$output."\n" 
1506             : "<B>HTML_FlexyFramework::debug</B> - ".$output."<BR>\n";
1507     
1508     }
1509     /**
1510     * Raises a fatal error. - normally only used when setting up to help get the config right.
1511     * 
1512     * can redirect to fatal Action page.. - hoepfully not issued before basic vars are set up..
1513     * 
1514     * @param   string  text to output.
1515     * @access   public
1516     */
1517     
1518     function fatalError($msg,$showConfig = 0) 
1519     {
1520         
1521         
1522          if ($this->fatalAction) {
1523             HTML_FlexyFramework::run($this->fatalAction,$msg);
1524             exit;
1525         }
1526         header('HTTP/1.1 503 Service Temporarily Unavailable');
1527         header('Status: 503 Service Temporarily Unavailable');
1528         header('Retry-After: 300');
1529         echo $this->cli ? $msg ."\n" : "<H1>$msg</H1>configuration information<PRE>";
1530         if ($showConfig) {
1531             
1532             print_r($this);
1533         }
1534         $ff = HTML_FlexyFramework::get();
1535         $ff->debug($msg);
1536         exit;
1537     }    
1538 }
1539
1540