REPOSITORY MDL-24205, added more check of path and files
[moodle.git] / repository / dropbox / lib.php
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
18 /**
19  * repository_dropbox class
20  * This plugin is used to access user's dropbox files
21  *
22  * TODO:
23  * Dropbox has problems to process filepath with spaces, tried to use
24  * urlencode filepath, still doesn't work
25  * http://code.google.com/p/dropbox-php/ has the same problem
26  *
27  * @since 2.0
28  * @package    repository
29  * @subpackage dropbox
30  * @copyright  2010 Dongsheng Cai
31  * @author     Dongsheng Cai <dongsheng@moodle.com>
32  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33  */
35 require_once(dirname(__FILE__).'/locallib.php');
37 class repository_dropbox extends repository {
38     private $dropbox;
39     public $files;
40     public $logged=false;
42     /**
43      * Constructor of dropbox plugin
44      * @param int $repositoryid
45      * @param object $context
46      * @param array $options
47      */
48     public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) {
49         global $SESSION, $CFG;
50         $options['page']    = optional_param('p', 1, PARAM_INT);
51         parent::__construct($repositoryid, $context, $options);
53         $this->setting = 'dropbox_';
55         $this->dropbox_key = $this->get_option('dropbox_key');
56         $this->dropbox_secret  = $this->get_option('dropbox_secret');
58         $this->access_key    = get_user_preferences($this->setting.'_access_key', '');
59         $this->access_secret = get_user_preferences($this->setting.'_access_secret', '');
61         if (!empty($this->access_key) && !empty($this->access_secret)) {
62             $this->logged = true;
63         }
65         $this->callback = new moodle_url($CFG->wwwroot.'/repository/repository_callback.php', array(
66             'callback'=>'yes',
67             'repo_id'=>$repositoryid
68             ));
70         $args = array(
71             'oauth_consumer_key'=>$this->dropbox_key,
72             'oauth_consumer_secret'=>$this->dropbox_secret,
73             'oauth_callback' => $this->callback->out(false),
74             'api_root' => 'http://api.dropbox.com/0/oauth',
75         );
77         $this->dropbox = new dropbox($args);
78     }
80     /**
81      * Check if moodle has got access token and secret
82      * @return bool
83      */
84     public function check_login() {
85         return !empty($this->logged);
86     }
88     /**
89      * Generate dropbox login url
90      * @return array
91      */
92     public function print_login() {
93         $result = $this->dropbox->request_token();
94         set_user_preference($this->setting.'_request_secret', $result['oauth_token_secret']);
95         $url = $result['authorize_url'];
96         if ($this->options['ajax']) {
97             $ret = array();
98             $popup_btn = new stdclass;
99             $popup_btn->type = 'popup';
100             $popup_btn->url = $url;
101             $ret['login'] = array($popup_btn);
102             return $ret;
103         } else {
104             echo '<a target="_blank" href="'.$this->flickr->auth().'">'.get_string('login', 'repository').'</a>';
105         }
106     }
108     /**
109      * Request access token
110      * @return array
111      */
112     public function callback() {
113         $token  = optional_param('oauth_token', '', PARAM_TEXT);
114         $secret = get_user_preferences($this->setting.'_request_secret', '');
115         $access_token = $this->dropbox->get_access_token($token, $secret);
116         set_user_preference($this->setting.'_access_key', $access_token['oauth_token']);
117         set_user_preference($this->setting.'_access_secret', $access_token['oauth_token_secret']);
118     }
120     /**
121      * Get dropbox files
122      * @param string $path
123      * @param int $page
124      * @return array
125      */
126     public function get_listing($path = '', $page = '1') {
127         global $OUTPUT;
128         if (empty($path) || $path=='/') {
129             $path = '/';
130         } else {
131             $path = file_correct_filepath($path);
132         }
134         $list = array();
135         $list['list'] = array();
136         $list['manage'] = false;
137         $list['dynload'] = true;
138         $list['nosearch'] = true;
139         // process breacrumb trail
140         $list['path'] = array(
141             array('name'=>get_string('sandbox', 'repository_dropbox'), 'path'=>'/')
142         );
144         $result = $this->dropbox->get_listing($path, $this->access_key, $this->access_secret);
145         if (!is_object($result) || empty($result)) {
146             return $list;
147         }
148         if (empty($result->path)) {
149             $current_path = '/';
150         } else {
151             $current_path = file_correct_filepath($result->path);
152         }
154         $trail = '';
155         if (!empty($path)) {
156             $parts = explode('/', $path);
157             if (count($parts) > 1) {
158                 foreach ($parts as $part) {
159                     if (!empty($part)) {
160                         $trail .= ('/'.$part);
161                         $list['path'][] = array('name'=>$part, 'path'=>$trail);
162                     }
163                 }
164             } else {
165                 $list['path'][] = array('name'=>$path, 'path'=>$path);
166             }
167         }
169         $files = $result->contents;
170         if (!is_array($files) || empty($files)) {
171             return $list;
172         }
173         foreach ($files as $file) {
174             if ($file->is_dir) {
175                 $list['list'][] = array(
176                     'title' => substr($file->path, strpos($file->path, $current_path)+strlen($current_path)),
177                     'path' => file_correct_filepath($file->path),
178                     'size' => $file->size,
179                     'date' => $file->modified,
180                     'thumbnail' => $OUTPUT->pix_url('f/folder-32')->out(false),
181                     'children' => array(),
182                 );
183             } else {
184                 $list['list'][] = array(
185                     'title' => substr($file->path, strpos($file->path, $current_path)+strlen($current_path)),
186                     'source' => $file->path,
187                     'size' => $file->size,
188                     'date' => $file->modified,
189                     'thumbnail' => $OUTPUT->pix_url(file_extension_icon($file->path, 32))->out(false)
190                 );
191             }
192         }
193         return $list;
194     }
195     /**
196      * Logout from dropbox
197      * @return array
198      */
199     public function logout() {
200         set_user_preference($this->setting.'_access_key', '');
201         set_user_preference($this->setting.'_access_secret', '');
202         $this->access_key    = '';
203         $this->access_secret = '';
204         return $this->print_login();
205     }
207     /**
208      * Set dropbox option
209      * @param array $options
210      * @return mixed
211      */
212     public function set_option($options = array()) {
213         if (!empty($options['dropbox_key'])) {
214             set_config('dropbox_key', trim($options['dropbox_key']), 'dropbox');
215         }
216         if (!empty($options['dropbox_secret'])) {
217             set_config('dropbox_secret', trim($options['dropbox_secret']), 'dropbox');
218         }
219         unset($options['dropbox_key']);
220         unset($options['dropbox_secret']);
221         $ret = parent::set_option($options);
222         return $ret;
223     }
225     /**
226      * Get dropbox options
227      * @param string $config
228      * @return mixed
229      */
230     public function get_option($config = '') {
231         if ($config==='dropbox_key') {
232             return trim(get_config('dropbox', 'dropbox_key'));
233         } elseif ($config==='dropbox_secret') {
234             return trim(get_config('dropbox', 'dropbox_secret'));
235         } else {
236             $options['dropbox_key'] = trim(get_config('dropbox', 'dropbox_key'));
237             $options['dropbox_secret'] = trim(get_config('dropbox', 'dropbox_secret'));
238         }
239         $options = parent::get_option($config);
240         return $options;
241     }
243     /**
244      *
245      * @param string $photo_id
246      * @param string $file
247      * @return string
248      */
249     public function get_file($filepath, $saveas = '') {
250         $this->dropbox->set_access_token($this->access_key, $this->access_secret);
251         return $this->dropbox->get_file($filepath, $saveas);
252     }
253     /**
254      * Add Plugin settings input to Moodle form
255      * @param object $mform
256      */
257     public function type_config_form($mform) {
258         global $CFG;
259         parent::type_config_form($mform);
260         $key    = get_config('dropbox', 'dropbox_key');
261         $secret = get_config('dropbox', 'dropbox_secret');
263         if (empty($key)) {
264             $key = '';
265         }
266         if (empty($secret)) {
267             $secret = '';
268         }
270         $strrequired = get_string('required');
272         $mform->addElement('text', 'dropbox_key', get_string('apikey', 'repository_dropbox'), array('value'=>$key,'size' => '40'));
273         $mform->addElement('text', 'dropbox_secret', get_string('secret', 'repository_dropbox'), array('value'=>$secret,'size' => '40'));
275         $mform->addRule('dropbox_key', $strrequired, 'required', null, 'client');
276         $mform->addRule('dropbox_secret', $strrequired, 'required', null, 'client');
277         $str_getkey = get_string('instruction', 'repository_dropbox');
278         $mform->addElement('static', null, '',  $str_getkey);
279     }
281     /**
282      * Option names of dropbox plugin
283      * @return array
284      */
285     public static function get_type_option_names() {
286         return array('dropbox_key', 'dropbox_secret', 'pluginname');
287     }
289     /**
290      * Dropbox plugin supports all kinds of files
291      * @return array
292      */
293     public function supported_filetypes() {
294         return '*';
295     }
297     /**
298      * User cannot use the external link to dropbox
299      * @return int
300      */
301     public function supported_returntypes() {
302         return FILE_INTERNAL;
303     }