MDL-16094 File storage conversion Quiz and Questions
[moodle.git] / mnet / peer.php
1 <?php
2 /**
3  * An object to represent lots of information about an RPC-peer machine
4  *
5  * @author  Donal McMullan  donal@catalyst.net.nz
6  * @version 0.0.1
7  * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
8  * @package mnet
9  */
11 class mnet_peer {
13     var $id                 = 0;
14     var $wwwroot            = '';
15     var $ip_address         = '';
16     var $name               = '';
17     var $public_key         = '';
18     var $public_key_expires = 0;
19     var $last_connect_time  = 0;
20     var $last_log_id        = 0;
21     var $force_theme        = 0;
22     var $theme              = '';
23     var $applicationid      = 1; // Default of 1 == Moodle
24     var $keypair            = array();
25     var $error              = array();
26     var $bootstrapped       = false; // set when the object is populated
28     function mnet_peer() {
29         return true;
30     }
32     /*
33      * Fetch information about a peer identified by wwwroot
34      * If information does not preexist in db, collect it together based on
35      * supplied information
36      *
37      * @param string $wwwroot - address of peer whose details we want
38      * @param string $pubkey - to use if we add a record to db for new peer
39      * @param int $application - table id - what kind of peer are we talking to
40      * @return bool - indication of success or failure
41      */
42     function bootstrap($wwwroot, $pubkey = null, $application) {
43         global $DB;
45         if (substr($wwwroot, -1, 1) == '/') {
46             $wwwroot = substr($wwwroot, 0, -1);
47         }
49         // If a peer record already exists for this address,
50         // load that info and return
51         if ($this->set_wwwroot($wwwroot)) {
52             return true;
53         }
55         $hostname = mnet_get_hostname_from_uri($wwwroot);
56         // Get the IP address for that host - if this fails, it will return the hostname string
57         $ip_address = gethostbyname($hostname);
59         // Couldn't find the IP address?
60         if ($ip_address === $hostname && !preg_match('/^\d+\.\d+\.\d+.\d+$/',$hostname)) {
61             throw new moodle_exception('noaddressforhost', 'mnet', '', $hostname);
62         }
64         $this->name = $wwwroot;
66         // TODO: In reality, this will be prohibitively slow... need another
67         // default - maybe blank string
68         $homepage = download_file_content($wwwroot);
69         if (!empty($homepage)) {
70             $count = preg_match("@<title>(.*)</title>@siU", $homepage, $matches);
71             if ($count > 0) {
72                 $this->name = $matches[1];
73             }
74         }
76         $this->wwwroot              = $wwwroot;
77         $this->ip_address           = $ip_address;
78         $this->deleted              = 0;
80         $this->application = $DB->get_record('mnet_application', array('name'=>$application));
81         if (empty($this->application)) {
82             $this->application = $DB->get_record('mnet_application', array('name'=>'moodle'));
83         }
85         $this->applicationid = $this->application->id;
87         if(empty($pubkey)) {
88             $this->public_key           = clean_param(mnet_get_public_key($this->wwwroot, $this->application), PARAM_PEM);
89         } else {
90             $this->public_key           = clean_param($pubkey, PARAM_PEM);
91         }
92         $this->public_key_expires   = $this->check_common_name($this->public_key);
93         $this->last_connect_time    = 0;
94         $this->last_log_id          = 0;
95         if ($this->public_key_expires == false) {
96             $this->public_key == '';
97             return false;
98         }
99         $this->bootstrapped = true;
100     }
102     /*
103      * Delete mnet peer
104      * the peer is marked as deleted in the database
105      * we delete current sessions.
106      * @return bool - success
107      */
108     function delete() {
109         global $DB;
111         if ($this->deleted) {
112             return true;
113         }
115         $this->delete_all_sessions();
117         $this->deleted = 1;
118         return $this->commit();
119     }
121     function count_live_sessions() {
122         global $DB;
123         $obj = $this->delete_expired_sessions();
124         return $DB->count_records('mnet_session', array('mnethostid'=>$this->id));
125     }
127     function delete_expired_sessions() {
128         global $DB;
129         $now = time();
130         return $DB->delete_records_select('mnet_session', " mnethostid = ? AND expires < ? ", array($this->id, $now));
131     }
133     function delete_all_sessions() {
134         global $CFG, $DB;
135         // TODO: Expires each PHP session individually
136         $sessions = $DB->get_records('mnet_session', array('mnethostid'=>$this->id));
138         if (count($sessions) > 0 && file_exists($CFG->dirroot.'/auth/mnet/auth.php')) {
139             require_once($CFG->dirroot.'/auth/mnet/auth.php');
140             $auth = new auth_plugin_mnet();
141             $auth->end_local_sessions($sessions);
142         }
144         $deletereturn = $DB->delete_records('mnet_session', array('mnethostid'=>$this->id));
145         return true;
146     }
148     function check_common_name($key) {
149         $credentials = $this->check_credentials($key);
150         return $credentials['validTo_time_t'];
151     }
153     function check_credentials($key) {
154         $credentials = openssl_x509_parse($key);
155         if ($credentials == false) {
156             $this->error[] = array('code' => 3, 'text' => get_string("nonmatchingcert", 'mnet', array('','')));
157             return false;
158         } elseif (array_key_exists('subjectAltName', $credentials['subject']) && $credentials['subject']['subjectAltName'] != $this->wwwroot) {
159             $a['subject'] = $credentials['subject']['subjectAltName'];
160             $a['host'] = $this->wwwroot;
161             $this->error[] = array('code' => 5, 'text' => get_string("nonmatchingcert", 'mnet', $a));
162             return false;
163         } elseif ($credentials['subject']['CN'] != $this->wwwroot) {
164             $a['subject'] = $credentials['subject']['CN'];
165             $a['host'] = $this->wwwroot;
166             $this->error[] = array('code' => 4, 'text' => get_string("nonmatchingcert", 'mnet', $a));
167             return false;
168         } else {
169             if (array_key_exists('subjectAltName', $credentials['subject'])) {
170                 $credentials['wwwroot'] = $credentials['subject']['subjectAltName'];
171             } else {
172                 $credentials['wwwroot'] = $credentials['subject']['CN'];
173             }
174             return $credentials;
175         }
176     }
178     function commit() {
179         global $DB;
180         $obj = new stdClass();
182         $obj->wwwroot               = $this->wwwroot;
183         $obj->ip_address            = $this->ip_address;
184         $obj->name                  = $this->name;
185         $obj->public_key            = $this->public_key;
186         $obj->public_key_expires    = $this->public_key_expires;
187         $obj->deleted               = $this->deleted;
188         $obj->last_connect_time     = $this->last_connect_time;
189         $obj->last_log_id           = $this->last_log_id;
190         $obj->force_theme           = $this->force_theme;
191         $obj->theme                 = $this->theme;
192         $obj->applicationid         = $this->applicationid;
194         if (isset($this->id) && $this->id > 0) {
195             $obj->id = $this->id;
196             return $DB->update_record('mnet_host', $obj);
197         } else {
198             $this->id = $DB->insert_record('mnet_host', $obj);
199             return $this->id > 0;
200         }
201     }
203     function touch() {
204         $this->last_connect_time = time();
205         $this->commit();
206     }
208     function set_name($newname) {
209         if (is_string($newname) && strlen($newname <= 80)) {
210             $this->name = $newname;
211             return true;
212         }
213         return false;
214     }
216     function set_applicationid($applicationid) {
217         if (is_numeric($applicationid) && $applicationid == intval($applicationid)) {
218             $this->applicationid = $applicationid;
219             return true;
220         }
221         return false;
222     }
224     /**
225      * Load information from db about an mnet peer into this object's properties
226      *
227      * @param string $wwwroot - address of peer whose details we want to load
228      * @return bool - indication of success or failure
229      */
230     function set_wwwroot($wwwroot) {
231         global $CFG, $DB;
233         $hostinfo = $DB->get_record('mnet_host', array('wwwroot'=>$wwwroot));
235         if ($hostinfo != false) {
236             $this->populate($hostinfo);
237             return true;
238         }
239         return false;
240     }
242     function set_id($id) {
243         global $CFG, $DB;
245         if (clean_param($id, PARAM_INT) != $id) {
246             $this->errno[]  = 1;
247             $this->errmsg[] = 'Your id ('.$id.') is not legal';
248             return false;
249         }
251         $sql = "
252                 SELECT
253                     h.*
254                 FROM
255                     {mnet_host} h
256                 WHERE
257                     h.id = ?";
259         if ($hostinfo = $DB->get_record_sql($sql, array($id))) {
260             $this->populate($hostinfo);
261             return true;
262         }
263         return false;
264     }
266     /**
267      * Several methods can be used to get an 'mnet_host' record. They all then
268      * send it to this private method to populate this object's attributes.
269      *
270      * @param   object  $hostinfo   A database record from the mnet_host table
271      * @return  void
272      */
273     function populate($hostinfo) {
274         global $DB;
275         $this->id                   = $hostinfo->id;
276         $this->wwwroot              = $hostinfo->wwwroot;
277         $this->ip_address           = $hostinfo->ip_address;
278         $this->name                 = $hostinfo->name;
279         $this->deleted              = $hostinfo->deleted;
280         $this->public_key           = $hostinfo->public_key;
281         $this->public_key_expires   = $hostinfo->public_key_expires;
282         $this->last_connect_time    = $hostinfo->last_connect_time;
283         $this->last_log_id          = $hostinfo->last_log_id;
284         $this->force_theme          = $hostinfo->force_theme;
285         $this->theme                = $hostinfo->theme;
286         $this->applicationid        = $hostinfo->applicationid;
287         $this->application = $DB->get_record('mnet_application', array('id'=>$this->applicationid));
288         $this->bootstrapped = true;
289     }
291     function get_public_key() {
292         if (isset($this->public_key_ref)) return $this->public_key_ref;
293         $this->public_key_ref = openssl_pkey_get_public($this->public_key);
294         return $this->public_key_ref;
295     }