root/trunk/wifidog-auth/wifidog/classes/Node.php @ 1253

Revision 1253, 55.9 KB (checked in by benoitg, 6 years ago)
  • Node.php: Improve getCurrentRealNode()
  • Implement #4: Allow the user to easily come back to the portal by typing in the root auth server adress from a hotspot.
  • Log the system information sent with the gateway since almost forever: sys_uptime, sys_memfree, sys_load, wifidog_uptime
  • NodeStatus?.php: Include the above information
  • node_list.html: Include wifidog_uptime if the hotspot is up.
  • Menu.php: Sort menus alphabetically according to the user's locale. TODO: Implement menu weights.
  • NodeLists?: Only list node types that have dependencies met in the menu. Refactor the NodeLists? for proper object-orientation.


  • 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/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5// +-------------------------------------------------------------------+
6// | WiFiDog Authentication Server                                     |
7// | =============================                                     |
8// |                                                                   |
9// | The WiFiDog Authentication Server is part of the WiFiDog captive  |
10// | portal suite.                                                     |
11// +-------------------------------------------------------------------+
12// | PHP version 5 required.                                           |
13// +-------------------------------------------------------------------+
14// | Homepage:     http://www.wifidog.org/                             |
15// | Source Forge: http://sourceforge.net/projects/wifidog/            |
16// +-------------------------------------------------------------------+
17// | This program is free software; you can redistribute it and/or     |
18// | modify it under the terms of the GNU General Public License as    |
19// | published by the Free Software Foundation; either version 2 of    |
20// | the License, or (at your option) any later version.               |
21// |                                                                   |
22// | This program is distributed in the hope that it will be useful,   |
23// | but WITHOUT ANY WARRANTY; without even the implied warranty of    |
24// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     |
25// | GNU General Public License for more details.                      |
26// |                                                                   |
27// | You should have received a copy of the GNU General Public License |
28// | along with this program; if not, contact:                         |
29// |                                                                   |
30// | Free Software Foundation           Voice:  +1-617-542-5942        |
31// | 59 Temple Place - Suite 330        Fax:    +1-617-542-2652        |
32// | Boston, MA  02111-1307,  USA       gnu@gnu.org                    |
33// |                                                                   |
34// +-------------------------------------------------------------------+
35
36/**
37 * @package    WiFiDogAuthServer
38 * @author     Benoit Grégoire <bock@step.polymtl.ca>
39 * @copyright  2005-2006 Benoit Grégoire, Technologies Coeus inc.
40 * @version    Subversion $Id$
41 * @link       http://www.wifidog.org/
42 */
43
44/**
45 * Load required classes
46 */
47require_once('classes/User.php');
48require_once('classes/GisPoint.php');
49require_once('classes/AbstractGeocoder.php');
50require_once('classes/Utils.php');
51require_once('classes/DateTimeWD.php');
52
53/**
54 * Abstract a Node.  A Node is an actual physical transmitter.
55 *
56 * @todo Make all the setter functions no-op if the value is the same as what
57 * was already stored Use setCustomPortalReduirectUrl as an example
58 *
59 * @package    WiFiDogAuthServer
60 * @author     Benoit Grégoire <bock@step.polymtl.ca>
61 * @copyright  2005 Benoit Grégoire, Technologies Coeus inc.
62 */
63class Node implements GenericObject
64{
65    /** Object cache for the object factory (getObject())*/
66    private static $instanceArray = array();
67    private $_row;
68    private $mdB; /**< An AbstractDb instance */
69    private $id;
70    private static $current_node_id = null;
71
72    /**
73     * List of deployment statuses
74     *
75     * @var array
76     * @access private
77     */
78    private $_deploymentStatuses = array();
79
80    /**
81     * Defines a warning message
82     *
83     * @var string
84     *
85     * @access private
86     */
87    private $_warningMessage;
88
89    /** Instantiate a node object
90     * @param $id The id of the requested node
91     * @return a Node object, or null if there was an error
92     */
93    public static function &getObject($id)
94    {
95        if(!isset(self::$instanceArray[$id]))
96        {
97            self::$instanceArray[$id] = new self($id);
98        }
99        return self::$instanceArray[$id];
100    }
101
102    /** Instantiate a node object using it's gateway id
103     * @param $gwId The id of the requested node
104     * @return a Node object, or null if there was an error
105     */
106    static function getObjectByGatewayId($gwId)
107    {
108        $object = null;
109        $object = new self($gwId, 'GATEWAY_ID');
110        return $object;
111    }
112    /** Get the current node for which the portal is displayed or to which a user is physically connected.
113     * @param $real_node_only true or false.  If true, the real physical node where the user is connected is returned, and the node set by setCurrentNode is ignored.
114     * @return a Node object, or null if it can't be found.
115     */
116    static function getCurrentNode($real_node_only = false)
117    {
118        $object = null;
119        if (self :: $current_node_id != null && $real_node_only == false)
120        {
121            $object = self::getObject(self :: $current_node_id);
122        }
123        else
124        {
125            $object = self :: getCurrentRealNode();
126        }
127        return $object;
128    }
129
130    /** Set the current node where the user is to be considered connected to.  (For portal and content display purpuses, among other.
131     * @param $node Node.  The new current node.
132     * @return true      */
133    static function setCurrentNode(Node $node)
134    {
135        self :: $current_node_id = $node->GetId();
136        return true;
137    }
138
139    /** Get the current node to which a user is physically connected, if any.  This is done by an IP address lookup against the last reported IP address of the node
140     * @param    * @return a Node object, or null if it can't be found.
141     */
142    public static function getCurrentRealNode()
143    {
144        static $currentRealNode;//For caching
145        static $currentRealNodeComputed;//For caching
146        $currentIp = $_SERVER['REMOTE_ADDR'];
147        //For testing:
148        //$currentIp = '24.201.12.219';
149        if(!isset($currentRealNodeComputed))
150        {
151            $currentRealNodeComputed=true;
152            $db = AbstractDb::getObject();
153            $sql_ip = "SELECT node_id from nodes WHERE last_heartbeat_ip='$currentIp' ORDER BY last_heartbeat_timestamp DESC";
154            $node_rows = null;
155            $db->execSql($sql_ip, $node_rows, false);
156            $num_match = count($node_rows);
157            if ($num_match == 0)
158            {
159                // User is not physically connected to a node
160                $currentRealNode = null;
161            }
162            else if ($num_match == 1)
163            {
164                // Only a single node matches, the user is presumed to be there
165                $currentRealNode = self::getObject($node_rows[0]['node_id']);
166            }
167            else
168            {
169                /* We have more than one node matching the IP (the nodes are behind the same NAT).*/
170                $currentRealNode = null;
171                $current_user = User :: getCurrentUser();
172                if ($current_user != null)
173                {
174                    /* We will try to discriminate by finding which node the user last authenticated against.
175                     * If the IP matches, we can be pretty certain the user is there.
176                     */
177                    $current_user_id = $current_user->getId();
178                    $sql = "SELECT node_id, last_heartbeat_ip, name, last_updated from connections NATURAL JOIN nodes WHERE user_id='$current_user_id' AND node_id IN ($sql_ip) ORDER BY last_updated DESC ";
179                    //$db->execSql($sql, $tmp, true);
180                    $db->execSqlUniqueRes("$sql LIMIT 1", $node_row, false);
181                    if ($node_row != null)
182                    {
183                        $currentRealNode = self::getObject($node_row['node_id']);
184                    }
185                }
186                else {
187                    /* Darn, the user doesn't have a session open, we can only take the first node in the list, which is marginaly better than nothing */
188                    $currentRealNode = self::getObject($node_rows[0]['node_id']);
189                }
190            }
191        }
192        return $currentRealNode;
193    }
194
195    public function delete(& $errmsg)
196    {
197        $retval = false;
198        $user = User :: getCurrentUser();
199        if ($user->DEPRECATEDisSuperAdmin()) {
200            $db = AbstractDb::getObject();
201            $id = $db->escapeString($this->getId());
202            if (!$db->execSqlUpdate("DELETE FROM nodes WHERE node_id='{$id}'", false))
203            {
204                $errmsg = _('Could not delete node!');
205            }
206            else
207            {
208                $retval = true;
209            }
210        }
211        else
212        {
213            $errmsg = _('Access denied!');
214        }
215
216        return $retval;
217    }
218
219    /**
220     * Create a new Node in the database
221     *
222     * @param string $gw_id The Id of the gatewqay to be associated with
223     * thisnode. If not present, a dummy value will be assigned.
224     * @param object $network Network object.  The node's network.  If not
225     *                        present, the current Network will be assigned
226     *
227     * @return mixed The newly created Node object, or null if there was
228     *               an error
229     *
230     * @static
231     * @access public
232     */
233    public static function createNewObject($gw_id = null, $network = null)
234    {
235        $db = AbstractDb::getObject();
236        if (empty ($gw_id)) {
237            $gw_id = $db->escapeString(_('PUT_GATEWAY_ID_HERE'));
238        }
239        else
240        {
241            $gw_id = $db->escapeString($gw_id);
242        }
243        $node_id = get_guid();
244
245
246        if (empty ($network)) {
247            $network = Network::getCurrentNetwork();
248        }
249
250        $network_id = $db->escapeString($network->getId());
251
252        $node_deployment_status = $db->escapeString("IN_PLANNING");
253        $node_name = _("New node");
254        $duplicate = null;
255        try{
256            $duplicate = Node::getObjectByGatewayId($gw_id);
257        }
258        catch (Exception $e)
259        {
260        }
261        if ($duplicate) {
262            throw new Exception(sprintf(_('Sorry, a node for the gateway %s already exists.'),$gw_id));
263        }
264
265        $sql = "INSERT INTO nodes (node_id, gw_id, network_id, creation_date, node_deployment_status, name) VALUES ('$node_id', '$gw_id', '$network_id', CURRENT_TIMESTAMP,'$node_deployment_status', '$node_name')";
266
267        if (!$db->execSqlUpdate($sql, false)) {
268            throw new Exception(_('Unable to insert new node into database!'));
269        }
270
271        $object = self::getObject($node_id);
272
273        return $object;
274    }
275
276    /** Get an interface to pick a node.
277     * @param $user_prefix A identifier provided by the programmer to recognise it's generated html form
278     *
279     * @param $sql_additional_where Addidional where conditions to restrict the candidate objects
280     * @param $type_interface:  select, select_multiple or table
281     * @param $selectedNodes; Node object or array of node objects to be pre-selected (not
282     * supported by type_interface=table)
283     * * @return html markup
284     */
285    public static function getSelectNodeUI($user_prefix, $sql_additional_join = null, $sql_additional_where = null,$selectedNodes = null, $type_interface = "select")
286    {
287        $db = AbstractDb::getObject();
288        $html = '';
289        $name = "{$user_prefix}";
290
291        $_deploymentStatuses = array(
292        "DEPLOYED" => _("Deployed"),
293        "IN_PLANNING" => _("In planning"),
294        "IN_TESTING" => _("In testing"),
295        "NON_WIFIDOG_NODE" => _("Non-Wifidog node"),
296        "PERMANENTLY_CLOSED" => _("Permanently closed"),
297        "TEMPORARILY_CLOSED" => _("Temporarily closed")
298        );
299
300        $sql = "SELECT nodes.node_id, nodes.name, nodes.gw_id, nodes.node_deployment_status, nodes.is_splash_only_node from nodes $sql_additional_join WHERE 1=1 $sql_additional_where ORDER BY lower(nodes.node_id)";
301        $node_rows = null;
302        $db->execSql($sql, $node_rows, false);
303
304        if ($node_rows != null) {
305            Utils :: natsort2d($node_rows, "name");
306            if ($type_interface != "table") {
307                $i = 0;
308                foreach ($node_rows as $node_row)
309                {
310                    $tab[$i][0] = $node_row['node_id'];
311                    //$tab[$i][1] = sprintf(_("%s (gw: %s)"),$node_row['name'],$node_row['gw_id']);
312                    $tab[$i][1] = $node_row['name'];
313                    $i ++;
314                }
315                if($type_interface == "select_multiple"){
316                    $select_options="MULTIPLE SIZE=6";
317                }
318                else
319                {
320                    $select_options=null;
321                }
322                //pretty_print_r($selectedNodes);
323                if(is_array($selectedNodes)){
324                    $selectedPrimaryKey=array();
325                    foreach($selectedNodes as $node){
326                        $selectedPrimaryKey[]=$node->getId();
327                    }
328
329                }
330                else if($selectedNodes instanceof Node){
331                    $selectedPrimaryKey=$selectedNodes->getId();
332                }
333                else{
334                    $selectedPrimaryKey=null;
335                }
336                $html .= FormSelectGenerator :: generateFromArray($tab, $selectedPrimaryKey, $name, null, false, null, $select_options);
337            } else {
338                $html .= "<fieldset>\n    <legend>Node List</legend>\n";
339                $html .= "    <span class='node_admin'>"._("Filter:")."<input type=\"text\" tabindex=\"1\" maxlength=\"40\" size=\"40\" id=\"nodes_list_filter\" name=\"nodes_list_filter\" /></span>\n    <br/>\n";
340                $html .= "    <!--[if IE]><style type='text/css'>#node_list_div table.scrollable>tbody { height: 15px; }</style><![endif]-->\n";
341                $html .= "    <script src='" . BASE_URL_PATH . "js/filtertable.js' type='text/javascript' language='javascript' charset='utf-8'></script>\n";
342                $html .= "    <script src='" . BASE_URL_PATH . "js/sorttable.js' type='text/javascript' language='javascript' charset='utf-8'></script>\n";
343                $html .= "    <div id='node_list_div' class='node_admin tableContainer'>\n";
344                $html .= "        <table id='nodes_list' class='node_admin filterable scrollable sortable'>\n\n";
345                $html .= "            <thead class='fixedHeader'>\n";
346                $html .= "<tr class='nofilter'>\n";
347                $html .= "<th>"._("Node Name")."</th>\n";
348                $html .= "<th>"._("Gateway ID")."</th>\n";
349                $html .= "<th>"._("Deployment Status")."</th>\n";
350                $html .= "</tr>\n";
351                $html .= "</thead>\n";
352                $html .= "<tbody>";
353
354                $i = 0;
355                foreach ($node_rows as $node_row)
356                {
357                    $href = GENERIC_OBJECT_ADMIN_ABS_HREF."?object_id={$node_row['node_id']}&object_class=Node&action=edit";
358                    $_deployStatusNode = $node_row['node_deployment_status'];
359                    $html .= "<tr class='row' onclick=\"javascript:location.href='{$href}'\">\n";
360                    $html .= "<td>{$node_row['name']}<noscript>(<a href='{$href}'>edit</a>)</noscript></td>\n";
361                    $html .= "<td>{$node_row['gw_id']}</td>\n";
362                    $html .= "<td>{$_deploymentStatuses[$_deployStatusNode]}</td>\n";
363                    $html .= "</tr>\n";
364                }
365                $html .= "            </tbody>\n        </table>\n";
366                $html .= "    </div>\n";
367                $html .= "</fieldset>\n";
368
369            }
370        } else {
371            $html .= "<div class='warningmsg'>"._("Sorry, no nodes available in the database")."</div>\n";
372        }
373        return $html;
374    }
375
376
377    /** Get the selected Network object.
378     * @param $user_prefix A identifier provided by the programmer to recognise it's generated form
379     * @return the node object
380     */
381    static function processSelectNodeUI($user_prefix)
382    {
383        $object = null;
384        $name = "{$user_prefix}";
385        return self::getObject($_REQUEST[$name]);
386    }
387
388    /** Get an interface to create a new node.
389     * @param $network Optional:  The network to which the new node will belong,
390     * if absent, the user will be prompted.
391     * @return html markup
392     */
393    public static function getCreateNewObjectUI($network = null)
394    {
395        $html = '';
396        $html .= _("Add a new node for the gateway ID")." \n";
397        $name = "new_node_gw_id";
398        $html .= "<input type='text' size='10' name='{$name}'>\n";
399        if ($network)
400        {
401            $name = "new_node_network_id";
402            $html .= "<input type='hidden' name='{$name}' value='{$network->getId()}'>\n";
403        }
404        else
405        {
406            $html .= " "._("in ")." \n";
407            $html .= Network :: getSelectUI('new_node');
408        }
409        return $html;
410
411    }
412
413    /**
414     * Process the new object interface.
415     *
416     * Will return the new object if the user has the credentials and the form was fully filled.
417     * @return the node object or null if no new node was created.
418     */
419    public static function processCreateNewObjectUI()
420    {
421        // Init values
422        $retval = null;
423        $name = "new_node_gw_id";
424
425        if (!empty ($_REQUEST[$name])) {
426            $gw_id = $_REQUEST[$name];
427        }
428        else
429        {
430            $gw_id = null;
431        }
432        $name = "new_node_network_id";
433
434        if (!empty ($_REQUEST[$name])) {
435            $network = Network::getObject($_REQUEST[$name]);
436        } else {
437            $network = Network::processSelectUI('new_node');
438        }
439
440        if ($network) {
441            try {
442                if (!$network->DEPRECATEDhasAdminAccess(User :: getCurrentUser())) {
443                    throw new Exception(_("Access denied"));
444                }
445            } catch (Exception $e) {
446                $ui = MainUI::getObject();
447                $ui->displayError($e->getMessage(), false);
448                exit;
449            }
450
451            $retval = self::createNewObject($gw_id, $network);
452        }
453
454        return $retval;
455    }
456
457    /**
458     * Get an interface to select the deployment status
459     *
460     * @param string $user_prefix A identifier provided by the programmer to
461     *                            recognise it's generated html form
462     *
463     * @return string HTML markup
464     */
465    public function getSelectDeploymentStatus($user_prefix)
466    {
467         
468        $db = AbstractDb::getObject();
469
470        // Init values
471        $html = "";
472        $status_list = null;
473        $tab = array();
474
475        $name = "{$user_prefix}";
476        $db->execSql("SELECT node_deployment_status FROM node_deployment_status", $status_list, false);
477
478        if ($status_list == null) {
479            throw new Exception(_("No deployment statuses could be found in the database"));
480        }
481
482        foreach ($status_list as $status) {
483            $_statusvalue = $status['node_deployment_status'];
484            $tab[] = array($_statusvalue, $this->_deploymentStatuses["$_statusvalue"]);
485        }
486
487        $html .= FormSelectGenerator::generateFromArray($tab, $this->getDeploymentStatus(), $name, null, false);
488
489        return $html;
490    }
491
492    /**
493     * Get the selected deployment status
494     *
495     * @param string $user_prefix An identifier provided by the programmer to
496     *                            recognise it's generated form
497     *
498     * @return string The deployment status
499
500     */
501    public function processSelectDeploymentStatus($user_prefix)
502    {
503        $object = null;
504        $name = "{$user_prefix}";
505        return $_REQUEST[$name];
506    }
507
508    /** @param $id The id of the node
509     * @param $idType 'NODE_ID' or 'GATEWAY_ID'*/
510    private function __construct($id, $idType='NODE_ID')
511    {
512        $db = AbstractDb::getObject();
513        $this->mDb = & $db;
514
515        $id_str = $db->escapeString($id);
516        switch ($idType) {
517            case 'NODE_ID': $sqlWhere = "node_id='$id_str'";
518            break;
519            case 'GATEWAY_ID': $sqlWhere = "gw_id='$id_str'";
520            break;
521            default:
522                throw new exception('Unknown idType parameter');
523        }
524        $sqlWhere =
525        $sql = "SELECT * FROM nodes WHERE $sqlWhere";
526        $row = null;
527        $db->execSqlUniqueRes($sql, $row, false);
528        if ($row == null)
529        {
530            throw new Exception(sprintf(_("The node with %s: %s could not be found in the database!"), $idType, $id_str));
531        }
532
533        $this->_deploymentStatuses = array(
534        "DEPLOYED" => _("Deployed"),
535        "IN_PLANNING" => _("In planning"),
536        "IN_TESTING" => _("In testing"),
537        "NON_WIFIDOG_NODE" => _("Non-Wifidog node"),
538        "PERMANENTLY_CLOSED" => _("Permanently closed"),
539        "TEMPORARILY_CLOSED" => _("Temporarily closed")
540        );
541
542        $this->_row = $row;
543        $this->id = $row['node_id'];
544    }
545
546    function __toString() {
547        return $this->getName();
548    }
549
550    function getId()
551    {
552        return $this->id;
553    }
554
555    /** Get the id of the gateway associated with this node */
556    function getGatewayId()
557    {
558        return $this->_row['gw_id'];
559    }
560    /** Change the gateway ID of the gateway asociated with this node.
561     * @param $id, string, the new node id.
562     * @return true on success, false on failure. Check this,
563     * as it's possible that someone will enter an existing id, especially
564     * if the MAC address is used and hardware is recycled.
565     */
566    function setGatewayId($id)
567    {
568        $id = $this->mDb->escapeString($id);
569        $retval = $this->mDb->execSqlUpdate("UPDATE nodes SET gw_id = '{$id}' WHERE node_id = '{$this->getId()}'");
570        if ($retval)
571        {
572            $this->refresh();
573        }
574        return $retval;
575    }
576
577    /** Gets the Network to which the node belongs
578     * @return Network object (never returns null)
579     */
580    public function getNetwork()
581    {
582        return Network :: getObject($this->_row['network_id']);
583    }
584
585    /** Get a GisPoint object ; altide is not supported yet
586     */
587    function getGisLocation()
588    {
589        // Altitude is not supported yet
590        return new GisPoint($this->_row['latitude'], $this->_row['longitude'], 0);
591    }
592
593    function setGisLocation($pt)
594    {
595        if (!empty ($pt))
596        {
597            $lat = $this->mDb->escapeString($pt->getLatitude());
598            $long = $this->mDb->escapeString($pt->getLongitude());
599
600            if (!empty ($lat) && !empty ($long))
601            $this->mDb->execSqlUpdate("UPDATE nodes SET latitude = $lat, longitude = $long WHERE node_id = '{$this->getId()}'");
602            else
603            $this->mDb->execSqlUpdate("UPDATE nodes SET latitude = NULL, longitude = NULL WHERE node_id = '{$this->getId()}'");
604            $this->refresh();
605        }
606    }
607
608    /** Return the name of the node
609     */
610    function getName()
611    {
612        return $this->_row['name'];
613    }
614
615    function setName($name)
616    {
617        $name = $this->mDb->escapeString($name);
618        $this->mDb->execSqlUpdate("UPDATE nodes SET name = '{$name}' WHERE node_id = '{$this->getId()}'");
619        $this->refresh();
620    }
621
622    function getCreationDate()
623    {
624        return $this->_row['creation_date'];
625    }
626
627    function setCreationDate($creation_date)
628    {
629        $creation_date = $this->mDb->escapeString($creation_date);
630        $this->mDb->execSqlUpdate("UPDATE nodes SET creation_date = '{$creation_date}' WHERE node_id = '{$this->getId()}'");
631        $this->refresh();
632    }
633
634    function getWebSiteURL()
635    {
636        return $this->_row['home_page_url'];
637    }
638
639    function setWebSiteUrl($url)
640    {
641        $url = $this->mDb->escapeString($url);
642        $this->mDb->execSqlUpdate("UPDATE nodes SET home_page_url = '{$url}' WHERE node_id = '{$this->getId()}'");
643        $this->refresh();
644    }
645
646    function getDescription()
647    {
648        return $this->_row['description'];
649    }
650
651    function setDescription($description)
652    {
653        $description = $this->mDb->escapeString($description);
654        $this->mDb->execSqlUpdate("UPDATE nodes SET description = '{$description}' WHERE node_id = '{$this->getId()}'");
655        $this->refresh();
656    }
657
658    function getMapURL()
659    {
660        return $this->_row['map_url'];
661    }
662
663    function setMapURL($url)
664    {
665        $url = $this->mDb->escapeString($url);
666        $this->mDb->execSqlUpdate("UPDATE nodes SET map_url = '{$url}' WHERE node_id = '{$this->getId()}'");
667        $this->refresh();
668    }
669
670    public function getCivicNumber()
671    {
672        return $this->_row['civic_number'];
673    }
674
675    public function setCivicNumber($civic_number)
676    {
677        $civic_number = $this->mDb->escapeString($civic_number);
678        $this->mDb->execSqlUpdate("UPDATE nodes SET civic_number = '{$civic_number}' WHERE node_id = '{$this->getId()}'");
679        $this->refresh();
680    }
681
682    public function getStreetName()
683    {
684        return $this->_row['street_name'];
685    }
686
687    public function setStreetName($street_name)
688    {
689        $street_name = $this->mDb->escapeString($street_name);
690        $this->mDb->execSqlUpdate("UPDATE nodes SET street_name = '{$street_name}' WHERE node_id = '{$this->getId()}'");
691        $this->refresh();
692    }
693
694    public function getCity()
695    {
696        return $this->_row['city'];
697    }
698
699    public function setCity($city)
700    {
701        $city = $this->mDb->escapeString($city);
702        $this->mDb->execSqlUpdate("UPDATE nodes SET city = '{$city}' WHERE node_id = '{$this->getId()}'");
703        $this->refresh();
704    }
705
706    public function getProvince()
707    {
708        return $this->_row['province'];
709    }
710
711    public function setProvince($province)
712    {
713        $province = $this->mDb->escapeString($province);
714        $this->mDb->execSqlUpdate("UPDATE nodes SET province = '{$province}' WHERE node_id = '{$this->getId()}'");
715        $this->refresh();
716    }
717
718    public function getCountry()
719    {
720        return $this->_row['country'];
721    }
722
723    protected function setCountry($country)
724    {
725        $country = $this->mDb->escapeString($country);
726        $this->mDb->execSqlUpdate("UPDATE nodes SET country = '{$country}' WHERE node_id = '{$this->getId()}'");
727        $this->refresh();
728    }
729
730    public function getPostalCode()
731    {
732        return $this->_row['postal_code'];
733    }
734
735    public function setPostalCode($postal_code)
736    {
737        $postal_code = $this->mDb->escapeString($postal_code);
738        $this->mDb->execSqlUpdate("UPDATE nodes SET postal_code = '{$postal_code}' WHERE node_id = '{$this->getId()}'");
739        $this->refresh();
740    }
741
742    function getTelephone()
743    {
744        return $this->_row['public_phone_number'];
745    }
746
747    function setTelephone($phone)
748    {
749        $phone = $this->mDb->escapeString($phone);
750        $this->mDb->execSqlUpdate("UPDATE nodes SET public_phone_number = '{$phone}' WHERE node_id = '{$this->getId()}'");
751        $this->refresh();
752    }
753
754    function getTransitInfo()
755    {
756        return $this->_row['mass_transit_info'];
757    }
758
759    function setTransitInfo($transit_info)
760    {
761        $transit_info = $this->mDb->escapeString($transit_info);
762        $this->mDb->execSqlUpdate("UPDATE nodes SET mass_transit_info = '{$transit_info}' WHERE node_id = '{$this->getId()}'");
763        $this->refresh();
764    }
765
766    function getEmail()
767    {
768        return $this->_row['public_email'];
769    }
770
771    function setEmail($email)
772    {
773        $email = $this->mDb->escapeString($email);
774        $this->mDb->execSqlUpdate("UPDATE nodes SET public_email = '{$email}' WHERE node_id = '{$this->getId()}'");
775        $this->refresh();
776    }
777
778    function getDeploymentStatus()
779    {
780        return $this->_row['node_deployment_status'];
781    }
782
783    function setDeploymentStatus($status)
784    {
785        $status = $this->mDb->escapeString($status);
786        $this->mDb->execSqlUpdate("UPDATE nodes SET node_deployment_status = '{$status}' WHERE node_id = '{$this->getId()}'");
787        $this->refresh();
788    }
789
790    function getLastPaged()
791    {
792        return $this->_row['last_paged'];
793    }
794
795    function setLastPaged($last_paged)
796    {
797        $this->mDb->execSqlUpdate("UPDATE nodes SET last_paged = {$last_paged}::abstime WHERE node_id = '{$this->getId()}'");
798        $this->refresh();
799    }
800
801    function getLastHeartbeatIP()
802    {
803        return $this->_row['last_heartbeat_ip'];
804    }
805
806    function getLastHeartbeatUserAgent()
807    {
808        return $this->_row['last_heartbeat_user_agent'];
809    }
810
811    function getLastHeartbeatWifidogUptime()
812    {
813        return $this->_row['last_heartbeat_wifidog_uptime'];
814    }
815   
816    function getLastHeartbeatSysUptime()
817    {
818        return $this->_row['last_heartbeat_sys_uptime'];
819    }
820   
821    function getLastHeartbeatSysLoad()
822    {
823        return $this->_row['last_heartbeat_sys_load'];
824    }
825   
826    function getLastHeartbeatSysMemfree()
827    {
828        return $this->_row['last_heartbeat_sys_memfree'];
829    }
830     
831    function getLastHeartbeatTimestamp()
832    {
833        return $this->_row['last_heartbeat_timestamp'];
834    }
835
836    function setLastHeartbeatTimestamp($timestamp)
837    {
838        $this->mDb->execSqlUpdate("UPDATE nodes SET last_heartbeat_timestamp = '{$timestamp}' WHERE node_id = '{$this->getId()}'");
839        $this->refresh();
840    }
841
842    /** Is the node a Splash Only node?  Will only return true if the Network configuration allows it.
843     * @return true or false */
844    public function isSplashOnly()
845    {
846        return $this->getNetwork()->getSplashOnlyNodesAllowed() && $this->isConfiguredSplashOnly();
847    }
848
849    /** Is the node configured as a Splash Only node?  This is NOT the same as isSplashOnly().
850     * This is the getter for the configuration set in the database for this node.
851     * For the node to actually be splash only, this AND the network
852     * gonfiguration must match.
853     * @return true or false */
854    public function isConfiguredSplashOnly()
855    {
856        return (($this->_row['is_splash_only_node'] == 't') ? true : false);
857    }
858
859    /** Set if this node should be a splash-only (no login) node (if enabled in Network configuration)
860     * @param $value The new value, true or false
861     * @return true on success, false on failure */
862    function setIsConfiguredSplashOnly($value)
863    {
864        $retval = true;
865        if ($value != $this->isConfiguredSplashOnly())
866        {
867            $db = AbstractDb::getObject();
868            $value ? $value = 'TRUE' : $value = 'FALSE';
869            $retval = $db->execSqlUpdate("UPDATE nodes SET is_splash_only_node = {$value} WHERE node_id = '{$this->getId()}'", false);
870            $this->refresh();
871        }
872        return $retval;
873    }
874
875    /** The url to show instead of the portal.  If empty, the portal is shown
876     Must be enabled in the Network configuration to have any effect
877     @return a string */
878    function getCustomPortalRedirectUrl()
879    {
880        return $this->_row['custom_portal_redirect_url'];
881    }
882
883    /** The url to show instead of the portal.  If empty, the portal is shown
884     Must be enabled in the Network configuration to have any effect
885     @return true on success, false on failure */
886    function setCustomPortalRedirectUrl($value)
887    {
888        $retval = true;
889        if ($value != $this->getCustomPortalRedirectUrl())
890        {
891            $db = AbstractDb::getObject();
892            $value = $db->escapeString($value);
893            $retval = $db->execSqlUpdate("UPDATE nodes SET custom_portal_redirect_url = '{$value}' WHERE node_id = '{$this->getId()}'", false);
894            $this->refresh();
895        }
896        return $retval;
897    }
898
899    /**
900     * Retrieves the admin interface of this object
901     *
902     * @return string The HTML fragment for this interface
903     *
904     * @access public
905     *
906     * @todo Most of this code will be moved to Hotspot class when the
907     *       abtraction will be completed
908     */
909    public function getAdminUI()
910    {
911        $permArray[]=array(Permission::P('NETWORK_PERM_EDIT_ANY_NODE_CONFIG'), $this->getNetwork());
912        $permArray[]=array(Permission::P('NODE_PERM_EDIT_CONFIG'), $this);
913        $permArray[]=array(Permission::P('NODE_PERM_EDIT_GATEWAY_ID'), $this);
914        Security::requireAnyPermission($permArray);
915        require_once('classes/InterfaceElements.php');
916        require_once('classes/Stakeholder.php');
917        // Init values
918        $html = '';
919
920        // Get information about the network
921        $network = $this->getNetwork();
922
923        // Check if user is a admin
924        $_userIsAdmin = User::getCurrentUser()->DEPRECATEDisSuperAdmin();
925
926        $node_id = $this->getId();
927
928        /*
929         * Check for a warning message
930         */
931        if ($this->_warningMessage != "") {
932            $html .= "<div class='errormsg'>".$this->_warningMessage."</div>\n";
933        }
934
935        /*
936         * Begin with admin interface
937         */
938        $html .= "<fieldset class='admin_container ".get_class($this)."'>\n";
939        $html .= "<legend>"._("Edit a node")."</legend>\n";
940        $html .= "<ul class='admin_element_list'>\n";
941
942        /*
943         * Display stats
944         */
945        $_title = _("Statistics");
946        $_data = InterfaceElements::generateInputSubmit("node_" . $this->id . "_get_stats", _("Get access statistics"), "node_get_stats_submit");
947        $html .= InterfaceElements::generateAdminSectionContainer("node_get_stats", $_title, $_data);
948
949        /*
950         * Information about the node
951         */
952        $_html_node_information = array();
953
954        // Gateway ID
955        $_title = _("Gateway ID");
956        if (Security::hasPermission(Permission::P('NODE_PERM_EDIT_GATEWAY_ID'), $this)) {
957            $_data = InterfaceElements::generateInputText("node_" . $node_id . "_gw_id", $this->getGatewayId(), "gw_id_input");
958        } else {
959            $_data  = htmlspecialchars($this->getGatewayId(), ENT_QUOTES);
960            $_data .= InterfaceElements::generateInputHidden("node_" . $node_id . "_gw_id", $this->getGatewayId());
961        }
962        $_html_node_information[] = InterfaceElements::generateAdminSectionContainer("gateway_id", $_title, $_data);
963
964        //Node content
965        $_html_content = array();
966        $_title = _("Node content");
967        $_data = Content::getLinkedContentUI("node_" . $node_id . "_content", "node_has_content", "node_id", $this->id, "portal");
968        $html .= InterfaceElements::generateAdminSectionContainer("node_content", $_title, $_data);
969
970        // Name
971        $_title = _("Name");
972        $_data = InterfaceElements::generateInputText("node_" . $node_id . "_name", $this->getName(), "node_name_input");
973        $_html_node_information[] = InterfaceElements::generateAdminSectionContainer("node_name", $_title, $_data);
974
975        // Creation date
976        $_title = _("Creation date");
977        if ($_userIsAdmin) {
978            $_data = DateTimeWD::getSelectDateTimeUI(new DateTimeWD($this->getCreationDate()), "node_" . $node_id . "_creation_date", DateTimeWD::INTERFACE_DATETIME_FIELD, "node_creation_date_input");
979        } else {
980            $_data  = htmlspecialchars($this->getCreationDate(), ENT_QUOTES);
981            $_data .= InterfaceElements::generateInputHidden("node_" . $node_id . "_creation_date", $this->getCreationDate());
982        }
983        $_html_node_information[] = InterfaceElements::generateAdminSectionContainer("node_creation_date", $_title, $_data);
984
985        // Description
986        $_title = _("Description");
987        $name = "node_" . $node_id . "_description";
988        $_data = "<textarea name='$name' cols=80 rows=5 id='node_description_textarea'>\n".$this->getDescription()."\n</textarea>\n";
989        $_html_node_information[] = InterfaceElements::generateAdminSectionContainer("node_description", $_title, $_data);
990
991        // Civic number
992        $_title = _("Civic number");
993        $_data = InterfaceElements::generateInputText("node_" . $node_id . "_civic_number", $this->getCivicNumber(), "node_civic_number_input");
994        $_html_node_information[] = InterfaceElements::generateAdminSectionContainer("node_civic_number", $_title, $_data);
995
996        // Street name
997        $_title = _("Street name");
998        $_data = InterfaceElements::generateInputText("node_" . $node_id . "_street_name", $this->getStreetName(), "node_street_name_input");
999        $_html_node_information[] = InterfaceElements::generateAdminSectionContainer("node_street_name", $_title, $_data);
1000
1001        // City
1002        $_title = _("City");
1003        $_data = InterfaceElements::generateInputText("node_" . $node_id . "_city", $this->getCity(), "node_city_input");
1004        $_html_node_information[] = InterfaceElements::generateAdminSectionContainer("node_city", $_title, $_data);
1005
1006        // Province
1007        $_title = _("Province / State");
1008        $_data = InterfaceElements::generateInputText("node_" . $node_id . "_province", $this->getProvince(), "node_province_input");
1009        $_html_node_information[] = InterfaceElements::generateAdminSectionContainer("node_province", $_title, $_data);
1010
1011        // Postal Code
1012        $_title = _("Postal code");
1013        $_data = InterfaceElements::generateInputText("node_" . $node_id . "_postal_code", $this->getPostalCode(), "node_postal_code_input");
1014        $_html_node_information[] = InterfaceElements::generateAdminSectionContainer("node_postal_code", $_title, $_data);
1015
1016        // Country
1017        $_title = _("Country");
1018        $_data = InterfaceElements::generateInputText("node_" . $node_id . "_country", $this->getCountry(), "node_country_input");
1019        $_html_node_information[] = InterfaceElements::generateAdminSectionContainer("node_country", $_title, $_data);
1020
1021        // Public phone #
1022        $_title = _("Public phone number");
1023        $_data = InterfaceElements::generateInputText("node_" . $node_id . "_public_phone", $this->getTelephone(), "node_public_phone_input");
1024        $_html_node_information[] = InterfaceElements::generateAdminSectionContainer("node_public_phone", $_title, $_data);
1025
1026        // Public mail
1027        $_title = _("Public email");
1028        $_data = InterfaceElements::generateInputText("node_" . $node_id . "_public_email", $this->getEmail(), "node_public_email_input");
1029        $_html_node_information[] = InterfaceElements::generateAdminSectionContainer("node_public_email", $_title, $_data);
1030
1031        // Homepage URL
1032        $_title = _("Homepage URL");
1033        $_data = InterfaceElements::generateInputText("node_" . $node_id . "_homepage_url", $this->getWebSiteURL(), "node_homepage_url_input");
1034        $_html_node_information[] = InterfaceElements::generateAdminSectionContainer("node_homepage_url", $_title, $_data);
1035
1036        // Mass transit info
1037        $_title = _("Mass transit info");
1038        $_data = InterfaceElements::generateInputText("node_" . $node_id . "_mass_transit_info", $this->getTransitInfo(), "node_mass_transit_info_input");
1039        $_html_node_information[] = InterfaceElements::generateAdminSectionContainer("node_mass_transit_info", $_title, $_data);
1040
1041        // Build section
1042        $html .= InterfaceElements::generateAdminSectionContainer("node_information", _("Information about the node"), implode(null, $_html_node_information));
1043
1044        /*
1045         * Node GIS data
1046         */
1047        $_html_node_gis_data = array();
1048        $gis_point = $this->getGisLocation();
1049
1050        // Latitude
1051        $_title = _("Latitude");
1052        $_data = InterfaceElements::generateInputText("node_" . $node_id . "_gis_latitude", $gis_point->getLatitude(), "node_" . $node_id . "_gis_latitude");
1053        $_html_node_gis_data[] = InterfaceElements::generateAdminSectionContainer("node_gis_latitude", $_title, $_data);
1054
1055        // Latitude
1056        $_title = _("Longitude");
1057        $_data = InterfaceElements::generateInputText("node_" . $node_id . "_gis_longitude", $gis_point->getLongitude(), "node_" . $node_id . "_gis_longitude");
1058        $_html_node_gis_data[] = InterfaceElements::generateAdminSectionContainer("node_gis_longitude", $_title, $_data);
1059
1060        // Call the geocoding service, if Google Maps is enabled then use Google Maps to let the user choose a more precise location
1061        if (defined('GMAPS_HOTSPOTS_MAP_ENABLED') && GMAPS_HOTSPOTS_MAP_ENABLED === true) {
1062            $_data  = InterfaceElements::generateInputSubmit("geocode_only", _("Geocode the address or postal code above"), "geocode_only_submit");
1063            $_data .= InterfaceElements::generateInputButton("google_maps_geocode", _("Check using Google Maps"), "google_maps_geocode_button", "submit", array("onclick" => "window.open('hotspot_location_map.php?node_id={$this->getId()}', 'hotspot_location', 'toolbar = 0, scrollbars = 1, resizable = 1, location = 0, statusbar = 0, menubar = 0, width = 600, height = 600');"));
1064            $_data .= "<div class='admin_section_hint' id='node_gis_geocode_hint'>". "(" . _("Use a geocoding service, then use Google Maps to pinpoint the exact location.") . ")" ."</div>\n";
1065        } else {
1066            $_data  = InterfaceElements::generateInputSubmit("geocode_only", _("Geocode the address or postal code above"), "geocode_only_submit");
1067            $_data .= "<div class='admin_section_hint' id='node_gis_geocode_hint'>". "(" . _("Use a geocoding service") . ")" ."</div>\n";
1068        }
1069
1070        $_html_node_gis_data[] = InterfaceElements::generateAdminSectionContainer("node_gis_geocode", "", $_data);
1071
1072        // Map URL
1073        $_title = _("Map URL");
1074        $_data = InterfaceElements::generateInputText("node_" . $node_id . "_map_url", $this->getMapURL(), "node_map_url_input");
1075        $_html_node_gis_data[] = InterfaceElements::generateAdminSectionContainer("node_map_url", $_title, $_data);
1076
1077        // Build section
1078        $html .= InterfaceElements::generateAdminSectionContainer("node_gis_data", _("GIS data"), implode(null, $_html_node_gis_data));
1079
1080        /*
1081         * Node configuration section
1082         */
1083        $_html_node_config = array();
1084
1085        // Deployment status
1086        $_title = _("Node deployment status");
1087        $_data = $this->getSelectDeploymentStatus("node_" . $node_id . "_deployment_status");
1088        $_html_node_config[] = InterfaceElements::generateAdminSectionContainer("node_deployment_status", $_title, $_data);
1089
1090        //  is_splash_only_node
1091        if ($network->getSplashOnlyNodesAllowed()) {
1092            $_title = _("Is this node splash-only (no login)?");
1093            $_data = InterfaceElements::generateInputCheckbox("node_" . $node_id . "_is_splash_only_node", "", _("Yes"), $this->isConfiguredSplashOnly(), "node_is_splash_only_node_radio");
1094            $_html_node_config[] = InterfaceElements::generateAdminSectionContainer("node_is_splash_only_node", $_title, $_data);
1095        }
1096
1097        // custom_portal_redirect_url
1098        if ($network->getCustomPortalRedirectAllowed()) {
1099            $_title = _("URL to show instead of the portal");
1100            $_data = InterfaceElements::generateInputText("node_" . $node_id . "_custom_portal_redirect_url", $this->getCustomPortalRedirectUrl(), "node_custom_portal_redirect_url_input");
1101            $_data .= _("If this is not empty, the portal will be disabled and this URL will be shown instead");
1102            $_html_node_config[] = InterfaceElements::generateAdminSectionContainer("node_custom_portal_redirect_url", $_title, $_data);
1103        }
1104
1105        // Build section
1106        $html .= InterfaceElements::generateAdminSectionContainer("node_config", _("Node configuration"), implode(null, $_html_node_config));
1107
1108        /*
1109         * Access rights
1110         */
1111        if ($_userIsAdmin) {
1112            require_once('classes/Stakeholder.php');
1113            $html_access_rights = Stakeholder::getAssignStakeholdersUI($this);
1114            $html .= InterfaceElements::generateAdminSectionContainer("access_rights", _("Access rights"), $html_access_rights);
1115        }
1116
1117        $html .= "</ul>\n";
1118        $html .= "</fieldset>";
1119
1120        return $html;
1121    }
1122
1123    /**
1124     * Process admin interface of this object.
1125     *
1126     * @return void
1127     *
1128     * @access public
1129     */
1130    public function processAdminUI()
1131    {
1132        require_once('classes/Stakeholder.php');
1133        $user = User::getCurrentUser();
1134        //pretty_print_r($_REQUEST);
1135        $permArray[]=array(Permission::P('NETWORK_PERM_EDIT_ANY_NODE_CONFIG'), $this->getNetwork());
1136        $permArray[]=array(Permission::P('NODE_PERM_EDIT_CONFIG'), $this);
1137        $permArray[]=array(Permission::P('NODE_PERM_EDIT_GATEWAY_ID'), $this);
1138        Security::requireAnyPermission($permArray);
1139        // Check if user is a admin
1140        $_userIsAdmin = User::getCurrentUser()->DEPRECATEDisSuperAdmin();
1141
1142        // Information about the node
1143
1144        $node_id = $this->getId();
1145
1146        // Gateway Id
1147        if(Security::hasPermission(Permission::P('NODE_PERM_EDIT_GATEWAY_ID'), $this)) {
1148            $name = "node_" . $node_id . "_gw_id";
1149            $this->setGatewayId($_REQUEST[$name]);
1150        }
1151        // Content processing
1152        $name = "node_{$node_id}_content";
1153        Content::processLinkedContentUI($name, 'node_has_content', 'node_id', $this->id);
1154
1155        // Name
1156        if ($_userIsAdmin) {
1157            $name = "node_".$node_id."_name";
1158            $this->setName($_REQUEST[$name]);
1159        } else {
1160            $this->setName($this->getName());
1161        }
1162
1163        // Creation date
1164        if ($_userIsAdmin) {
1165            $name = "node_".$node_id."_creation_date";
1166            $this->setCreationDate(DateTimeWD::processSelectDateTimeUI($name, DateTimeWD :: INTERFACE_DATETIME_FIELD)->getIso8601FormattedString());
1167        } else {
1168            $this->setCreationDate($this->getCreationDate());
1169        }
1170
1171        // Homepage URL
1172        $name = "node_".$node_id."_homepage_url";
1173        $this->setWebSiteUrl($_REQUEST[$name]);
1174
1175        // Description
1176        $name = "node_".$node_id."_description";
1177        $this->setDescription($_REQUEST[$name]);
1178
1179        // Map URL
1180        $name = "node_".$node_id."_map_url";
1181        $this->setMapUrl($_REQUEST[$name]);
1182
1183        // Civic number
1184        $name = "node_".$node_id."_civic_number";
1185        $this->setCivicNumber($_REQUEST[$name]);
1186
1187        // Street name
1188        $name = "node_".$node_id."_street_name";
1189        $this->setStreetName($_REQUEST[$name]);
1190
1191        // City
1192        $name = "node_".$node_id."_city";
1193        $this->setCity($_REQUEST[$name]);
1194
1195        // Province
1196        $name = "node_".$node_id."_province";
1197        $this->setProvince($_REQUEST[$name]);
1198
1199        // Postal Code
1200        $name = "node_".$node_id."_postal_code";
1201        $this->setPostalCode($_REQUEST[$name]);
1202
1203        // Country
1204        $name = "node_".$node_id."_country";
1205        $this->setCountry($_REQUEST[$name]);
1206
1207        // Public phone #
1208        $name = "node_".$node_id."_public_phone";
1209        $this->setTelephone($_REQUEST[$name]);
1210
1211        // Public mail
1212        $name = "node_".$node_id."_public_email";
1213        $this->setEmail($_REQUEST[$name]);
1214
1215        // Mass transit info
1216        $name = "node_".$node_id."_mass_transit_info";
1217        $this->setTransitInfo($_REQUEST[$name]);
1218
1219        // GIS data
1220        // Get a geocoder for a given country
1221        if (!empty ($_REQUEST['geocode_only']))
1222        {
1223            $geocoder = AbstractGeocoder :: getGeocoder($this->getCountry());
1224            if ($geocoder != null)
1225            {
1226                $geocoder->setCivicNumber($this->getCivicNumber());
1227                $geocoder->setStreetName($this->getStreetName());
1228                $geocoder->setCity($this->getCity());
1229                $geocoder->setProvince($this->getProvince());
1230                $geocoder->setPostalCode($this->getPostalCode());
1231                if ($geocoder->validateAddress() === true)
1232                {
1233                    if (($point = $geocoder->getGisLocation()) !== null)
1234                    $this->setGisLocation($point);
1235                    else
1236                    $this->_warningMessage = _("It appears that the Geocoder could not be reached or could not geocode the given address.");
1237                }
1238                else
1239                $this->_warningMessage = _("You must enter a valid address.");
1240            }
1241            else
1242            {
1243                $this->_warningMessage = _("Unable to create geocoder.  Are you sure you set the country?");
1244            }
1245        }
1246        else
1247        {
1248            // Use what has been set by the user.
1249            $gis_lat_name = "node_".$node_id."_gis_latitude";
1250            $gis_long_name = "node_".$node_id."_gis_longitude";
1251            $this->setGisLocation(new GisPoint($_REQUEST[$gis_lat_name], $_REQUEST[$gis_long_name], .0));
1252        }
1253
1254        // Statistics
1255        $name = "node_{$this->id}_get_stats";
1256        if (!empty ($_REQUEST[$name]))
1257        header("Location: stats.php?node_id=".urlencode($this->getId()));
1258
1259        // Node configuration section
1260
1261        $network = $this->getNetwork();
1262
1263        // Deployment status
1264        $name = "node_".$node_id."_deployment_status";
1265        $this->setDeploymentStatus(self :: processSelectDeploymentStatus($name));
1266
1267        //  is_splash_only_node
1268        if ($network->getSplashOnlyNodesAllowed())
1269        {
1270            $name = "node_".$node_id."_is_splash_only_node";
1271            $this->setIsConfiguredSplashOnly(empty ($_REQUEST[$name]) ? false : true);
1272        }
1273
1274        // custom_portal_redirect_url
1275        if ($network->getCustomPortalRedirectAllowed())
1276        {
1277            $name = "node_".$node_id."_custom_portal_redirect_url";
1278            $this->setCustomPortalRedirectUrl($_REQUEST[$name]);
1279        }
1280
1281        // End Node configuration section
1282
1283        // Access rights
1284        Stakeholder::processAssignStakeholdersUI($this, $errMsg);
1285        if(!empty($errMsg)) {
1286            echo $errMsg;
1287        }
1288    }
1289
1290    // Redirect to this node's portal page
1291    public function getUserUI()
1292    {
1293        header("Location: ".BASE_SSL_PATH."portal/?node_id=".$this->getId());
1294    }
1295
1296    /** Add content to this node */
1297    public function addContent(Content $content)
1298    {
1299        $db = AbstractDb::getObject();
1300        $content_id = $db->escapeString($content->getId());
1301        $sql = "INSERT INTO node_has_content (node_id, content_id) VALUES ('$this->id','$content_id')";
1302        $db->execSqlUpdate($sql, false);
1303        exit;
1304    }
1305
1306    /** Remove content from this node */
1307    public function removeContent(Content $content)
1308    {
1309        $db = AbstractDb::getObject();
1310        $content_id = $db->escapeString($content->getId());
1311        $sql = "DELETE FROM node_has_content WHERE node_id='$this->id' AND content_id='$content_id'";
1312        $db->execSqlUpdate($sql, false);
1313    }
1314
1315    /**
1316     * The list of the 5 most recent users who have logged into this node in the past week
1317     *
1318     * @return array An array of User object, or an empty array
1319     *
1320     * @access public
1321     */
1322    public function getRecentUsers()
1323    {
1324         
1325        $db = AbstractDb::getObject();
1326
1327        // Init values
1328        $retval = array();
1329        $users = null;
1330        $anonUsers = 0;
1331        $weekAgoDate = strftime("%Y-%m-%d 00:00", strtotime("-1 week"));
1332
1333        $db->execSql("SELECT DISTINCT users.user_id FROM users,connections WHERE connections.timestamp_in>'{$weekAgoDate}' AND users.user_id=connections.user_id AND connections.node_id='{$this->id}' LIMIT 5", $users, false);
1334
1335        if ($users != null) {
1336            foreach ($users as $user_row) {
1337                $retval[] = User::getObject($user_row['user_id']);
1338            }
1339        }
1340
1341        return $retval;
1342    }
1343
1344    /**
1345     * The list of the 5 users who have logged into this node most often
1346     *
1347     * @return array An array of User object, or an empty array
1348     *
1349     * @access public
1350     */
1351    public function getActiveUsers()
1352    {
1353         
1354        $db = AbstractDb::getObject();
1355
1356        // Init values
1357        $retval = array();
1358        $users = null;
1359        $anonUsers = 0;
1360
1361        $db->execSql("SELECT DISTINCT users.user_id, count(users.user_id) as connections FROM users, connections WHERE users.user_id=connections.user_id AND connections.node_id='{$this->id}' GROUP BY users.user_id ORDER BY connections desc LIMIT 5", $users, false);
1362
1363        if ($users != null) {
1364            foreach ($users as $user_row) {
1365                $retval[] = User::getObject($user_row['user_id']);
1366            }
1367        }
1368
1369        return $retval;
1370    }
1371
1372    /**
1373     * The list of users online at this node
1374     *
1375     * @return array An array of User object, or an empty array
1376     *
1377     * @access public
1378     */
1379    public function getOnlineUsers()
1380    {
1381         
1382        $db = AbstractDb::getObject();
1383
1384        // Init values
1385        $retval = array();
1386        $users = null;
1387        $anonUsers = 0;
1388
1389        $db->execSql("SELECT users.user_id FROM users,connections WHERE connections.token_status='".TOKEN_INUSE."' AND users.user_id=connections.user_id AND connections.node_id='{$this->id}'", $users, false);
1390
1391        if ($users != null) {
1392            foreach ($users as $user_row) {
1393                $retval[] = User::getObject($user_row['user_id']);
1394            }
1395        }
1396
1397        return $retval;
1398    }
1399
1400    /**
1401     * Find out how many users are online this specific Node
1402     *
1403     * @return int Number of online users
1404     *
1405     * @access public
1406     */
1407    public function getNumOnlineUsers()
1408    {
1409         
1410        $db = AbstractDb::getObject();
1411
1412        // Init values
1413        $retval = array ();
1414        $row = null;
1415
1416        if (!$this->isConfiguredSplashOnly()) {
1417            $db->execSqlUniqueRes("SELECT COUNT(DISTINCT users.user_id) as count FROM users,connections WHERE connections.token_status='".TOKEN_INUSE."' AND users.user_id=connections.user_id AND connections.node_id='{$this->id}'", $row, false);
1418        } else {
1419            $db->execSqlUniqueRes("SELECT COUNT(DISTINCT connections.user_mac) as count FROM connections WHERE connections.token_status='".TOKEN_INUSE."' AND connections.node_id='{$this->id}'", $row, false);
1420        }
1421
1422        return $row['count'];
1423    }
1424
1425    /** The list of all Technical officers of this node.
1426     * Technical officers are displayed highlited and in the online user's list,
1427     * and are contacted when the Node goes down.
1428     * @return An array of User object, or en empty array */
1429    function DEPRECATEDgetTechnicalOfficers()
1430    {
1431        $db = AbstractDb::getObject();
1432        $retval = array ();
1433        $officers = null;
1434        $db->execSql("SELECT user_id FROM node_stakeholders WHERE role_id = 'IS_TECH_OFFICER' AND object_id='{$this->id}'", $officers, false);
1435        if ($officers != null)
1436        {
1437            foreach ($officers as $officer_row)
1438            {
1439                $retval[] = User :: getObject($officer_row['user_id']);
1440            }
1441        }
1442        return $retval;
1443    }
1444
1445    /** Reloads the object from the database.  Should normally be called after a set operation */
1446    protected function refresh()
1447    {
1448        $this->__construct($this->id);
1449    }
1450    /** Menu hook function */
1451    static public function hookMenu() {
1452        $items = array();
1453        if(Security::getObjectsWithPermission(Permission::P('NETWORK_PERM_EDIT_ANY_NODE_CONFIG')))
1454        {
1455            $items[] = array('path' => 'node/node_edit',
1456            'title' => _("Edit nodes"),
1457            'url' => BASE_URL_PATH."admin/generic_object_admin.php?object_class=Node&action=list"
1458                );
1459        }
1460        else if($nodes = Security::getObjectsWithPermission(Permission::P('NODE_PERM_EDIT_CONFIG'))) {
1461             
1462            foreach ($nodes as $nodeId => $node) {
1463                $items[] = array('path' => 'node/node_'.$nodeId.'edit',
1464                'title' => sprintf(_("Edit %s"), $node->getName()),
1465                'url' => BASE_URL_PATH."admin/generic_object_admin.php?object_class=Node&action=edit&object_id=$nodeId"
1466                );
1467            }
1468        }
1469        $items[] = array('path' => 'node',
1470        'title' => _('Node administration'),
1471        'type' => MENU_ITEM_GROUPING);
1472        return $items;
1473    }
1474    /**
1475     * Assigns values about node to be processed by the Smarty engine.
1476     *
1477     * @param object $smarty Smarty object
1478     * @param object $node    Node object, if unset, the current node will be used
1479     *
1480     * @return void
1481     */
1482    public static function assignSmartyValues($smarty, $node = null)
1483    {
1484        if (!$node) {
1485            $node = self::getCurrentNode();
1486        }
1487
1488        // Set node details
1489        $smarty->assign('nodeId', $node ? $node->getId() : '');
1490        $smarty->assign('nodeName', $node ? $node->getName() : '');
1491        $smarty->assign('nodeLastHeartbeatIP', $node ? $node->getLastHeartbeatIP() : '');
1492        $smarty->assign('nodeNumOnlineUsers', $node ? $node->getNumOnlineUsers() : '');
1493        $smarty->assign('nodeWebSiteURL', $node ? $node->getWebSiteURL() : '');
1494        $node = self::getCurrentRealNode();
1495        // Set node details
1496        $smarty->assign('realNodeId', $node ? $node->getId() : '');
1497        $smarty->assign('realNodeName', $node ? $node->getName() : '');
1498        $smarty->assign('realNodeLastHeartbeatIP', $node ? $node->getLastHeartbeatIP() : '');
1499    }
1500}
1501
1502/*
1503 * Local variables:
1504 * tab-width: 4
1505 * c-basic-offset: 4
1506 * c-hanging-comment-ender-p: nil
1507 * End:
1508 */
Note: See TracBrowser for help on using the browser.