root/trunk/wifidog-auth/wifidog/classes/MainUI.php @ 1312

Revision 1312, 23.0 KB (checked in by benoitg, 5 years ago)
  • Node.php: Fix bug in setCurrentNode() reported by Vacio
  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1<?php
2
3
4/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
5
6// +-------------------------------------------------------------------+
7// | WiFiDog Authentication Server                                     |
8// | =============================                                     |
9// |                                                                   |
10// | The WiFiDog Authentication Server is part of the WiFiDog captive  |
11// | portal suite.                                                     |
12// +-------------------------------------------------------------------+
13// | PHP version 5 required.                                           |
14// +-------------------------------------------------------------------+
15// | Homepage:     http://www.wifidog.org/                             |
16// | Source Forge: http://sourceforge.net/projects/wifidog/            |
17// +-------------------------------------------------------------------+
18// | This program is free software; you can redistribute it and/or     |
19// | modify it under the terms of the GNU General Public License as    |
20// | published by the Free Software Foundation; either version 2 of    |
21// | the License, or (at your option) any later version.               |
22// |                                                                   |
23// | This program is distributed in the hope that it will be useful,   |
24// | but WITHOUT ANY WARRANTY; without even the implied warranty of    |
25// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     |
26// | GNU General Public License for more details.                      |
27// |                                                                   |
28// | You should have received a copy of the GNU General Public License |
29// | along with this program; if not, contact:                         |
30// |                                                                   |
31// | Free Software Foundation           Voice:  +1-617-542-5942        |
32// | 59 Temple Place - Suite 330        Fax:    +1-617-542-2652        |
33// | Boston, MA  02111-1307,  USA       gnu@gnu.org                    |
34// |                                                                   |
35// +-------------------------------------------------------------------+
36
37/** This file contains the code for the MainUI class, as well as GUI exception handling.
38 * @package    WiFiDogAuthServer
39 * @author     Benoit Grégoire <bock@step.polymtl.ca>
40 * @copyright  2005-2007 Benoit Grégoire, Technologies Coeus inc.
41 * @version    Subversion $Id$
42 * @link       http://www.wifidog.org/
43 */
44
45/**
46 * @internal We put a call to validate_schema() here so it systematically called
47 * from any UI page, but not from any machine readable pages
48 */
49require_once ('include/schema_validate.php');
50validate_schema();
51require_once ('include/process_login_out_form.php');
52
53/** Protects against secondary exceptions during exception display */
54function exception_output_helper($html) {
55    try{
56        // Load MainUI class
57        $ui = MainUI::getObject();
58        $ui->addContent('main_area_middle', $html);
59        $ui->display();
60    }
61    catch (Exception $e)
62    {
63        echo "Notice:  A secondary Exception was thrown trying to display the Exception graphically using MainUI.  Here is the text-only output:<br/>";
64        echo $html;
65    }
66}
67/**
68 * This custom exception handler is only called if the MainUI file is included
69 */
70function wifidog_exception_handler($e) {
71    $exceptionClass = get_class($e);
72    switch ($exceptionClass) {
73        case 'SecurityException':
74            $html = null;
75            $html .= "<div class = 'errormsg'>\n";
76            $user = User::getCurrentUser();
77            if($user) {
78                $html .= sprintf(_("Your current user (%s) does not have the required level of access.  Please login with with a user with the required permission(s) to try this operation again."),$user->getUserName());
79            }
80            else {
81                $html .= sprintf(_("You didn't log-in or your session timed-out.  Please login to try this operation again."));
82            }
83            $html .= "</div>\n";
84            $html .= "<form name='login_form' id='login_form' action='' method='post'>\n";
85            require_once ('classes/Authenticator.php');
86            $html .= Authenticator::getLoginUI();
87            $html .= "</form>\n";
88            $html .= "<div class = 'warningmsg'>\n";
89            $html .= sprintf(_("%s"), $e->getMessage());
90            $html .= "<pre>\n";
91            $html .= sprintf(_("%s was thrown in %s, line %d\n"), get_class($e), $e->getFile(), $e->getLine());
92            $html .= $e->getTraceAsString();
93            $html .= "</pre>\n";
94            $html .= "</div>\n";
95            exception_output_helper($html);
96
97            break;
98        default:
99            //@ob_clean();
100            $html = null;
101            $html .= "<div class = 'errormsg'>\n";
102            $html .= sprintf(_("Detailed error was:  Uncaught %s %s (%s) thrown in file %s, line %d"),get_class($e), $e->getMessage(), $e->getCode(), $e->getFile(), $e->getLine());
103            $html .= "<pre>\n";
104            $html .= $e->getTraceAsString();
105            $html .= "</pre>\n";
106            $html .= "</div>\n";
107            exception_output_helper($html);
108    }
109}
110
111set_exception_handler('wifidog_exception_handler');
112/**
113 * If the database doesn't get cleaned up by a cron job, we'll do now
114 */
115if (CONF_USE_CRON_FOR_DB_CLEANUP == false) {
116    garbage_collect();
117}
118// Clear the buffer
119@ob_clean();
120/**
121 * Load required file
122 */
123require_once('include/init_php.php');
124
125/**
126 * Load required files
127 */
128require_once('classes/Session.php');
129require_once('classes/SmartyWifidog.php');
130require_once('classes/User.php');
131require_once('include/language.php');
132
133/**
134 * Singleton class for managing headers, footers, stylesheet, etc.
135 *
136 * @package    WiFiDogAuthServer
137 * @author     Benoit Grégoire <bock@step.polymtl.ca>
138 * @copyright  2005-2006 Benoit Grégoire, Technologies Coeus inc.
139 */
140class MainUI {
141    /** holder for the singleton */
142    private static $object;
143
144    /**
145     * Content to be displayed the page
146     *
147     * @var array
148     * @access private
149     */
150    private $_contentDisplayArray;
151
152    /**
153     * Content to be displayed on the page, before ordering
154     *
155     * @var array
156     * @access private
157     */
158    private $_contentArray;
159
160    /**
161     * Object for Smarty class
162     *
163     * @var object
164     * @access private
165     */
166    private $smarty;
167
168    /**
169     * Title of HTML page
170     *
171     * @var string
172     * @access private
173     */
174    private $title;
175    /**
176     * Additional class of the <body> of the HTML page
177     */
178    private $_pageName;
179
180    /** list of URLs to stylesheet to be included */
181    private $stylesheetUrlArray = array ();
182
183    /**
184     * Headers of HTML page
185     *
186     * @var private
187     * @access private
188     */
189    private $_htmlHeaders;
190
191    /**
192     * Defines if tool section of HTML page is enabled or not
193     *
194     * @var bool
195     * @access private
196     */
197    private $_toolSectionEnabled = true;
198
199    /**
200     * Scripts for the footer
201     *
202     * @var array
203     * @access private
204     */
205    private $_footerScripts = array ();
206
207    private $_shrinkLeftArea = false;
208    /**
209     * Get the MainUI object
210     * @return object The MainUI object
211     */
212    public static function &getObject() {
213        if (self :: $object == null) {
214            self :: $object = new self();
215        }
216        return self :: $object;
217    }
218    /**
219     * Constructor
220     *
221     * @return void
222     *
223     * @access public
224     */
225    private function __construct() {
226        $db = AbstractDb :: getObject();
227        // Init Smarty
228        $this->smarty = SmartyWifidog :: getObject();
229
230        // Set default title
231        $this->title = Network :: getCurrentNetwork()->getName() . ' ' . _("authentication server");
232        // Init the content array
233        $current_content_sql = "SELECT display_area FROM content_available_display_areas\n";
234        $rows = array ();
235        $db->execSql($current_content_sql, $rows, false);
236        foreach ($rows as $row) {
237            $this->_contentDisplayArray[$row['display_area']] = '';
238        }
239    }
240
241    /**
242     * Add content to a structural area of the page
243     *
244     * @param string $display_area Structural area where content is to be
245     * placed.  Must be one of the display aread defined in the
246     * content_available_display_areas table
247     *
248     * @param string $content Either a Content object (recommended) or raw HTML content to be added to the area
249     *
250     * @param integer $display_order_index The order in which the content should
251     * be displayed
252     *
253     * @return void
254     */
255    public function addContent($displayArea, $content, $displayOrderIndex = 1) {
256        //echo "MainUI::addContent(): Debug: displayArea: $displayArea, displayOrderIndex: $displayOrderIndex, content: $content<br/>";
257        if (!isset ($this->_contentDisplayArray[$displayArea])) {
258            throw new exception(sprintf(_('%s is not a valid structural display area'), $displayArea));
259        }
260        $this->_contentArray[] = array (
261        'display_area' => $displayArea,
262        'display_order' => $displayOrderIndex,
263        'content' => $content
264        );
265    }
266
267    /** Private compare function for sorting the _contentArray() */
268    private static function _contentArrayCmp($a, $b) {
269        if ($a['display_order'] == $b['display_order']) {
270            return 0;
271        }
272        return ($a['display_order'] < $b['display_order']) ? -1 : 1;
273    }
274
275    /** Main processing function do generate the final content.
276     * It will successively call prepareGetUserUI() on all content objects,
277     * and then getUserUI() on all objects.  Note that the point of calling
278     * prepareGetUserUI is to allow that function to call methods of MainUI
279     * (such ans changing headers, etc.).  However, please note that you should not
280     * call MainUI::addContent() from prepareGetUserUI, as prepareGetUserUI() wouldn't
281     * in turn get called on objects added this way.
282     * Orders the content and put it in the _contentDisplayArray array
283     *
284     * @return void
285     */
286    private function generateDisplayContent() {
287        //pretty_print_r($this->_contentArray);
288        usort($this->_contentArray, array (
289        $this,
290        "_contentArrayCmp"
291        ));
292
293        //Fist pass (preparation pass)
294        foreach ($this->_contentArray as $content_fragment) {
295            $content = $content_fragment['content'];
296
297            if (method_exists($content, 'prepareGetUserUI')) {
298                //echo "<h1>prepareGetUserUI on ".$content->getId()."</h1>";
299                $content->prepareGetUserUI();
300            }
301        }
302        foreach ($this->_contentArray as $content_fragment) {
303            $content = $content_fragment['content'];
304            if (is_object($content)) {
305                if (method_exists($content, 'getUserUI')) {
306                    $this->_contentDisplayArray[$content_fragment['display_area']] .= $content->getUserUI();
307                } else {
308                    throw new exception("Object must implement getUserUI");
309                }
310            } else {
311                $this->_contentDisplayArray[$content_fragment['display_area']] .= $content;
312            }
313        }
314
315    }
316
317    /**
318     * Add the content marked "everywhere" from both the current node and the
319     * current network.
320     *
321     * @return void
322     */
323    private function addEverywhereContent() {
324        $db = AbstractDb :: getObject();
325        // Get all network content and node "everywhere" content
326        $content_rows = null;
327        $network_id = $db->escapeString(Network :: getCurrentNetwork()->getId());
328        $sql_network = "(SELECT content_id, display_area, display_order, subscribe_timestamp FROM network_has_content WHERE network_id='$network_id'  AND display_page='everywhere') ";
329        $node = Node :: getCurrentNode();
330        $sql_node = null;
331        if ($node) {
332            // Get all node content
333            $node_id = $db->escapeString($node->getId());
334            $sql_node = "UNION (SELECT content_id, display_area, display_order, subscribe_timestamp FROM node_has_content WHERE node_id='$node_id'  AND display_page='everywhere')";
335        }
336        $sql = "SELECT * FROM ($sql_network $sql_node) AS content_everywhere ORDER BY display_area, display_order, subscribe_timestamp DESC";
337
338        $db->execSql($sql, $content_rows, false);
339        if ($content_rows) {
340            foreach ($content_rows as $content_row) {
341                $content = Content :: getObject($content_row['content_id']);
342                if ($content->isDisplayableAt($node)) {
343                    $this->addContent($content_row['display_area'], $content, $content_row['display_order']);
344                }
345            }
346        }
347
348    }
349
350    /**
351     * Check if the tool section is enabled
352     *
353     * @return bool True or false
354     *
355     * @access public
356     */
357    public function isToolSectionEnabled() {
358        return $this->_toolSectionEnabled;
359    }
360
361    /**
362     * Check if the tool section is enabled
363     *
364     * @return bool True or false
365     *
366     * @access public
367     */
368    public function setToolSectionEnabled($status) {
369        $this->_toolSectionEnabled = $status;
370    }
371
372    /**
373     * Set the title of the HTML page
374     *
375     * @param string $title_string Title of the HTML page
376     *
377     * @return void
378     *
379     * @access public
380     */
381    public function setTitle($title_string) {
382        $this->title = $title_string;
383    }
384
385    public function shrinkLeftArea() {
386        $this->_shrinkLeftArea = true;
387    }
388
389    /**
390     * Set the class name of the <body> of the resulting page.
391     *
392     * @param string $page_name_string The page name of the resulting page.  Must have no spaces.  ex:  portal, login, userprofile, etc.)
393     *
394     * @return void
395     *
396     * @access public
397     */
398    public function setPageName($page_name_string) {
399        $this->_pageName = $page_name_string;
400    }
401
402    /**
403     * Add content at the very end of the <body>.
404     *
405     * This is NOT meant to add footers or other display content, it is meant
406     * to add <script></script> tag pairs that have to be executed only once
407     * the page is loaded.
408     *
409     * @param string $script A piece of script surrounded by
410     *                       <script></script> tags.
411     *
412     * @return void
413     *
414     * @access public
415     */
416    public function addFooterScript($script) {
417        $this->_footerScripts[] = $script;
418    }
419
420    /**
421     * Append HTML markup (normally <script> elements) to the <head> element to
422     * the final page.
423     *
424     * @param string $headers_string HTML markup suitable for the HEAD element
425     *
426     * @return void
427     *
428     * @access public
429     */
430    public function appendHtmlHeadContent($headers_string) {
431        $this->_htmlHeaders .= $headers_string . "\n";
432    }
433
434    /**
435     * Add a stylesheet URL to the main page
436     *
437     * @param string Stylesheet URL
438     *@param media The target media of the selected strylesheet (print, screen,etc.)
439     * @return void
440     *
441     * @access public
442     */
443    public function appendStylesheetURL($stylesheet_url, $media=null) {
444        //Note:  using the URL as value AND key will remove duplicate while keeping the stylesheet inclusion order, because of the way foreach is implemented in PHP
445        $this->stylesheetUrlArray[$stylesheet_url]['href'] = $stylesheet_url;
446                $this->stylesheetUrlArray[$stylesheet_url]['media'] = $media;
447    }
448
449    /**
450     * Get the content to be displayed in the tool pane
451     *
452     * @return string HTML markup
453     *
454     * @access private
455     */
456    private function getToolContent() {
457
458        $session = Session :: getObject();
459        $AVAIL_LOCALE_ARRAY = LocaleList::getAvailableLanguageArray();
460
461        // Init values
462        $html = "";
463        $_gwId = null;
464        $_gwAddress = null;
465        $_gwPort = null;
466        $_selected = "";
467        $_languageChooser = array ();
468
469        // Init ALL smarty SWITCH values
470        $this->smarty->assign('sectionSTART', false);
471        $this->smarty->assign('sectionLOGIN', false);
472
473        // Set section of Smarty template
474        $this->smarty->assign('sectionSTART', true);
475
476        // Get information about user
477        $_currentUser = User :: getCurrentUser();
478        $_currentUser?$this->smarty->assign('userListUI', $_currentUser->getListUI()):$this->smarty->assign('userListUI', "");
479        $this->smarty->assign('logoutParameters', "");
480        $this->smarty->assign('loginParameters', "");
481        $this->smarty->assign('formAction', "");
482        $this->smarty->assign('toolContent', "");
483        $this->smarty->assign('accountInformation', "");
484        $this->smarty->assign('techSupportInformation', "");
485        $this->smarty->assign('shrinkLeftArea', $this->_shrinkLeftArea);
486
487        /*
488         * Provide Smarty information about the user's login/logout status
489         */
490
491        if ($_currentUser != null) {
492            // User is logged in
493
494            // Detect gateway information
495            $_gwId = $session->get(SESS_GW_ID_VAR);
496            $_gwAddress = $session->get(SESS_GW_ADDRESS_VAR);
497            $_gwPort = $session->get(SESS_GW_PORT_VAR);
498
499            // If gateway information could be detected tell them to Smarty
500            if ($_gwId && $_gwAddress && $_gwPort) {
501                $this->smarty->assign('logoutParameters', "&amp;gw_id=" . $_gwId . "&amp;gw_address=" . $_gwAddress . "&amp;gw_port=" . $_gwPort);
502            }
503        } else {
504        }
505
506        /*
507         * Provide Smarty information for the language chooser
508         */
509
510        // Assign the action URL for the form
511        $this->smarty->assign('formAction', htmlspecialchars($_SERVER['REQUEST_URI']));
512
513        foreach ($AVAIL_LOCALE_ARRAY as $_langIds => $_langNames) {
514            if (Locale :: getCurrentLocale()->getId() == $_langIds) {
515                $_selected = ' selected="selected"';
516            } else {
517                $_selected = "";
518            }
519            $langName = "{$_langNames[0]}";
520            $_languageChooser[] = '<option value="' . $_langIds . '"' . $_selected . '>' . $langName . '</option>';
521        }
522
523        // Provide Smarty all available languages
524        $this->smarty->assign('languageChooser', $_languageChooser);
525
526        // Compile HTML code
527        $html = $this->smarty->fetch("templates/classes/MainUI_ToolContent.tpl");
528
529        return $html;
530    }
531
532    /**
533     * Display the main page
534     *
535     * @return void
536     *
537     * @access public
538     * @internal Uses a few request parameters to display debug information.
539     * If $_REQUEST['debug_request'] is present, it will print out the
540     * $_REQUEST array at the top of the page.
541     */
542    public function display() {
543        $db = AbstractDb :: getObject();
544        // Init values
545        // Asign base CSS and theme pack CSS stylesheet
546        $this->appendStylesheetURL(BASE_THEME_URL . STYLESHEET_NAME);
547                $this->appendStylesheetURL(BASE_THEME_URL . PRINT_STYLESHEET_NAME, 'print');
548        $networkThemePack = Network :: getCurrentNetwork()->getThemePack();
549        if ($networkThemePack) {
550            $this->appendStylesheetURL($networkThemePack->getStylesheetUrl());
551        }
552
553        //Handle content (must be done before headers and anything else is handled)
554        /*
555        * Build tool pane if it has been enabled
556        */
557        if ($this->isToolSectionEnabled()) {
558            $this->addContent('left_area_top', $this->getToolContent());
559            //Display main menu
560            require_once('classes/Menu.php');
561            $menu = Menu::getObject();
562            $this->addContent('main_area_top', $menu->getUserUI());
563                        $this->appendHtmlHeadContent(Menu::getIEWorkaroundJS());
564        }
565
566        $this->addEverywhereContent();
567        $this->generateDisplayContent();
568
569        // Init ALL smarty values
570        $this->smarty->assign('htmlHeaders', "");
571        // $this->smarty->assign('isSuperAdmin', false);
572        // $this->smarty->assign('isOwner', false);
573        $this->smarty->assign('debugRequested', false);
574        $this->smarty->assign('debugOutput', "");
575        $this->smarty->assign('footerScripts', array ());
576
577        // Add HTML headers
578        $this->smarty->assign('htmlHeaders', $this->_htmlHeaders);
579
580        // Asign title
581        $this->smarty->assign('title', $this->title);
582
583        // Asign CSS class for body
584        $this->smarty->assign('page_name', $this->_pageName);
585
586        $this->smarty->assign('stylesheetUrlArray', $this->stylesheetUrlArray);
587
588        /*
589         * Allow super admin to display debug output if requested by using
590         * $_REQUEST['debug_request']
591         */
592
593        // Provide footer scripts to Smarty
594        $this->smarty->assign('footerScripts', $this->_footerScripts);
595
596        // Add SQL queries log (must be done manually here at the very end to catch everything)
597        if (defined("LOG_SQL_QUERIES") && LOG_SQL_QUERIES == true)
598        $this->_contentDisplayArray['page_footer'] .= $db->getSqlQueriesLog();
599
600        // Provide the content array to Smarty
601        $this->smarty->assign('contentDisplayArray', $this->_contentDisplayArray);
602
603        // Compile HTML code and output it
604        $this->smarty->display("templates/classes/MainUI_Display.tpl");
605    }
606
607    /**
608     * Display a generic error message
609     *
610     * @param string $errmsg                  The error message to be displayed
611     * @param bool   $show_tech_support_email Defines wether to show the link of
612     *                                        the tech-support
613     *
614     * @return void
615     *
616     * @access public
617     */
618    function displayError($errmsg, $show_tech_support_email = true) {
619        // Init ALL smarty values
620        $this->smarty->assign("error", "");
621        $this->smarty->assign("show_tech_support_email", false);
622        $this->smarty->assign("tech_support_email", "");
623
624        // Define needed error content
625        $this->smarty->assign("error", $errmsg);
626
627        if ($show_tech_support_email) {
628            $this->smarty->assign("show_tech_support_email", true);
629            $this->smarty->assign("tech_support_email", Network :: getCurrentNetwork()->getTechSupportEmail());
630        }
631
632        /*
633         * Output the error message
634         */
635        $html = $this->smarty->fetch("templates/sites/error.tpl");
636
637        $this->addContent('page_header', $html);
638        $this->display();
639    }
640
641    static public function redirect($redirect_url, $redirect_to_title = null, $timeout = 60) {
642        if (!$redirect_to_title) {
643            $network = Network :: getCurrentNetwork();
644            $redirect_to_title = $network ? sprintf(_("%s Login"), $network->getName()) : _("Login");
645        }
646
647        header("Location: $redirect_url");
648        echo "<html>\n" . "<head><meta http-equiv='Refresh' content='$timeout; URL=$redirect_url'/></head>\n" . "<body>\n" . "<noscript>\n" . "<span style='display:none;'>\n" . "<h1>" . $redirect_to_title . "</h1>\n" . sprintf(_("Click <a href='%s'>here</a> to continue"), $redirect_url) . "<br/>\n" . _("The transfer from secure login back to regular http may cause a warning.") . "\n" . "</span>\n" . "</noscript>\n" . "</body>\n" . "</html>\n";
649        exit;
650    }
651}
652
653/*
654 * Local variables:
655 * tab-width: 4
656 * c-basic-offset: 4
657 * c-hanging-comment-ender-p: nil
658 * End:
659 */
Note: See TracBrowser for help on using the browser.