Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 401 and 402] [Versions 401 and 403]

   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/>.
  16  
  17  
  18  /**
  19   * Accept uploading files by web service token to the user draft file area.
  20   *
  21   * POST params:
  22   *  token => the web service user token (needed for authentication)
  23   *  filepath => file path (where files will be stored)
  24   *  [_FILES] => for example you can send the files with <input type=file>,
  25   *              or with curl magic: 'file_1' => '@/path/to/file', or ...
  26   *  itemid   => The draftid - this can be used to add a list of files
  27   *              to a draft area in separate requests. If it is 0, a new draftid will be generated.
  28   *
  29   * @package    core_webservice
  30   * @copyright  2011 Dongsheng Cai <dongsheng@moodle.com>
  31   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  32   */
  33  
  34  /**
  35   * AJAX_SCRIPT - exception will be converted into JSON
  36   */
  37  define('AJAX_SCRIPT', true);
  38  
  39  /**
  40   * NO_MOODLE_COOKIES - we don't want any cookie
  41   */
  42  define('NO_MOODLE_COOKIES', true);
  43  
  44  require_once(__DIR__ . '/../config.php');
  45  require_once($CFG->dirroot . '/webservice/lib.php');
  46  
  47  // Allow CORS requests.
  48  header('Access-Control-Allow-Origin: *');
  49  
  50  $filepath = optional_param('filepath', '/', PARAM_PATH);
  51  $itemid = optional_param('itemid', 0, PARAM_INT);
  52  
  53  echo $OUTPUT->header();
  54  
  55  // authenticate the user
  56  $token = required_param('token', PARAM_ALPHANUM);
  57  $webservicelib = new webservice();
  58  $authenticationinfo = $webservicelib->authenticate_user($token);
  59  $fileuploaddisabled = empty($authenticationinfo['service']->uploadfiles);
  60  if ($fileuploaddisabled) {
  61      throw new webservice_access_exception('Web service file upload must be enabled in external service settings');
  62  }
  63  
  64  $context = context_user::instance($USER->id);
  65  
  66  $fs = get_file_storage();
  67  
  68  $totalsize = 0;
  69  $files = array();
  70  foreach ($_FILES as $fieldname=>$uploaded_file) {
  71      // check upload errors
  72      if (!empty($_FILES[$fieldname]['error'])) {
  73          switch ($_FILES[$fieldname]['error']) {
  74          case UPLOAD_ERR_INI_SIZE:
  75              throw new moodle_exception('upload_error_ini_size', 'repository_upload');
  76              break;
  77          case UPLOAD_ERR_FORM_SIZE:
  78              throw new moodle_exception('upload_error_form_size', 'repository_upload');
  79              break;
  80          case UPLOAD_ERR_PARTIAL:
  81              throw new moodle_exception('upload_error_partial', 'repository_upload');
  82              break;
  83          case UPLOAD_ERR_NO_FILE:
  84              throw new moodle_exception('upload_error_no_file', 'repository_upload');
  85              break;
  86          case UPLOAD_ERR_NO_TMP_DIR:
  87              throw new moodle_exception('upload_error_no_tmp_dir', 'repository_upload');
  88              break;
  89          case UPLOAD_ERR_CANT_WRITE:
  90              throw new moodle_exception('upload_error_cant_write', 'repository_upload');
  91              break;
  92          case UPLOAD_ERR_EXTENSION:
  93              throw new moodle_exception('upload_error_extension', 'repository_upload');
  94              break;
  95          default:
  96              throw new moodle_exception('nofile');
  97          }
  98      }
  99  
 100      // Scan for viruses.
 101      \core\antivirus\manager::scan_file($_FILES[$fieldname]['tmp_name'], $_FILES[$fieldname]['name'], true);
 102  
 103      $file = new stdClass();
 104      $file->filename = clean_param($_FILES[$fieldname]['name'], PARAM_FILE);
 105      // check system maxbytes setting
 106      if (($_FILES[$fieldname]['size'] > get_max_upload_file_size($CFG->maxbytes))) {
 107          // oversize file will be ignored, error added to array to notify
 108          // web service client
 109          $file->errortype = 'fileoversized';
 110          $file->error = get_string('maxbytes', 'error');
 111      } else {
 112          $file->filepath = $_FILES[$fieldname]['tmp_name'];
 113          // calculate total size of upload
 114          $totalsize += $_FILES[$fieldname]['size'];
 115      }
 116      $files[] = $file;
 117  }
 118  
 119  $fs = get_file_storage();
 120  
 121  if ($itemid <= 0) {
 122      $itemid = file_get_unused_draft_itemid();
 123  }
 124  
 125  // Get any existing file size limits.
 126  $maxupload = get_user_max_upload_file_size($context, $CFG->maxbytes);
 127  
 128  // Check the size of this upload.
 129  if ($maxupload !== USER_CAN_IGNORE_FILE_SIZE_LIMITS && $totalsize > $maxupload) {
 130      throw new file_exception('userquotalimit');
 131  }
 132  
 133  $results = array();
 134  foreach ($files as $file) {
 135      if (!empty($file->error)) {
 136          // including error and filename
 137          $results[] = $file;
 138          continue;
 139      }
 140      $file_record = new stdClass;
 141      $file_record->component = 'user';
 142      $file_record->contextid = $context->id;
 143      $file_record->userid    = $USER->id;
 144      $file_record->filearea  = 'draft';
 145      $file_record->filename = $file->filename;
 146      $file_record->filepath  = $filepath;
 147      $file_record->itemid    = $itemid;
 148      $file_record->license   = $CFG->sitedefaultlicense;
 149      $file_record->author    = fullname($authenticationinfo['user']);
 150      $file_record->source    = serialize((object)array('source' => $file->filename));
 151  
 152      //Check if the file already exist
 153      $existingfile = $fs->file_exists($file_record->contextid, $file_record->component, $file_record->filearea,
 154                  $file_record->itemid, $file_record->filepath, $file_record->filename);
 155      if ($existingfile) {
 156          $file->errortype = 'filenameexist';
 157          $file->error = get_string('filenameexist', 'webservice', $file->filename);
 158          $results[] = $file;
 159      } else {
 160          $stored_file = $fs->create_file_from_pathname($file_record, $file->filepath);
 161          $results[] = $file_record;
 162      }
 163  }
 164  echo json_encode($results);