Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
namespace Moodle;
4
 
5
use stdClass;
6
 
7
/**
8
 * Class
9
 */
10
class H5peditorFile {
11
  private $result, $field, $interface;
12
  public $type, $name, $path, $mime, $size, $extension;
13
 
14
  /**
15
   * Constructor. Process data for file uploaded through the editor.
16
   */
17
  function __construct($interface) {
18
    $field = filter_input(INPUT_POST, 'field', FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_FLAG_NO_ENCODE_QUOTES);
19
 
20
    // Check for file upload.
21
    if ($field === NULL || empty($_FILES) || !isset($_FILES['file'])) {
22
      return;
23
    }
24
 
25
    $this->interface = $interface;
26
 
27
    // Create a new result object.
28
    $this->result = new stdClass();
29
 
30
    // Get the field.
31
    $this->field = json_decode($field);
32
 
33
    // Handle temporarily uploaded form file
34
    if (function_exists('finfo_file')) {
35
      $finfo = finfo_open(FILEINFO_MIME_TYPE);
36
      $this->type = finfo_file($finfo, $_FILES['file']['tmp_name']);
37
      finfo_close($finfo);
38
    }
39
    elseif (function_exists('mime_content_type')) {
40
      // Deprecated, only when finfo isn't available.
41
      $this->type = mime_content_type($_FILES['file']['tmp_name']);
42
    }
43
    else {
44
      $this->type = $_FILES['file']['type'];
45
    }
46
 
47
    $this->extension = pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
48
    $this->size = $_FILES['file']['size'];
49
  }
50
 
51
  /**
52
   * Indicates if an uploaded file was found or not.
53
   *
54
   * @return boolean
55
   */
56
  public function isLoaded() {
57
    return is_object($this->result);
58
  }
59
 
60
  /**
61
   * Check current file up agains mime types and extensions in the given list.
62
   *
63
   * @param array $mimes List to check against.
64
   * @return boolean
65
   */
66
  public function check($mimes) {
67
    $ext = strtolower($this->extension);
68
    foreach ($mimes as $mime => $extension) {
69
      if (is_array($extension)) {
70
        // Multiple extensions
71
        if (in_array($ext, $extension)) {
72
          $this->type = $mime;
73
          return TRUE;
74
        }
75
      }
76
      elseif (/*$this->type === $mime && */$ext === $extension) {
77
        // TODO: Either remove everything that has to do with mime types, or make it work
78
        // Currently we're experiencing trouble with mime types on different servers...
79
        $this->type = $mime;
80
        return TRUE;
81
      }
82
    }
83
    return FALSE;
84
  }
85
 
86
  /**
87
   * Validate the file.
88
   *
89
   * @return boolean
90
   */
91
  public function validate() {
92
    if (isset($this->result->error)) {
93
      return FALSE;
94
    }
95
 
96
    // Check for field type.
97
    if (!isset($this->field->type)) {
98
      $this->result->error = $this->interface->t('Unable to get field type.');
99
      return FALSE;
100
    }
101
 
102
    $whitelist = explode(' ', $this->interface->getWhitelist(
103
      FALSE,
104
      H5PCore::$defaultContentWhitelist,
105
      H5PCore::$defaultLibraryWhitelistExtras
106
    ));
107
 
108
    // Check if mime type is allowed.
109
    $isValidMime = !isset($this->field->mimes) || in_array($this->type, $this->field->mimes);
110
    $isPhp = substr($this->extension, 0, 3) === 'php';
111
    $isWhitelisted = in_array(strtolower($this->extension), $whitelist);
112
    if (!$isValidMime || !$isWhitelisted || $isPhp) {
113
      $this->result->error = $this->interface->t("File type isn't allowed.");
114
      return FALSE;
115
    }
116
 
117
    // Type specific validations.
118
    switch ($this->field->type) {
119
      default:
120
        $this->result->error = $this->interface->t('Invalid field type.');
121
        return FALSE;
122
 
123
      case 'image':
124
        $allowed = array(
125
          'image/png' => 'png',
126
          'image/jpeg' => array('jpg', 'jpeg'),
127
          'image/gif' => 'gif',
128
        );
129
        if (!$this->check($allowed)) {
130
          $this->result->error = $this->interface->t('Invalid image file format. Use jpg, png or gif.');
131
          return FALSE;
132
        }
133
 
134
        // Image size from temp file
135
        $image = @getimagesize($_FILES['file']['tmp_name']);
136
 
137
        if (!$image) {
138
          $this->result->error = $this->interface->t('File is not an image.');
139
          return FALSE;
140
        }
141
 
142
        $this->result->width = $image[0];
143
        $this->result->height = $image[1];
144
        $this->result->mime = $this->type;
145
        break;
146
 
147
      case 'audio':
148
        $allowed = array(
149
          'audio/mpeg' => 'mp3',
150
          'audio/mp3' => 'mp3',
151
          'audio/mp4' => 'm4a',
152
          'audio/x-wav' => 'wav',
153
          'audio/wav' => 'wav',
154
          //'application/ogg' => 'ogg',
155
          'audio/ogg' => 'ogg',
156
          //'video/ogg' => 'ogg',
157
        );
158
        if (!$this->check($allowed)) {
159
          $this->result->error = $this->interface->t('Invalid audio file format. Use mp3 or wav.');
160
          return FALSE;
161
 
162
        }
163
 
164
        $this->result->mime = $this->type;
165
        break;
166
 
167
      case 'video':
168
        $allowed = array(
169
          'video/mp4' => 'mp4',
170
          'video/webm' => 'webm',
171
         // 'application/ogg' => 'ogv',
172
          'video/ogg' => 'ogv',
173
        );
174
        if (!$this->check($allowed)) {
175
          $this->result->error = $this->interface->t('Invalid video file format. Use mp4 or webm.');
176
          return FALSE;
177
        }
178
 
179
        $this->result->mime = $this->type;
180
        break;
181
 
182
      case 'file':
183
        // TODO: Try to get file extension for type and check that it matches the current extension.
184
        $this->result->mime = $this->type;
185
    }
186
 
187
    return TRUE;
188
  }
189
 
190
  /**
191
   * Get the type of the current file.
192
   *
193
   * @return string
194
   */
195
  public function getType() {
196
    return $this->field->type;
197
  }
198
 
199
  /**
200
   * Get the name of the current file.
201
   *
202
   * @return string
203
   */
204
  public function getName() {
205
    static $name;
206
 
207
    if (empty($name)) {
208
      $name = uniqid($this->field->name . '-');
209
 
210
      $matches = array();
211
      preg_match('/([a-z0-9]{1,})$/i', $_FILES['file']['name'], $matches);
212
      if (isset($matches[0])) {
213
        $name .= '.' . $matches[0];
214
      }
215
    }
216
 
217
    return $name;
218
  }
219
 
220
  /**
221
   * Get result from file processing.
222
   */
223
  public function getResult() {
224
    return json_encode($this->result);
225
  }
226
 
227
  /**
228
   * Print result from file processing.
229
   */
230
  public function printResult() {
231
    $this->result->path = $this->getType() . 's/' . $this->getName() . '#tmp';
232
 
233
    // text/plain is used to support IE
234
    header('Cache-Control: no-cache');
235
    header('Content-Type: text/plain; charset=utf-8');
236
 
237
    print $this->getResult();
238
  }
239
}