Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

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