deduplicate session cookies
[pear] / HTML / FlexyFramework / Page.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: Page.php,v 1.5 2003/02/22 01:52:50 alan Exp $
20 //
21 // A Base Page Class for use with HTML_Template_Flexy
22 // You could write one of these which used another template engine.
23 //
24
25
26 require_once 'HTML/Template/Flexy.php' ;
27 require_once 'HTML/Template/Flexy/Factory.php' ;
28
29 /**
30 * The Base Page class - extend and override the methods to implement your own pages.
31 *
32 *
33 */
34
35
36 class HTML_FlexyFramework_Page  {
37
38
39     /**
40     * the main Template name (which can include a body template)
41     *
42     * @var string template name
43     * @access public
44     */
45     var $masterTemplate = "master.html";
46     /**
47     * the body Template name
48     *
49     * @var string template name
50     * @access public
51     */
52     var $template = "error.html";
53
54
55
56
57     /**
58     * cache method -
59     *   can be 'output', or 'data'
60     * used to set a default caching method
61     *
62     * @var string
63     * @access public
64     * @see getCache()
65     */
66     var $cacheMethod = '';
67
68
69
70
71    /**
72     * cache store (PEAR's Cache Object Instance
73     *   initialized at start
74     *   set at output stage.
75     *
76     * @var object
77     * @access private
78     * @see getCache()
79     */
80
81     var $_cache = NULL;
82
83     /* ---- Variables set by Page loader -------- */
84
85
86
87     /**
88     * baseURL, that can be prefixed to URL's to ensure that they correctly relate to application
89     * (set by page loader)
90     * @var string
91     * @access public
92     */
93     var $baseURL;
94     /**
95     * rootURL, the base installation directory - can be used to get images directories.
96     * (set by page loader)
97     * @var string
98     * @access public
99     */
100     var $rootURL;
101     /**
102     * rootDir, the base installation directory - can be used to find relative files.
103     * (set by page loader)
104     * @var string
105     * @access public
106     */
107     var $rootDir;
108     /**
109     * the full request string used by the getCacheID().
110     * (set by page loader)
111     * @var string
112     * @access public
113     */
114     var $request; // clean page request for page
115     /**
116     * overrides for elements.
117     *
118     * @var array
119     * @access public
120     */
121     var $elements = array(); // key=>HTML_Template_Flexy_Element
122
123      /**
124     * errors for elements
125     *
126     * @var array
127     * @access public
128     */
129     var $errors = array(); // key(element name)=>error message
130
131
132     /**
133     * is the page being run from the command line?
134     *  
135     * @var bool
136     * @access public
137     */
138     var $cli = false;
139     /**
140     * Arguments from cli if static $cli_opts is used.
141     *
142     * @var array
143     * @access public
144     */
145     var $cli_args = array(); // key(element name)=>error message
146
147     /**
148      * Reference to the page loader
149      * @var type HTML_FlexyFramework -
150      *
151      */
152
153     var $bootLoader = false;
154
155
156
157     /**
158     * The default page handler
159     * by default relays to get(), or post() methods depending on the request.
160     *
161     * Override this if you do not handle get or post differently.
162     *
163     *
164     * @param   string  request, the remainder of the request not handled by the object.
165     *
166     * @return   none|string none = handled, string = redirect to another page = eg. data/list
167     * @access   public
168     */
169
170     function start($request,$isRedirect=false,$args=array())
171     {
172         $cli= HTML_Flexyframework::get()->cli;
173         if (!$cli && !$isRedirect && !empty($_SERVER["REQUEST_METHOD"]) && $_SERVER["REQUEST_METHOD"] == "POST") {
174             return $this->post($request,$args);
175         } else {
176             return $this->get($request,$args,$isRedirect);
177         }
178     }
179     /**
180     * The get page handler
181     *
182     * Override this if you want to handle get requests
183     *
184     *
185     * @param   string  request, the remainder of the request not handled by the object.
186     *
187     * @return   none|string none = handled, string = redirect to another page = eg. data/list
188     * @access   public
189     */
190     function get($request)
191     {
192     }
193      /**
194     * The post page handler
195     *
196     * Override this if you want to handle get requests
197     *
198     *
199     * @param   string  request, the remainder of the request not handled by the object.
200     *
201     * @return   none|string none = handled, string = redirect to another page = eg. data/list
202     * @access   public
203     */
204    function post($request)
205    {
206    }
207     /**
208     * Authentication Check method
209     * Override this with a straight return for pages that do not require authentication
210     *
211     * By default
212     *   a) redirects to login if authenticaiton fails
213     *   b) checks to see if a isAdmin method exists on the auth object
214     *       if it does see if the user is admin and let them in.
215     *       otherwise access denied error is raised
216     *   c) lets them in.
217     *
218     *
219     *
220     * @return   none or string redirection to another page.
221     * @access   public
222     */
223
224     function getAuth() {
225
226
227         return false;
228
229     }
230
231
232
233
234     /**
235     * The master Output layer.
236     *
237     * compiles the template
238     * if no caching - just runs the template.
239     * otherwise stores it in the cache.
240     *
241     * you dont normally need to override this.
242     *
243     * called by the page loader.
244     * @access   public
245     */
246
247
248
249     function output()
250     {
251       
252         if (!empty($this->cli)) {
253             return;
254         }
255
256         /* output the body if no masterTemplate is set */
257         $options = HTML_FlexyFramework::get();
258
259         $type = isset($this->contentType) ? $this->contentType : 'text/html';
260         header('Content-Type: '.$type.';charset='.( empty($options->charset) ? 'UTF-8' : $options->charset ));
261
262
263         if (!$this->masterTemplate) {
264             return $this->outputBody();
265         }
266         /* master template */
267
268
269         $template_engine = new HTML_Template_Flexy();
270         $template_engine->compile($this->masterTemplate);
271         if (!$this->_cache || !$this->cacheMethod) {
272             $template_engine->outputObject($this,$this->elements);
273             return;
274         }
275
276         $id = $this->_cache->generateID($this->getID());
277         $this->_cache->save($id, $template_engine->bufferedOutputObject($this,$this->elements));
278         echo $this->_cache->get($id);
279
280     }
281     /**
282     * The body Output layer.
283     *
284     * compiles the template
285     * At present there is no caching in here..  - this may change latter..
286     *
287     * used by putting {outputBody} in the main template.
288     * @access   public
289     */
290     function outputBody() {
291
292         $template_engine = new HTML_Template_Flexy();
293         $template_engine->compile($this->template);
294         if ($this->elements) { /* BC crap! */
295             $this->elements = HTML_Template_Flexy_Factory::setErrors($this->elements,$this->errors);
296         }
297         $template_engine->elements = $this->elements;
298         $template_engine->outputObject($this,$this->elements);
299
300     }
301
302
303      /**
304     * Do any Page Caching if $this->cacheMethod is set.
305     * You should also look at output caching by overriding the outputBody Method.
306     *
307     * Note that Caching is disabled in a number of situations.
308     *   a) cacheMethod is empty
309     *   b) POST requests
310     *   c) if sess is set (Eg. if you are using sessions)
311     *   d) useCache is not set in the [Cache] section of the config.
312     *
313     * utilizes $this->getCacheID() to
314     *
315     * @return   none|boolean|string|int|object    Description
316     * @access   public|private
317     * @see      see also methods.....
318     */
319
320
321     function getCache() {
322         if (!$this->cacheMethod) {
323             return;
324         }
325         if ($_SERVER["REQUEST_METHOD"] == "POST") {
326             return;
327         }
328
329         /* lets assume we can cache ourselves.. */
330         $coptions = PEAR::getStaticProperty('Cache','options');
331         if (!$coptions) {
332             return;
333         }
334         if (empty($coptions['useCache'])) {
335             return;
336         }
337         require_once 'Cache.php';
338
339         $this->_cache = new Cache($coptions['container'], $coptions);
340         $id = $this->_cache->generateID($this->getCacheID());
341         if ($_SERVER["REQUEST_METHOD"] == "POST") {
342             $this->_cache->flush($id);
343             return;
344         }
345         if ($data = $this->_cache->get($id)) {
346             echo $data;
347             return TRUE;
348         }
349
350     }
351
352     /**
353     * Get a distinct Page Cache ID.
354     *
355     * By default this is the full request string
356     * override this to define a more precise string
357     *
358     * @return   string   distinct page id (eg. the request url)
359     * @access   private
360     */
361
362     function getCacheID() {
363         return  $this->request;
364
365     }
366
367
368     /**
369     * Utility method : get the Class name (used on templates)
370     *
371     * @return   string   class name
372     * @access   public
373     */
374
375
376     function getClass() {
377         return get_class($this);
378     }
379     /**
380     * Utility method : get the Time taken to generate the page.
381     *
382     * @return   string   time in seconds..
383     * @access   public
384     */
385
386     function getTime() {
387
388         $m = explode(' ',microtime());
389         $ff =  HTML_FlexyFramework::get();
390         return sprintf('%0.2fs',($m[0] + $m[1]) -  $ff->start)
391                 . '/ Files ' . count(get_included_files());
392
393
394     }
395     /**
396      * turn on off session - wrap long database queries or
397      * data processing with this to prevent locking
398      * @see
399      * @param int $state new session state - 0 = off, 1 = on
400      */
401
402     function sessionState($state)
403     {
404         static $ses_status = false;
405         static $ini = false;
406         // session status is only php5.4 and up..
407         if (!defined('PHP_SESSION_ACTIVE')) {
408             define('PHP_SESSION_ACTIVE' , 1);
409         }
410         if(!function_exists('session_status')){
411              $ses_status = 1;
412         } else {
413             $ses_status = ($ses_status === false) ? session_status() : $ses_status;
414         }
415         if (PHP_SESSION_ACTIVE != $ses_status) {
416             return;
417         }
418
419         switch ($state) {
420             case 0:
421                 session_write_close();
422                 return;
423             case 1:
424                 if ($ini) {
425                     ini_set('session.use_only_cookies', false);
426                     ini_set('session.use_cookies', false);
427                     ini_set('session.use_trans_sid', false);
428                     ini_set('session.cache_limiter', null);
429                 }
430                 $ini = true;
431                 // sometimes raises a notice - ps_files_cleanup_dir.
432                 @session_start();
433                 $this->dedupeSessionCookies();
434                 return;
435         }
436     }
437     
438     function dedupeSessionCookies()
439     {
440          if (headers_sent()) {
441             return;
442         }
443         $cookies = array();
444         
445         foreach (headers_list() as $header) {
446             // Identify cookie headers
447             if (strpos($header, 'Set-Cookie:') === 0) {
448                 $cookies[] = $header;
449             }
450         }
451         header_remove('Set-Cookie');
452
453         // Restore one copy of each cookie
454         foreach(array_unique($cookies) as $cookie) {
455             header($cookie, false);
456         }
457     }
458     
459
460 }