Merge branch 'MDL-29810' of git://github.com/bostelm/moodle
[moodle.git] / repository / repository_ajax.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/>.
19 /**
20  * The Web service script that is called from the filepicker front end
21  *
22  * @since 2.0
23  * @package    core
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  */
29 define('AJAX_SCRIPT', true);
31 require_once(dirname(dirname(__FILE__)).'/config.php');
32 require_once(dirname(dirname(__FILE__)).'/lib/filelib.php');
33 require_once(dirname(__FILE__).'/lib.php');
35 $err = new stdClass();
37 /// Parameters
38 $action    = optional_param('action', '', PARAM_ALPHA);
39 $repo_id   = optional_param('repo_id', 0, PARAM_INT);           // Repository ID
40 $contextid = optional_param('ctx_id', SYSCONTEXTID, PARAM_INT); // Context ID
41 $env       = optional_param('env', 'filepicker', PARAM_ALPHA);  // Opened in editor or moodleform
42 $license   = optional_param('license', $CFG->sitedefaultlicense, PARAM_TEXT);
43 $author    = optional_param('author', '', PARAM_TEXT);          // File author
44 $source    = optional_param('source', '', PARAM_RAW);           // File to download
45 $itemid    = optional_param('itemid', 0, PARAM_INT);            // Itemid
46 $page      = optional_param('page', '', PARAM_RAW);             // Page
47 $maxbytes  = optional_param('maxbytes', 0, PARAM_INT);          // Maxbytes
48 $req_path  = optional_param('p', '', PARAM_RAW);                // Path
49 $accepted_types  = optional_param_array('accepted_types', '*', PARAM_RAW);
50 $saveas_filename = optional_param('title', '', PARAM_FILE);     // save as file name
51 $saveas_path   = optional_param('savepath', '/', PARAM_PATH);   // save as file path
52 $search_text   = optional_param('s', '', PARAM_CLEANHTML);
53 $linkexternal  = optional_param('linkexternal', '', PARAM_ALPHA);
55 list($context, $course, $cm) = get_context_info_array($contextid);
56 require_login($course, false, $cm);
57 $PAGE->set_context($context);
59 echo $OUTPUT->header(); // send headers
60 @header('Content-type: text/html; charset=utf-8');
62 // if uploaded file is larger than post_max_size (php.ini) setting, $_POST content will lost
63 if (empty($_POST) && !empty($action)) {
64     $err->error = get_string('errorpostmaxsize', 'repository');
65     die(json_encode($err));
66 }
68 if (!confirm_sesskey()) {
69     $err->error = get_string('invalidsesskey');
70     die(json_encode($err));
71 }
73 /// Get repository instance information
74 $sql = 'SELECT i.name, i.typeid, r.type FROM {repository} r, {repository_instances} i WHERE i.id=? AND i.typeid=r.id';
76 if (!$repository = $DB->get_record_sql($sql, array($repo_id))) {
77     $err->error = get_string('invalidrepositoryid', 'repository');
78     die(json_encode($err));
79 } else {
80     $type = $repository->type;
81 }
83 /// Check permissions
84 repository::check_capability($contextid, $repository);
86 $moodle_maxbytes = get_max_upload_file_size();
87 // to prevent maxbytes greater than moodle maxbytes setting
88 if ($maxbytes == 0 || $maxbytes>=$moodle_maxbytes) {
89     $maxbytes = $moodle_maxbytes;
90 }
92 /// Wait as long as it takes for this script to finish
93 set_time_limit(0);
95 // Early actions which need to be done before repository instances initialised
96 switch ($action) {
97     // global search
98     case 'gsearch':
99         $params = array();
100         $params['context'] = array(get_context_instance_by_id($contextid), get_system_context());
101         $params['currentcontext'] = get_context_instance_by_id($contextid);
102         $repos = repository::get_instances($params);
103         $list = array();
104         foreach($repos as $repo){
105             if ($repo->global_search()) {
106                 $ret = $repo->search($search_text);
107                 array_walk($ret['list'], 'repository_attach_id', $repo->id);  // See function below
108                 $tmp = array_merge($list, $ret['list']);
109                 $list = $tmp;
110             }
111         }
112         $listing = array('list'=>$list);
113         $listing['gsearch'] = true;
114         die(json_encode($listing));
115         break;
117     // remove the cache files & logout
118     case 'ccache':
119         $cache = new curl_cache;
120         $cache->refresh();
121         $action = 'list';
122         break;
125 if (file_exists($CFG->dirroot.'/repository/'.$type.'/lib.php')) {
126     require_once($CFG->dirroot.'/repository/'.$type.'/lib.php');
127     $classname = 'repository_' . $type;
128     $repo = new $classname($repo_id, $contextid, array('ajax'=>true, 'name'=>$repository->name, 'type'=>$type));
129 } else {
130     $err->error = get_string('invalidplugin', 'repository', $type);
131     die(json_encode($err));
134 /// These actions all occur on the currently active repository instance
135 switch ($action) {
136     case 'sign':
137     case 'signin':
138     case 'list':
139         if ($repo->check_login()) {
140             $listing = $repo->get_listing($req_path, $page);
141             $listing['repo_id'] = $repo_id;
142             echo json_encode($listing);
143             break;
144         } else {
145             $action = 'login';
146         }
147     case 'login':
148         $listing = $repo->print_login();
149         $listing['repo_id'] = $repo_id;
150         echo json_encode($listing);
151         break;
152     case 'logout':
153         $logout = $repo->logout();
154         $logout['repo_id'] = $repo_id;
155         echo json_encode($logout);
156         break;
157     case 'searchform':
158         $search_form['form'] = $repo->print_search();
159         echo json_encode($search_form);
160         break;
161     case 'search':
162         $search_result = $repo->search($search_text, (int)$page);
163         $search_result['repo_id'] = $repo_id;
164         $search_result['issearchresult'] = true;
165         echo json_encode($search_result);
166         break;
167     case 'download':
168         // validate mimetype
169         $mimetypes = array();
170         if ((is_array($accepted_types) and in_array('*', $accepted_types)) or $accepted_types == '*') {
171             $mimetypes = '*';
172         } else {
173             foreach ($accepted_types as $type) {
174                 $mimetypes[] = mimeinfo('type', $type);
175             }
176             if (!in_array(mimeinfo('type', $saveas_filename), $mimetypes)) {
177                 throw new moodle_exception('invalidfiletype', 'repository', '', get_string(mimeinfo('type', $saveas_filename), 'mimetypes'));
178             }
179         }
181         // We have two special repository type need to deal with
182         // local and recent plugins don't added new files to moodle, just add new records to database
183         // so we don't check user quota and maxbytes here
184         $allowexternallink = (int)get_config(null, 'repositoryallowexternallinks');
185         if (!empty($allowexternallink)) {
186             $allowexternallink = true;
187         } else {
188             $allowexternallink = false;
189         }
190         // allow external links in url element all the time
191         $allowexternallink = ($allowexternallink || ($env == 'url'));
193         // Use link of the files
194         if ($allowexternallink and $linkexternal === 'yes' and ($repo->supported_returntypes() & FILE_EXTERNAL)) {
195             // use external link
196             $link = $repo->get_link($source);
197             $info = array();
198             $info['filename'] = $saveas_filename;
199             $info['type'] = 'link';
200             $info['url'] = $link;
201             echo json_encode($info);
202             die;
203         } else {
204             // some repository plugins deal with moodle internal files, so we cannot use get_file
205             // method, so we use copy_to_area method
206             // (local, user, coursefiles, recent)
207             if ($repo->has_moodle_files()) {
208                 // check filesize against max allowed size
209                 $filesize = $repo->get_file_size($source);
210                 if (empty($filesize)) {
211                     $err->error = get_string('filesizenull', 'repository');
212                     die(json_encode($err));
213                 }
214                 if (($maxbytes !== -1) && ($filesize > $maxbytes)) {
215                     throw new file_exception('maxbytes');
216                 }
217                 $fileinfo = $repo->copy_to_area($source, $itemid, $saveas_path, $saveas_filename);
218                 echo json_encode($fileinfo);
219                 die;
220             }
221             // Download file to moodle
222             $file = $repo->get_file($source, $saveas_filename);
223             if ($file['path'] === false) {
224                 $err->error = get_string('cannotdownload', 'repository');
225                 die(json_encode($err));
226             }
228             // check if exceed maxbytes
229             if (($maxbytes!==-1) && (filesize($file['path']) > $maxbytes)) {
230                 throw new file_exception('maxbytes');
231             }
233             $record = new stdClass();
234             $record->filepath = $saveas_path;
235             $record->filename = $saveas_filename;
236             $record->component = 'user';
237             $record->filearea = 'draft';
238             $record->itemid   = $itemid;
240             if (!empty($file['license'])) {
241                 $record->license  = $file['license'];
242             } else {
243                 $record->license  = $license;
244             }
245             if (!empty($file['author'])) {
246                 $record->author   = $file['author'];
247             } else {
248                 $record->author   = $author;
249             }
250             $record->source = !empty($file['url']) ? $file['url'] : '';
252             $info = repository::move_to_filepool($file['path'], $record);
253             if (empty($info)) {
254                 $info['e'] = get_string('error', 'moodle');
255             }
256             echo json_encode($info);
257             die;
258         }
259         break;
260     case 'upload':
261         $result = $repo->upload($saveas_filename, $maxbytes);
262         echo json_encode($result);
263         break;
265     case 'overwrite':
266         // existing file
267         $filepath    = required_param('existingfilepath', PARAM_PATH);
268         $filename    = required_param('existingfilename', PARAM_FILE);
269         // user added file which needs to replace the existing file
270         $newfilepath = required_param('newfilepath', PARAM_PATH);
271         $newfilename = required_param('newfilename', PARAM_FILE);
273         echo json_encode(repository::overwrite_existing_draftfile($itemid, $filepath, $filename, $newfilepath, $newfilename));
274         break;
276     case 'deletetmpfile':
277         // delete tmp file
278         $newfilepath = required_param('newfilepath', PARAM_PATH);
279         $newfilename = required_param('newfilename', PARAM_FILE);
280         echo json_encode(repository::delete_tempfile_from_draft($itemid, $newfilepath, $newfilename));
282         break;