"MDL-13766, fixed path bar parameter, better exception handling"
[moodle.git] / repository / repository_ajax.php
CommitLineData
aa6c1ced 1<?php
5bce5972 2
6f2cd52a
DC
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/>.
17
18
19/**
20 * The Web service script that is called from the filepicker front end
21 *
22 * @since 2.0
23 * @package moodlecore
24 * @subpackage repository
25 * @copyright 2009 Dongsheng Cai <dongsheng@moodle.com>
26 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 */
455860ce 28
14469892
DC
29require_once(dirname(dirname(__FILE__)).'/config.php');
30require_once(dirname(dirname(__FILE__)).'/lib/filelib.php');
31require_once(dirname(__FILE__).'/lib.php');
99eaca9d 32
9d4ef80f 33require_login();
cf493e89 34
d0f8585d 35/// Parameters
9d4ef80f 36$action = optional_param('action', '', PARAM_ALPHA);
f8df83f3 37$repo_id = optional_param('repo_id', 0, PARAM_INT); // repository ID
9d4ef80f 38$callback = optional_param('callback', '', PARAM_CLEANHTML);
d10c92f3
DC
39$client_id = optional_param('client_id', '', PARAM_RAW); // client ID
40$contextid = optional_param('ctx_id', SYSCONTEXTID, PARAM_INT); // context ID
9d4ef80f 41$env = optional_param('env', 'filepicker', PARAM_ALPHA); // opened in editor or moodleform
1dce6261
DC
42$license = optional_param('license', $CFG->sitedefaultlicense, PARAM_TEXT);
43$author = optional_param('author', '', PARAM_TEXT);
14469892 44$source = optional_param('source', '', PARAM_RAW); // file to download
9d4ef80f 45$itemid = optional_param('itemid', 0, PARAM_INT);
9d4ef80f
DC
46$page = optional_param('page', '', PARAM_RAW); // page
47$maxbytes = optional_param('maxbytes', -1, PARAM_INT);
48$req_path = optional_param('p', '', PARAM_RAW); // path
14469892
DC
49$saveas_filearea = optional_param('filearea', 'user_draft', PARAM_TEXT);
50$saveas_filename = optional_param('title', '', PARAM_FILE); // new file name
51$saveas_path = optional_param('saveaspath', '/', PARAM_PATH);
9d4ef80f
DC
52$search_text = optional_param('s', '', PARAM_CLEANHTML);
53$linkexternal = optional_param('linkexternal', '', PARAM_ALPHA);
455860ce 54
577aab9b 55/// Headers to make it not cacheable
9d4ef80f
DC
56header('Cache-Control: no-cache, must-revalidate');
57header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
58
59$err = new stdclass;
60$err->client_id = $client_id;
0eb58cf4 61
d0f8585d 62/// Check permissions
9d4ef80f
DC
63if (! (isloggedin() && repository::check_context($contextid)) ) {
64 $err->e = get_string('nopermissiontoaccess', 'repository');
65 die(json_encode($err));
66}
0eb58cf4 67
577aab9b 68/// Wait as long as it takes for this script to finish
9d4ef80f 69set_time_limit(0);
577aab9b 70
9d4ef80f
DC
71// Early actions which need to be done before repository instaces initialised
72switch ($action) {
73 // global search
74 case 'gsearch':
75 $params = array();
76 $params['context'] = array(get_context_instance_by_id($contextid), get_system_context());
77 $params['currentcontext'] = get_context_instance_by_id($contextid);
78 $repos = repository::get_instances($params);
79 $list = array();
80 foreach($repos as $repo){
81 if ($repo->global_search()) {
82 try {
83 $ret = $repo->search($search_text);
84 array_walk($ret['list'], 'repository_attach_id', $repo->id); // See function below
85 $tmp = array_merge($list, $ret['list']);
86 $list = $tmp;
87 } catch (repository_exception $e) {
88 $err->e = $e->getMessage();
89 die(json_encode($err));
d0f8585d 90 }
91 }
9d4ef80f
DC
92 }
93 $listing = array('list'=>$list);
94 $listing['gsearch'] = true;
95 $listing['client_id'] = $client_id;
96 die(json_encode($listing));
97 break;
d0f8585d 98
9d4ef80f
DC
99 // remove the cache files & logout
100 case 'ccache':
101 $cache = new curl_cache;
102 $cache->refresh();
103 $action = 'list';
104 break;
105}
d0f8585d 106
107/// Get repository instance information
9d4ef80f
DC
108$sql = 'SELECT i.name, i.typeid, r.type FROM {repository} r, {repository_instances} i '.
109 'WHERE i.id=? AND i.typeid=r.id';
d0f8585d 110
9d4ef80f
DC
111if (!$repository = $DB->get_record_sql($sql, array($repo_id))) {
112 $err->e = get_string('invalidrepositoryid', 'repository');
113 die(json_encode($err));
114} else {
115 $type = $repository->type;
116}
117
118if (file_exists($CFG->dirroot.'/repository/'.$type.'/repository.class.php')) {
119 require_once($CFG->dirroot.'/repository/'.$type.'/repository.class.php');
120 $classname = 'repository_' . $type;
121 try {
122 $repo = new $classname($repo_id, $contextid, array('ajax'=>true, 'name'=>$repository->name, 'type'=>$type, 'client_id'=>$client_id));
123 } catch (repository_exception $e){
124 $err->e = $e->getMessage();
bf1fccf0 125 die(json_encode($err));
5bce5972 126 }
a06878d3 127} else {
9d4ef80f
DC
128 $err->e = get_string('invalidplugin', 'repository', $type);
129 die(json_encode($err));
a06878d3 130}
9d4ef80f
DC
131
132
133if (!empty($callback)) {
134 // call opener window to refresh repository
135 // the callback url should be something like this:
136 // http://xx.moodle.com/repository/repository_ajax.php?callback=yes&repo_id=1&sid=xxx
137 // sid is the attached auth token from external source
138 // If Moodle is working on HTTPS mode, then we are not allowed to access
139 // parent window, in this case, we need to alert user to refresh the repository
140 // manually.
141 $strhttpsbug = get_string('cannotaccessparentwin', 'repository');
142 $strrefreshnonjs = get_string('refreshnonjsfilepicker', 'repository');
143 $js =<<<EOD
144<html>
145<head>
146 <script type="text/javascript">
147 if(window.opener){
148 window.opener.M.core_filepicker.active_filepicker.list();
149 window.close();
150 } else {
151 alert("{$strhttpsbug }");
152 }
153 </script>
154</head>
5e98ab96 155<body>
9d4ef80f 156 <noscript>
99eaca9d 157 {$strrefreshnonjs}
9d4ef80f 158 </noscript>
5e98ab96 159</body>
160</html>
d0f8585d 161EOD;
9d4ef80f
DC
162 die($js);
163}
d0f8585d 164
165/// These actions all occur on the currently active repository instance
9d4ef80f
DC
166switch ($action) {
167 case 'sign':
168 case 'signin':
169 case 'list':
170 if ($repo->check_login()) {
d0f8585d 171 try {
9d4ef80f 172 $listing = $repo->get_listing($req_path, $page);
e189ec00 173 $listing['client_id'] = $client_id;
174 $listing['repo_id'] = $repo_id;
175 echo json_encode($listing);
d0f8585d 176 } catch (repository_exception $e) {
d0f8585d 177 $err->e = $e->getMessage();
178 die(json_encode($err));
179 }
180 break;
9d4ef80f
DC
181 } else {
182 $action = 'login';
183 }
184 case 'login':
185 try {
186 $listing = $repo->print_login();
187 $listing['client_id'] = $client_id;
188 $listing['repo_id'] = $repo_id;
189 echo json_encode($listing);
190 } catch (repository_exception $e){
191 $err->e = $e->getMessage();
192 die(json_encode($err));
193 }
194 break;
195 case 'logout':
196 $logout = $repo->logout();
197 $logout['client_id'] = $client_id;
198 $logout['repo_id'] = $repo_id;
199 echo json_encode($logout);
200 break;
201 case 'searchform':
202 $search_form['form'] = $repo->print_search($client_id);
203 $search_form['client_id'] = $client_id;
204 echo json_encode($search_form);
205 break;
206 case 'search':
207 try {
208 $search_result = $repo->search($search_text, (int)$page);
209 $search_result['client_id'] = $client_id;
210 $search_result['repo_id'] = $repo_id;
211 $search_result['search_result'] = true;
212 echo json_encode($search_result);
213 } catch (repository_exception $e) {
214 $err->e = $e->getMessage();
215 die(json_encode($err));
216 }
217 break;
218 case 'download':
219 try {
220 // we have two special repoisitory type need to deal with
7f288e50
DC
221 if ($repo->options['type'] == 'local' || $repo->options['type'] == 'recent' ) {
222 $fileinfo = repository::move_to_draft($source, $saveas_filename, $itemid, $saveas_path);
9d4ef80f
DC
223 $info = array();
224 $info['client_id'] = $client_id;
225 $info['file'] = $fileinfo['title'];
226 $info['id'] = $itemid;
227 $info['url'] = $CFG->httpswwwroot.'/draftfile.php/'.$fileinfo['contextid'].'/user_draft/'.$itemid.'/'.$fileinfo['title'];
228 $filesize = $fileinfo['filesize'];
229 if (($maxbytes!==-1) && ($filesize > $maxbytes)) {
230 $fileinfo->delete();
231 throw new file_exception('maxbytes');
41076c58 232 }
9d4ef80f
DC
233 die(json_encode($info));
234 }
41076c58 235
9d4ef80f
DC
236 $allowexternallink = (int)get_config(null, 'repositoryallowexternallinks');
237 if (!empty($allowexternallink)) {
238 $allowexternallink = true;
239 } else {
240 $allowexternallink = false;
241 }
242 // allow external links in url element all the time
243 $allowexternallink = ($allowexternallink || ($env == 'url'));
99d52655 244
9d4ef80f
DC
245 if ($allowexternallink and $linkexternal === 'yes' and ($repo->supported_returntypes() || FILE_EXTERNAL)) {
246 try {
14469892 247 $link = $repo->get_link($source);
9d4ef80f 248 } catch (repository_exception $e){
99d52655 249 }
9d4ef80f 250 $info = array();
14469892 251 $info['filename'] = $saveas_filename;
9d4ef80f
DC
252 $info['type'] = 'link';
253 $info['url'] = $link;
254 die(json_encode($info));
255 }
99d52655 256
9d4ef80f 257 // get the file location
1dce6261
DC
258 $file = $repo->get_file($source, $saveas_filename);
259 if ($file['path'] === false) {
9d4ef80f 260 $err->e = get_string('cannotdownload', 'repository');
d0f8585d 261 die(json_encode($err));
262 }
1dce6261 263 if (($maxbytes!==-1) && (filesize($file['path']) > $maxbytes)) {
9d4ef80f 264 throw new file_exception('maxbytes');
d0f8585d 265 }
14469892
DC
266
267 $record = new stdclass;
268 $record->filepath = $saveas_path;
269 $record->filename = $saveas_filename;
270 $record->filearea = $saveas_filearea;
271 $record->itemid = $itemid;
14469892 272
1dce6261
DC
273 if (!empty($file['license'])) {
274 $record->license = $file['license'];
275 } else {
276 $record->license = $license;
277 }
278 if (!empty($file['author'])) {
279 $record->author = $file['author'];
280 } else {
281 $record->author = $author;
282 }
283 $record->source = !empty($file['url']) ? $file['url'] : '';
284
285 $info = repository::move_to_filepool($file['path'], $record);
9d4ef80f
DC
286 if (empty($info)) {
287 $info['e'] = get_string('error', 'moodle');
288 }
289 echo json_encode($info);
290 } catch (repository_exception $e){
291 $err->e = $e->getMessage();
292 die(json_encode($err));
293 } catch (Exception $e) {
294 $err->e = $e->getMessage();
295 die(json_encode($err));
296 }
297 break;
298 case 'upload':
299 try {
1dce6261 300 $result = $repo->upload();
9d4ef80f
DC
301 $result['client_id'] = $client_id;
302 echo json_encode($result);
303 } catch (Exception $e){
304 $err->e = $e->getMessage();
305 $err->client_id = $client_id;
306 die(json_encode($err));
307 }
308 break;
309}
d0f8585d 310
311/**
312 * Small function to walk an array to attach repository ID
9d4ef80f
DC
313 * @param array $value
314 * @param string $key
315 * @param int $id
d0f8585d 316 */
317function repository_attach_id(&$value, $key, $id){
318 $value['repo_id'] = $id;
0eb58cf4 319}