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