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

Revision 1156, 22.8 KB (checked in by benoitg, 6 years ago)
  • install.php: Move path verification to the first page, and make it clearer. Fix PHP warnings.
  • wifidog/include/smarty.resource.string.php: A smarty resource plugin to parse a smarty template from a

string

  • SmartyTemplate?: Very basic but functionnal commit of the new Smarty content type. IMPORTANT NOTE: This will eventually obsolete IFrameRest, which will be removed.
  • Continue cleaning-up/standardizing Smarty variable usage.
  • 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/**
38 * @package    WiFiDogAuthServer
39 * @author     Benoit Grégoire <bock@step.polymtl.ca>
40 * @copyright  2005-2006 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();
51
52/**
53 * If the database doesn't get cleaned up by a cron job, we'll do now
54 */
55if (CONF_USE_CRON_FOR_DB_CLEANUP == false) {
56    garbage_collect();
57}
58
59/**
60 * Load required file
61 */
62require_once ('include/common_interface.php');
63
64/**
65 * Singleton class for managing headers, footers, stylesheet, etc.
66 *
67 * @package    WiFiDogAuthServer
68 * @author     Benoit Grégoire <bock@step.polymtl.ca>
69 * @copyright  2005-2006 Benoit Grégoire, Technologies Coeus inc.
70 */
71class MainUI {
72    /** holder for the singleton */
73    private static $object;
74
75    /**
76    * Content to be displayed the page
77    *
78    * @var array
79    * @access private
80    */
81    private $_contentDisplayArray;
82
83    /**
84    * Content to be displayed on the page, before ordering
85    *
86    * @var array
87    * @access private
88    */
89    private $_contentArray;
90
91    /**
92     * Object for Smarty class
93     *
94     * @var object
95     * @access private
96     */
97    private $smarty;
98
99    /**
100     * Title of HTML page
101     *
102     * @var string
103     * @access private
104     */
105    private $title;
106    /**
107     * Additional class of the <body> of the HTML page
108     */
109    private $_pageName;
110
111    /** list of URLs to stylesheet to be included */
112    private $stylesheetUrlArray = array ();
113
114    /**
115     * Headers of HTML page
116     *
117     * @var private
118     * @access private
119     */
120    private $_htmlHeaders;
121
122    /**
123     * Defines if tool section of HTML page is enabled or not
124     *
125     * @var bool
126     * @access private
127     */
128    private $_toolSectionEnabled = true;
129
130    /**
131     * Scripts for the footer
132     *
133     * @var array
134     * @access private
135     */
136    private $_footerScripts = array ();
137
138    private $_shrinkLeftArea = false;
139    /**
140     * Get the MainUI object
141     * @return object The MainUI object
142     */
143    public static function getObject() {
144        if (self :: $object == null) {
145            self :: $object = new self();
146        }
147        return self :: $object;
148    }
149    /**
150     * Contructor
151     *
152     * @return void
153     *
154     * @access public
155     */
156    private function __construct() {
157        $db = AbstractDb :: getObject();
158        // Init Smarty
159        $this->smarty = SmartyWifidog :: getObject();
160
161        // Set default title
162        $this->title = Network :: getCurrentNetwork()->getName() . ' ' . _("authentication server");
163        // Init the content array
164        $current_content_sql = "SELECT display_area FROM content_available_display_areas\n";
165        $rows = array ();
166        $db->execSql($current_content_sql, $rows, false);
167        foreach ($rows as $row) {
168            $this->_contentDisplayArray[$row['display_area']] = '';
169        }
170    }
171
172    /**
173     * Add content to a structural area of the page
174     *
175     * @param string $display_area Structural area where content is to be
176     * placed.  Must be one of the display aread defined in the
177     * content_available_display_areas table
178     *
179     * @param string $content Either a Content object (recommended) or raw HTML content to be added to the area
180     *
181     * @param integer $display_order_index The order in which the content should
182     * be displayed
183     *
184     * @return void
185     */
186    public function addContent($displayArea, $content, $displayOrderIndex = 1) {
187        //echo "MainUI::addContent(): Debug: displayArea: $displayArea, displayOrderIndex: $displayOrderIndex, content: $content<br/>";
188        if (!isset ($this->_contentDisplayArray[$displayArea])) {
189            throw new exception(sprintf(_('%s is not a valid structural display area'), $displayArea));
190        }
191        $this->_contentArray[] = array (
192            'display_area' => $displayArea,
193            'display_order' => $displayOrderIndex,
194            'content' => $content
195        );
196    }
197
198    /** Private compare function for sorting the _contentArray() */
199    private static function _contentArrayCmp($a, $b) {
200        if ($a['display_order'] == $b['display_order']) {
201            return 0;
202        }
203        return ($a['display_order'] < $b['display_order']) ? -1 : 1;
204    }
205
206    /** Main processing function do generate the final content.
207     * It will successively call prepareGetUserUI() on all content objects,
208     * and then getUserUI() on all objects.  Note that the point of calling
209     * prepareGetUserUI is to allow that function to call methods of MainUI
210     * (such ans changing headers, etc.).  However, please note that you should not
211     * call MainUI::addContent() from prepareGetUserUI, as prepareGetUserUI() wouldn't
212     * in turn get called on objects added this way.
213     * Orders the content and put it in the _contentDisplayArray array
214     *
215     * @return void
216     */
217    private function generateDisplayContent() {
218        //pretty_print_r($this->_contentArray);
219        usort($this->_contentArray, array (
220            $this,
221            "_contentArrayCmp"
222        ));
223
224        //Fist pass (preparation pass)
225        foreach ($this->_contentArray as $content_fragment) {
226            $content = $content_fragment['content'];
227
228            if (method_exists($content, 'prepareGetUserUI')) {
229                //echo "<h1>prepareGetUserUI on ".$content->getId()."</h1>";
230                $content->prepareGetUserUI();
231            }
232        }
233        foreach ($this->_contentArray as $content_fragment) {
234            $content = $content_fragment['content'];
235            if (is_object($content)) {
236                if (method_exists($content, 'getUserUI')) {
237                    $this->_contentDisplayArray[$content_fragment['display_area']] .= $content->getUserUI();
238                } else {
239                    throw new exception("Object must implement getUserUI");
240                }
241            } else {
242                $this->_contentDisplayArray[$content_fragment['display_area']] .= $content;
243            }
244        }
245
246    }
247
248    /**
249     * Add the content marked "everywhere" from both the current node and the
250     * current network.
251     *
252     * @return void
253     */
254    private function addEverywhereContent() {
255        $db = AbstractDb :: getObject();
256        // Get all network content and node "everywhere" content
257        $content_rows = null;
258        $network_id = $db->escapeString(Network :: getCurrentNetwork()->getId());
259        $sql_network = "(SELECT content_id, display_area, display_order, subscribe_timestamp FROM network_has_content WHERE network_id='$network_id'  AND display_page='everywhere') ";
260        $node = Node :: getCurrentNode();
261        $sql_node = null;
262        if ($node) {
263            // Get all node content
264            $node_id = $db->escapeString($node->getId());
265            $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')";
266        }
267        $sql = "SELECT * FROM ($sql_network $sql_node) AS content_everywhere ORDER BY display_area, display_order, subscribe_timestamp DESC";
268
269        $db->execSql($sql, $content_rows, false);
270        if ($content_rows) {
271            foreach ($content_rows as $content_row) {
272                $content = Content :: getObject($content_row['content_id']);
273                if ($content->isDisplayableAt($node)) {
274                    $this->addContent($content_row['display_area'], $content, $content_row['display_order']);
275                }
276            }
277        }
278
279    }
280
281    /**
282    * Check if the tool section is enabled
283    *
284    * @return bool True or false
285    *
286    * @access public
287    */
288    public function isToolSectionEnabled() {
289        return $this->_toolSectionEnabled;
290    }
291
292    /**
293     * Check if the tool section is enabled
294     *
295     * @return bool True or false
296     *
297     * @access public
298     */
299    public function setToolSectionEnabled($status) {
300        $this->_toolSectionEnabled = $status;
301    }
302
303    /**
304     * Set the title of the HTML page
305     *
306     * @param string $title_string Title of the HTML page
307     *
308     * @return void
309     *
310     * @access public
311     */
312    public function setTitle($title_string) {
313        $this->title = $title_string;
314    }
315
316    public function shrinkLeftArea() {
317        $this->_shrinkLeftArea = true;
318    }
319
320    /**
321     * Set the class name of the <body> of the resulting page.
322     *
323     * @param string $page_name_string The page name of the resulting page.  Must have no spaces.  ex:  portal, login, userprofile, etc.)
324     *
325     * @return void
326     *
327     * @access public
328     */
329    public function setPageName($page_name_string) {
330        $this->_pageName = $page_name_string;
331    }
332
333    /**
334    * Add content at the very end of the <body>.
335    *
336    * This is NOT meant to add footers or other display content, it is meant
337    * to add <script></script> tag pairs that have to be executed only once
338    * the page is loaded.
339    *
340    * @param string $script A piece of script surrounded by
341    *                       <script></script> tags.
342    *
343    * @return void
344    *
345    * @access public
346    */
347    public function addFooterScript($script) {
348        $this->_footerScripts[] = $script;
349    }
350
351    /**
352     * Append HTML markup (normally <script> elements) to the <head> element to
353     * the final page.
354     *
355     * @param string $headers_string HTML markup suitable for the HEAD element
356     *
357     * @return void
358     *
359     * @access public
360     */
361    public function appendHtmlHeadContent($headers_string) {
362        $this->_htmlHeaders .= $headers_string . "\n";
363    }
364
365    /**
366     * Add a stylesheet URL to the main page
367     *
368     * @param string Stylesheet URL
369     *
370     * @return void
371     *
372     * @access public
373     */
374    public function appendStylesheetURL($stylesheet_url) {
375        //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
376        $this->stylesheetUrlArray[$stylesheet_url] = $stylesheet_url;
377    }
378    /**
379     * Set the section to be displayed in the tool pane
380     *
381     * @param string $section Section to be displayed:
382     *                          + ADMIN for administration tool pane
383     *
384     * @return string HTML code of tool pane
385     *
386     * @access public
387     */
388    public function setToolSection($section) {
389        // Init ALL smarty SWITCH values
390        $this->smarty->assign('sectionADMIN', false);
391
392        switch ($section) {
393            case "ADMIN" :
394                // Set section of Smarty template
395                $this->smarty->assign('sectionADMIN', true);
396
397                // Get information about user
398                $_currentUser = User :: getCurrentUser();
399
400                // Init values
401                $_sqlAdditionalWhere = "";
402
403                // Init ALL smarty values
404                $this->smarty->assign('formAction', "");
405                $this->smarty->assign('nodeUI', "");
406                $this->smarty->assign('networkUI', "");
407
408                /*
409                 * If the user is super admin OR owner of at least one node
410                 * show the node menu
411                 */
412                if ($_currentUser && ($_currentUser->isSuperAdmin() || $_currentUser->isOwner())) {
413                    // Assign the action URL for the form
414                    $this->smarty->assign('formAction', GENERIC_OBJECT_ADMIN_ABS_HREF);
415
416                    /*
417                     * If current user is a owner the SQL query must be changed
418                     * to return his nodes only
419                     */
420                    if (!$_currentUser->isSuperAdmin()) {
421                        $_sqlAdditionalWhere = "AND node_id IN (SELECT node_id from node_stakeholders WHERE is_owner = true AND user_id='" . $_currentUser->getId() . "')";
422                        // Provide node select control to the template
423                        $this->smarty->assign('nodeUI', Node :: getSelectNodeUI('object_id', null, $_sqlAdditionalWhere));
424                    }
425
426                }
427
428                // If the user is network admin show the network menu
429                if ($_currentUser && $_currentUser->isSuperAdmin()) {
430                    // Provide network select control to the template
431                    $this->smarty->assign('networkUI', Network :: getSelectNetworkUI('object_id'));
432                }
433
434                // Compile HTML code
435                $_html = $this->smarty->fetch("templates/classes/MainUI_ToolSection.tpl");
436                break;
437
438            default :
439                $_html = _("Unknown section:") . $section;
440                break;
441        }
442
443        $this->addContent('left_area_middle', $_html);
444    }
445
446    /**
447     * Get the content to be displayed in the tool pane
448     *
449     * @return string HTML markup
450     *
451     * @access private
452     */
453    private function getToolContent() {
454
455        $session = Session :: getObject();
456        global $AVAIL_LOCALE_ARRAY;
457
458        // Init values
459        $_html = "";
460        $_gwId = null;
461        $_gwAddress = null;
462        $_gwPort = null;
463        $_selected = "";
464        $_languageChooser = array ();
465
466        // Init ALL smarty SWITCH values
467        $this->smarty->assign('sectionSTART', false);
468        $this->smarty->assign('sectionLOGIN', false);
469
470        // Set section of Smarty template
471        $this->smarty->assign('sectionSTART', true);
472
473        // Get information about user
474        $_currentUser = User :: getCurrentUser();
475
476        $this->smarty->assign('logoutParameters', "");
477        $this->smarty->assign('loginParameters', "");
478        $this->smarty->assign('formAction', "");
479        $this->smarty->assign('toolContent', "");
480        $this->smarty->assign('accountInformation', "");
481        $this->smarty->assign('techSupportInformation', "");
482        $this->smarty->assign('shrinkLeftArea', $this->_shrinkLeftArea);
483
484        /*
485         * Provide Smarty information about the user's login/logout status
486         */
487
488        if ($_currentUser != null) {
489            // User is logged in
490
491            // Detect gateway information
492            $_gwId = $session->get(SESS_GW_ID_VAR);
493            $_gwAddress = $session->get(SESS_GW_ADDRESS_VAR);
494            $_gwPort = $session->get(SESS_GW_PORT_VAR);
495
496            // If gateway information could be detected tell them to Smarty
497            if ($_gwId && $_gwAddress && $_gwPort) {
498                $this->smarty->assign('logoutParameters', "&amp;gw_id=" . $_gwId . "&amp;gw_address=" . $_gwAddress . "&amp;gw_port=" . $_gwPort);
499            }
500        } else {
501            // Detect gateway information
502            $_gwId = !empty ($_REQUEST['gw_id']) ? $_REQUEST['gw_id'] : $session->get(SESS_GW_ID_VAR);
503            $_gwAddress = !empty ($_REQUEST['gw_address']) ? $_REQUEST['gw_address'] : $session->get(SESS_GW_ADDRESS_VAR);
504            $_gwPort = !empty ($_REQUEST['gw_port']) ? $_REQUEST['gw_port'] : $session->get(SESS_GW_PORT_VAR);
505
506            // If gateway information could be detected tell them Smarty
507            if (!empty ($_gwId) && !empty ($_gwAddress) && !empty ($_gwPort)) {
508                $this->smarty->assign('loginParameters', "?gw_id=" . $_gwId . "&amp;gw_address=" . $_gwAddress . "&amp;gw_port=" . $_gwPort);
509            }
510        }
511
512        /*
513         * Provide Smarty information for the language chooser
514         */
515
516        // Assign the action URL for the form
517        $this->smarty->assign('formAction', $_SERVER['REQUEST_URI']);
518
519        foreach ($AVAIL_LOCALE_ARRAY as $_langIds => $_langNames) {
520            if (Locale :: getCurrentLocale()->getId() == $_langIds) {
521                $_selected = ' selected="selected"';
522            } else {
523                $_selected = "";
524            }
525
526            $_languageChooser[] = '<option label="' . $_langNames . '" value="' . $_langIds . '"' . $_selected . '>' . $_langNames . '</option>';
527        }
528
529        // Provide Smarty all available languages
530        $this->smarty->assign('languageChooser', $_languageChooser);
531
532        // Compile HTML code
533        $_html = $this->smarty->fetch("templates/classes/MainUI_ToolContent.tpl");
534
535        return $_html;
536    }
537
538    /**
539     * Display the main page
540     *
541     * @return void
542     *
543     * @access public
544     * @internal Uses a few request parameters to display debug information.
545     * If $_REQUEST['debug_request'] is present, it will print out the
546     * $_REQUEST array at the top of the page.
547     */
548    public function display() {
549        $db = AbstractDb :: getObject();
550        // Init values
551        // Asign base CSS and theme pack CSS stylesheet
552        $this->appendStylesheetURL(BASE_THEME_URL . STYLESHEET_NAME);
553        $networkThemePack = Network :: getCurrentNetwork()->getThemePack();
554        if ($networkThemePack) {
555            $this->appendStylesheetURL($networkThemePack->getStylesheetUrl());
556        }
557
558        //Handle content (must be done before headers and anything else is handled)
559        /*
560         * Build tool pane if it has been enabled
561         */
562        if ($this->isToolSectionEnabled()) {
563            $this->addContent('left_area_top', $this->getToolContent());
564        }
565        $this->addEverywhereContent();
566        $this->generateDisplayContent();
567
568        // Init ALL smarty values
569        $this->smarty->assign('htmlHeaders', "");
570        // $this->smarty->assign('isSuperAdmin', false);
571        // $this->smarty->assign('isOwner', false);
572        $this->smarty->assign('debugRequested', false);
573        $this->smarty->assign('debugOutput', "");
574        $this->smarty->assign('footerScripts', array ());
575
576        // Add HTML headers
577        $this->smarty->assign('htmlHeaders', $this->_htmlHeaders);
578
579        // Asign title
580        $this->smarty->assign('title', $this->title);
581
582        // Asign CSS class for body
583        $this->smarty->assign('page_name', $this->_pageName);
584
585        $this->smarty->assign('stylesheetUrlArray', $this->stylesheetUrlArray);
586
587        /*
588         * Allow super admin to display debug output if requested by using
589         * $_REQUEST['debug_request']
590         */
591
592        // Provide footer scripts to Smarty
593        $this->smarty->assign('footerScripts', $this->_footerScripts);
594
595        // Add SQL queries log (must be done manually here at the very end to catch everything)
596        if (defined("LOG_SQL_QUERIES") && LOG_SQL_QUERIES == true)
597            $this->_contentDisplayArray['page_footer'] .= $db->getSqlQueriesLog();
598
599        // Provide the content array to Smarty
600        $this->smarty->assign('contentDisplayArray', $this->_contentDisplayArray);
601
602        // Compile HTML code and output it
603        $this->smarty->display("templates/classes/MainUI_Display.tpl");
604    }
605
606    /**
607     * Display a generic error message
608     *
609     * @param string $errmsg                  The error message to be displayed
610     * @param bool   $show_tech_support_email Defines wether to show the link of
611     *                                        the tech-support
612     *
613     * @return void
614     *
615     * @access public
616     */
617    function displayError($errmsg, $show_tech_support_email = true) {
618        // Init ALL smarty values
619        $this->smarty->assign("error", "");
620        $this->smarty->assign("show_tech_support_email", false);
621        $this->smarty->assign("tech_support_email", "");
622
623        // Define needed error content
624        $this->smarty->assign("error", $errmsg);
625
626        if ($show_tech_support_email) {
627            $this->smarty->assign("show_tech_support_email", true);
628            $this->smarty->assign("tech_support_email", Network :: getCurrentNetwork()->getTechSupportEmail());
629        }
630
631        /*
632         * Output the error message
633         */
634        $_html = $this->smarty->fetch("templates/sites/error.tpl");
635
636        $this->addContent('page_header', $_html);
637        $this->display();
638    }
639
640    static public function redirect($redirect_url, $redirect_to_title = null, $timeout = 60) {
641        if (!$redirect_to_title) {
642            $network = Network :: getCurrentNetwork();
643            $redirect_to_title = $network ? sprintf(_("%s Login"), $network->getName()) : _("Login");
644        }
645
646        header("Location: $redirect_url");
647        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";
648        exit;
649    }
650}
651
652/*
653 * Local variables:
654 * tab-width: 4
655 * c-basic-offset: 4
656 * c-hanging-comment-ender-p: nil
657 * End:
658 */
Note: See TracBrowser for help on using the browser.