e1e8387516a49672e0d71430982b977334655463
[moodle.git] / lib / boxlib.php
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
17 /**
18  * Box REST Client Library for PHP5 Developers
19  *
20  *
21  * @package moodlecore
22  * @author James Levy <james@box.net>
23  * @link http://enabled.box.net
24  * @access public
25  * @version 1.0
26  * @copyright copyright Box.net 2007
27  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
28  */
30 /**
31  * @package moodlecore
32  * @copyright copyright Box.net 2007
33  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
34  */
35 class boxclient {
36     /** @var string */
37     public $auth_token = '';
38     /** @var string */
39     private $_box_api_url = 'http://box.net/api/1.0/rest';
40     private $_box_api_upload_url = 'http://upload.box.net/api/1.0/upload';
41     private $_error_code = '';
42     private $_error_msg = '';
43     /** @var bool */
44     private $debug = false;
46     /**
47      * @param string $api_key
48      * @param string $auth_token
49      * @param bool $debug
50      */
51     public function __construct($api_key, $auth_token = '', $debug = false) {
52         $this->api_key    = $api_key;
53         $this->auth_token = $auth_token;
54         if (!empty($debug)) {
55             $this->debug = true;
56         } else {
57             $this->debug = false;
58         }
59     }
60     /**
61      * Setup for Functions
62      *
63      * @param string $method
64      * @param array $params
65      * @return array
66      */
67     function makeRequest($method, $params = array()) {
68         $this->_clearErrors();
69         $c = new curl(array('debug'=>$this->debug, 'cache'=>true, 'module_cache'=>'repository'));
70         try {
71             if ($method == 'upload'){
72                 $request = $this->_box_api_upload_url.'/'.
73                     $this->auth_token.'/'.$params['folder_id'];
74                 $xml = $c->post($request, $params);
75             }else{
76                 $args = array();
77                 $xml = $c->get($this->_box_api_url, $params);
78             }
79             $xml_parser = xml_parser_create();
80             // set $data here
81             xml_parse_into_struct($xml_parser, $xml, $data);
82             xml_parser_free($xml_parser);
83         } catch (moodle_exception $e) {
84             $this->setError(0, 'connection time-out or invalid url');
85             return false;
86         }
87         return $data;
88     }
89     /**
90      * @param array $params
91      * @return array
92      */
93     function getTicket($params = array()) {
94         $params['api_key'] = $this->api_key;
95         $params['action']  = 'get_ticket';
96         $ret_array = array();
97         $data = $this->makeRequest('action=get_ticket', $params);
98         if ($this->_checkForError($data)) {
99             return false;
100         }
101         foreach ($data as $a) {
102             switch ($a['tag']) {
103             case 'STATUS':
104                 $ret_array['status'] = $a['value'];
105                 break;
106             case 'TICKET':
107                 $ret_array['ticket'] = $a['value'];
108                 break;
109             }
110         }
111         return $ret_array;
112     }
114     /**
115      * $options['username'] and $options['password'] must be
116      * given, we  will use them to obtain a valid auth_token
117      * To get a token, you should use following code:
118      *
119      * <code>
120      * $box = new boxclient('dmls97d8j3i9tn7av8y71m9eb55vrtj4');
121      * Get a ticket
122      * $t = $box->getTicket();
123      * $box->getAuthToken($t['ticket'], array(
124      *              'username'=>'dongsheng@moodle.com',
125      *              'password'=>'xxx'));
126      * </code>
127      *
128      * @param string $ticket
129      * @param string $username
130      * @param string $password
131      * @return mixed
132      */
133     function getAuthToken($ticket, $username, $password) {
134         $c = new curl(array('debug'=>$this->debug));
135         $c->setopt(array('CURLOPT_FOLLOWLOCATION'=>0));
136         $param =  array(
137             'login_form1'=>'',
138             'login'=>$username,
139             'password'=>$password,
140             'dologin'=>1,
141             '__login'=>1
142             );
143         try {
144             $ret = $c->post('http://www.box.net/api/1.0/auth/'.$ticket, $param);
145         } catch (moodle_exception $e) {
146             $this->setError(0, 'connection time-out or invalid url');
147             return false;
148         }
149         $header = $c->getResponse();
150         if(empty($header['location'])) {
151             throw new repository_exception('invalidpassword', 'repository_boxnet');
152         }
153         $location = $header['location'];
154         preg_match('#auth_token=(.*)$#i', $location, $matches);
155         $auth_token = $matches[1];
156         if(!empty($auth_token)) {
157             $this->auth_token = $auth_token;
158             return $auth_token;
159         } else {
160             throw new repository_exception('invalidtoken', 'repository_boxnet');
161         }
162     }
163     /**
164      * @param string $path Unused
165      * @param array $params
166      * @return array
167      */
168     function getfiletree($path, $params = array()) {
169         $this->_clearErrors();
170         $params['auth_token'] = $this->auth_token;
171         $params['folder_id']  = 0;
172         $params['api_key']    = $this->api_key;
173         $params['action']     = 'get_account_tree';
174         $params['onelevel']   = 1;
175         $params['params[]']   = 'nozip';
176         $c = new curl(array('debug'=>$this->debug, 'cache'=>true, 'module_cache'=>'repository'));
177         try {
178             $args = array();
179             $xml = $c->get($this->_box_api_url, $params);
180         } catch (Exception $e){
181         }
182         $ret = array();
183         $o = simplexml_load_string(trim($xml));
184         if($o->status == 'listing_ok') {
185             $tree = $o->tree->folder;
186             $this->buildtree($tree, $ret);
187         }
188         return $ret;
189     }
191     /**
192      * Get box.net file info
193      *
194      * @param string $fileid
195      * @return string|null
196      */
197     function get_file_info($fileid) {
198         $this->_clearErrors();
199         $params = array();
200         $params['action']     = 'get_file_info';
201         $params['file_id']    = $fileid;
202         $params['auth_token'] = $this->auth_token;
203         $params['api_key']    = $this->api_key;
204         $http = new curl(array('debug'=>$this->debug, 'cache'=>true, 'module_cache'=>'repository'));
205         $xml = $http->get($this->_box_api_url, $params);
206         $o = simplexml_load_string(trim($xml));
207         if ($o->status == 's_get_file_info') {
208             return $o->info;
209         } else {
210             return null;
211         }
212     }
214     /**
215      * @param array $sax
216      * @param array $tree Passed by reference
217      */
218     function buildtree($sax, &$tree){
219         $sax = (array)$sax;
220         $count = 0;
221         foreach($sax as $k=>$v){
222             if($k == 'folders'){
223                 $o = $sax[$k];
224                 foreach($o->folder as $z){
225                     $tmp = array('title'=>(string)$z->attributes()->name,
226                         'size'=>0, 'date'=>userdate(time()),
227                         'thumbnail'=>'http://www.box.net/img/small_folder_icon.gif',
228                         'path'=>array('name'=>(string)$z->attributes()->name, 'path'=>(int)$z->attributes()->id));
229                     $tmp['children'] = array();
230                     $this->buildtree($z, $tmp['children']);
231                     $tree[] = $tmp;
232                 }
233             } elseif ($k == 'files') {
234                 $val = $sax[$k]->file;
235                 foreach($val as $file){
236                     $thumbnail = (string)$file->attributes()->thumbnail;
237                     if (!preg_match('#^(?:http://)?([^/]+)#i', $thumbnail)) {
238                         $thumbnail =  'http://www.box.net'.$thumbnail;
239                     }
240                     $tmp = array('title'=>(string)$file->attributes()->file_name,
241                         'size'=>display_size((int)$file->attributes()->size),
242                         'thumbnail'=>$thumbnail,
243                         'date'=>userdate((int)$file->attributes()->updated),
244                         'source'=>'http://box.net/api/1.0/download/'
245                             .$this->auth_token.'/'.(string)$file->attributes()->id,
246                         'url'=>(string)$file->attributes()->shared_link);
247                     $tree[] = $tmp;
248                 }
249             }
250             $count++;
251         }
252     }
253     /**
254      * @param array $params
255      * @return bool|array Array or false
256      */
257     function getAccountTree($params = array()) {
258         $params['auth_token'] = $this->auth_token;
259         $params['folder_id']  = 0;
260         $params['api_key']    = $this->api_key;
261         $params['action']     = 'get_account_tree';
262         $params['onelevel']   = 1;
263         $params['params[]']   = 'nozip';
264         $ret_array = array();
265         $data = $this->makeRequest('action=get_account_tree', $params);
266         if ($this->_checkForError($data)) {
267             return false;
268         }
269         $tree_count=count($data);
270         $entry_count = 0;
271         for ($i=0; $i<$tree_count; $i++) {
272             $a = $data[$i];
273             switch ($a['tag'])
274             {
275             case 'FOLDER':
276                 if (@is_array($a['attributes'])) {
277                     $ret_array['folder_id'][$i] = $a['attributes']['ID'];
278                     $ret_array['folder_name'][$i] = $a['attributes']['NAME'];
279                     $ret_array['shared'][$i] = $a['attributes']['SHARED'];
280                 }
281                 break;
283             case 'FILE':
284                 if (@is_array($a['attributes'])) {
285                     $ret_array['file_id'][$i] = $a['attributes']['ID'];
286                     @$ret_array['file_name'][$i] = $a['attributes']['FILE_NAME'];
287                     @$ret_array['file_keyword'][$i] = $a['attributes']['KEYWORD'];
288                     @$ret_array['file_size'][$i] = display_size($a['attributes']['SIZE']);
289                     @$ret_array['file_date'][$i] = userdate($a['attributes']['UPDATED']);
290                     if (preg_match('#^(?:http://)?([^/]+)#i', $a['attributes']['THUMBNAIL'])) {
291                         @$ret_array['thumbnail'][$i] =  $a['attributes']['THUMBNAIL'];
292                     } else {
293                         @$ret_array['thumbnail'][$i] =  'http://www.box.net'.$a['attributes']['THUMBNAIL'];
294                     }
295                     $entry_count++;
296                 }
297                 break;
298             }
299         }
300         return $ret_array;
301     }
303     /**
304      * @param string $new_folder_name
305      * @param array $params
306      * @return bool|array Array or false
307      */
308     function CreateFolder($new_folder_name, $params = array()) {
309         $params['auth_token'] =  $this->auth_token;
310         $params['api_key']    = $this->api_key;
311         $params['action']     = 'create_folder';
312         $params['name']       = $new_folder_name;
313         $defaults = array(
314             'parent_id'  => 0, //Set to '0' by default. Change to create within sub-folder.
315             'share'     => 1, //Set to '1' by default. Set to '0' to make folder private.
316         );
317         foreach ($defaults as $key => $value) {
318             if (!array_key_exists($key, $params)) {
319                 $params[$key] = $value;
320             }
321         }
323         $ret_array = array();
324         $data = $this->makeRequest('action=create_folder', $params);
325         if ($this->_checkForError($data)) {
326             return false;
327         }
328         foreach ($data as $a) {
329             if (!empty($a['value'])) {
330                 switch ($a['tag']) {
332                 case 'FOLDER_ID':
333                     $ret_array['folder_id'] = $a['value'];
334                     break;
336                 case 'FOLDER_NAME':
337                     $ret_array['folder_name'] = $a['value'];
338                     break;
340                 case 'FOLDER_TYPE_ID':
341                     $ret_array['folder_type_id'] = $a['value'];
342                     break;
344                 case 'SHARED':
345                     $ret_array['shared'] = $a['value'];
346                     break;
348                 case 'PASSWORD':
349                     $ret_array['password'] = $a['value'];
350                     break;
351                 }
352             } else {
353                 $ret_array[strtolower($a['tag'])] = null;
354             }
355         }
356         return $ret_array;
357     }
359     /**
360      * Upload a File
361      * @param array $params the file MUST be present in key 'file' and be a moodle stored_file object.
362      * @return array|bool Array or false
363      */
364     function UploadFile ($params = array()) {
365         $params['auth_token'] = $this->auth_token;
366         // this param should be the full path of the file
367         $params['new_file1']  = $params['file'];
368         unset($params['file']);
369         $defaults = array(
370             'folder_id' => 0, //Set to '0' by default. Change to create within sub-folder.
371             'share'     => 1, //Set to '1' by default. Set to '0' to make folder private.
372         );
373         foreach ($defaults as $key => $value) {
374             if (!array_key_exists($key, $params)) {
375                 $params[$key] = $value;
376             }
377         }
378         $ret_array = array();
379         $entry_count = 0;
380         $data = $this->makeRequest('upload', $params);
381         if ($this->_checkForError($data)) {
382             return false;
383         }
384         for ($i=0, $tree_count=count($data); $i<$tree_count; $i++) {
385             $a = $data[$i];
386             switch ($a['tag']) {
387             case 'STATUS':
388                 $ret_array['status'] = $a['value'];
389                 break;
391             case 'FILE':
392                 if (is_array($a['attributes'])) {
393                     @$ret_array['file_name'][$i] = $a['attributes']['FILE_NAME'];
394                     @$ret_array['id'][$i] = $a['attributes']['ID'];
395                     @$ret_array['folder_name'][$i] = $a['attributes']['FOLDER_NAME'];
396                     @$ret_array['error'][$i] = $a['attributes']['ERROR'];
397                     @$ret_array['public_name'][$i] = $a['attributes']['PUBLIC_NAME'];
398                     $entry_count++;
399                 }
400                 break;
401             }
402         }
404         return $ret_array;
405     }
406     /**
407      * @param string $fileid
408      * @param string $newname
409      * @return bool
410      */
411     function RenameFile($fileid, $newname) {
412         $params = array(
413             'api_key'    => $this->api_key,
414             'auth_token' => $this->auth_token,
415             'action'     => 'rename',
416             'target'     => 'file',
417             'target_id'  => $fileid,
418             'new_name'   => $newname,
419         );
420         $data = $this->makeRequest('action=rename', $params);
421         if ($this->_checkForError($data)) {
422             return false;
423         }
424         foreach ($data as $a) {
425             switch ($a['tag']) {
426                 case 'STATUS':
427                     if ($a['value'] == 's_rename_node') {
428                         return true;
429                     }
430             }
431         }
432         return false;
433     }
435     /**
436      * Register New User
437      *
438      * @param array $params
439      * @return array|bool Outcome Array or false
440      */
441     function RegisterUser($params = array()) {
442         $params['api_key'] = $this->api_key;
443         $params['action']  = 'register_new_user';
444         $params['login']   = $_REQUEST['login'];
445         $params['password'] = $_REQUEST['password'];
446         $ret_array = array();
447         $data = $this->makeRequest('action=register_new_user', $params);
448         if ($this->_checkForError($data)) {
449             return false;
450         }
451         foreach ($data as $a) {
452             switch ($a['tag']) {
453             case 'STATUS':
454                 $ret_array['status'] = $a['value'];
455                 break;
457             case 'AUTH_TOKEN':
458                 $ret_array['auth_token'] = $a['value'];
459                 break;
461             case 'LOGIN':
462                 $ret_array['login'] = $a['value'];
463                 break;
464             case 'SPACE_AMOUNT':
465                 $ret_array['space_amount'] = $a['value'];
466                 break;
467             case 'SPACE_USED':
468                 $ret_array['space_used'] = $a['value'];
469                 break;
470             }
471         }
473         return $ret_array;
474     }
476     /**
477      * Add Tags  (http://enabled.box.net/docs/rest#add_to_tag)
478      *
479      * @param string $tag
480      * @param string $id Set to ID of file or folder
481      * @param string $target_type File or folder
482      * @param array $params
483      * @return array|bool Outcome Array or false
484      */
485     function AddTag($tag, $id, $target_type, $params = array()) {
486         $params['auth_token'] = $this->auth_token;
487         $params['api_key']    = $this->api_key;
488         $params['action']     = 'add_to_tag';
489         $params['target']     = $target_type; // File or folder
490         $params['target_id']  = $id; // Set to ID of file or folder
491         $params['tags[]']     = $tag;
492         $ret_array = array();
493         $data = $this->makeRequest('action=add_to_tag', $params);
494         if ($this->_checkForError($data)) {
495             return false;
496         }
497         foreach ($data as $a) {
498             switch ($a['tag']) {
499             case 'STATUS':
500                 $ret_array['status'] = $a['value'];
502                 break;
503             }
504         }
505         return $ret_array;
506     }
508     /**
509      * Public Share  (http://enabled.box.net/docs/rest#public_share)
510      *
511      * @param string $message
512      * @param string $emails
513      * @param string $id Set to ID of file or folder
514      * @param string $target_type File or folder
515      * @param string $password
516      * @param array $params
517      * @return array|bool Outcome Array or false
518      */
519     function PublicShare($message, $emails, $id, $target_type, $password, $params = array()) {
520         $params['auth_token'] = $this->auth_token;
521         $params['api_key']    = $this->api_key;
522         $params['action']     = 'public_share';
523         $params['target']     = $target_type;
524         $params['target_id']  = $id;
525         $params['password']   =  $password;
526         $params['message']    = $message;
527         $params['emails']     = $emails;
528         $ret_array = array();
529         $data = $this->makeRequest('action=public_share', $params);
530         if ($this->_checkForError($data)) {
531             return false;
532         }
533         foreach ($data as $a) {
534             switch ($a['tag']) {
535             case 'STATUS':
536                 $ret_array['status'] = $a['value'];
537                 break;
538             case 'PUBLIC_NAME':
539                 $ret_array['public_name'] = $a['value'];
540                 break;
541             }
542         }
544         return $ret_array;
545     }
546     /**
547      * Get Friends  (http://enabled.box.net/docs/rest#get_friends)
548      *
549      * @param array $params
550      * @return array|bool Outcome Array or false
551      */
552     function GetFriends ($params = array()) {
553         $params['auth_token'] = $this->auth_token;
554         $params['action']     = 'get_friends';
555         $params['api_key']    = $this->api_key;
556         $params['params[]']   = 'nozip';
557         $ret_array = array();
558         $data = $this->makeRequest('action=get_friends', $params);
559         if ($this->_checkForError($data)) {
560             return false;
561         }
562         foreach ($data as $a) {
563             switch ($a['tag']) {
564             case 'NAME':
565                 $ret_array['name'] = $a['value'];
566                 break;
567             case 'EMAIL':
568                 $ret_array['email'] = $a['value'];
569                 break;
570             case 'ACCEPTED':
571                 $ret_array['accepted'] = $a['value'];
572                 break;
573             case 'AVATAR_URL':
574                 $ret_array['avatar_url'] = $a['value'];
575                 break;
576             case 'ID':
577                 $ret_array['id'] = $a['value'];
578                 break;
579             case 'URL':
580                 $ret_array['url'] = $a['value'];
581                 break;
582             case 'STATUS':
583                 $ret_array['status'] = $a['value'];
584                 break;
585             }
586         }
587         return $ret_array;
588     }
590     /**
591      * Logout User  (http://enabled.box.net/docs/rest#get_friends)
592      *
593      * @param array $params
594      * @return array|bool Outcome Array or false
595      */
596     function Logout($params = array()) {
597         $params['auth_token'] = $this->auth_token;
598         $params['api_key']    = $this->api_key;
599         $params['action']     = 'logout';
600         $ret_array = array();
601         $data = $this->makeRequest('action=logout', $params);
602         if ($this->_checkForError($data)) {
603             return false;
604         }
605         foreach ($data as $a) {
606             switch ($a['tag']) {
607             case 'ACTION':
608                 $ret_array['logout'] = $a['value'];
610                 break;
611             }
612             return $ret_array;
613         }
614     }
615     /**
616      * @param array $data
617      * @return bool
618      */
619     function _checkForError($data) {
620         if ($this->_error_msg != '') {
621             return true;
622         }
623         if (@$data[0]['attributes']['STAT'] == 'fail') {
624             $this->_error_code = $data[1]['attributes']['CODE'];
625             $this->_error_msg = $data[1]['attributes']['MSG'];
626             return true;
627         }
628         return false;
629     }
631     /**
632      * @return bool
633      */
634     public function isError() {
635         if  ($this->_error_msg != '') {
636             return true;
637         }
638         return false;
639     }
640     /**
641      *
642      */
643     public function setError($code = 0, $msg){
644         $this->_error_code = $code;
645         $this->_error_msg  = $msg;
646     }
647     /**
648      * @return string
649      */
650     function getErrorMsg() {
651         return '<p>Error: (' . $this->_error_code . ') ' . $this->_error_msg . '</p>';
652     }
653     /**
654      * @return string
655      */
656     function getErrorCode() {
657         return $this->_error_code;
658     }
659     /**
660      *
661      */
662     function _clearErrors() {
663         $this->_error_code = '';
664         $this->_error_msg = '';
665     }