phpBB
Statistics
| Revision:

root / branches / phpBB-3_0_0 / phpBB / includes / functions_upload.php

History | View | Annotate | Download (24.4 kB)

1
<?php
2
/**
3
*
4
* @package phpBB3
5
* @version $Id: functions_upload.php 10923 2011-01-10 22:45:09Z git-gate $
6
* @copyright (c) 2005 phpBB Group
7
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
8
*
9
*/
10
11
/**
12
* @ignore
13
*/
14
if (!defined('IN_PHPBB'))
15
{
16
        exit;
17
}
18
19
/**
20
* Responsible for holding all file relevant information, as well as doing file-specific operations.
21
* The {@link fileupload fileupload class} can be used to upload several files, each of them being this object to operate further on.
22
* @package phpBB3
23
*/
24
class filespec
25
{
26
        var $filename = '';
27
        var $realname = '';
28
        var $uploadname = '';
29
        var $mimetype = '';
30
        var $extension = '';
31
        var $filesize = 0;
32
        var $width = 0;
33
        var $height = 0;
34
        var $image_info = array();
35
36
        var $destination_file = '';
37
        var $destination_path = '';
38
39
        var $file_moved = false;
40
        var $init_error = false;
41
        var $local = false;
42
43
        var $error = array();
44
45
        var $upload = '';
46
47
        /**
48
        * File Class
49
        * @access private
50
        */
51
        function filespec($upload_ary, $upload_namespace)
52
        {
53
                if (!isset($upload_ary))
54
                {
55
                        $this->init_error = true;
56
                        return;
57
                }
58
59
                $this->filename = $upload_ary['tmp_name'];
60
                $this->filesize = $upload_ary['size'];
61
                $name = (STRIP) ? stripslashes($upload_ary['name']) : $upload_ary['name'];
62
                $name = trim(utf8_htmlspecialchars(utf8_basename($name)));
63
                $this->realname = $this->uploadname = $name;
64
                $this->mimetype = $upload_ary['type'];
65
66
                // Opera adds the name to the mime type
67
                $this->mimetype        = (strpos($this->mimetype, '; name') !== false) ? str_replace(strstr($this->mimetype, '; name'), '', $this->mimetype) : $this->mimetype;
68
69
                if (!$this->mimetype)
70
                {
71
                        $this->mimetype = 'application/octetstream';
72
                }
73
74
                $this->extension = strtolower($this->get_extension($this->realname));
75
76
                // Try to get real filesize from temporary folder (not always working) ;)
77
                $this->filesize = (@filesize($this->filename)) ? @filesize($this->filename) : $this->filesize;
78
79
                $this->width = $this->height = 0;
80
                $this->file_moved = false;
81
82
                $this->local = (isset($upload_ary['local_mode'])) ? true : false;
83
                $this->upload = $upload_namespace;
84
        }
85
86
        /**
87
        * Cleans destination filename
88
        *
89
        * @param real|unique|unique_ext $mode real creates a realname, filtering some characters, lowering every character. Unique creates an unique filename
90
        * @param string $prefix Prefix applied to filename
91
        * @access public
92
        */
93
        function clean_filename($mode = 'unique', $prefix = '', $user_id = '')
94
        {
95
                if ($this->init_error)
96
                {
97
                        return;
98
                }
99
100
                switch ($mode)
101
                {
102
                        case 'real':
103
                                // Remove every extension from filename (to not let the mime bug being exposed)
104
                                if (strpos($this->realname, '.') !== false)
105
                                {
106
                                        $this->realname = substr($this->realname, 0, strpos($this->realname, '.'));
107
                                }
108
109
                                // Replace any chars which may cause us problems with _
110
                                $bad_chars = array("'", "\\", ' ', '/', ':', '*', '?', '"', '<', '>', '|');
111
112
                                $this->realname = rawurlencode(str_replace($bad_chars, '_', strtolower($this->realname)));
113
                                $this->realname = preg_replace("/%(\w{2})/", '_', $this->realname);
114
115
                                $this->realname = $prefix . $this->realname . '.' . $this->extension;
116
                        break;
117
118
                        case 'unique':
119
                                $this->realname = $prefix . md5(unique_id());
120
                        break;
121
122
                        case 'avatar':
123
                                $this->extension = strtolower($this->extension);
124
                                $this->realname = $prefix . $user_id . '.' . $this->extension;
125
126
                        break;
127
128
                        case 'unique_ext':
129
                        default:
130
                                $this->realname = $prefix . md5(unique_id()) . '.' . $this->extension;
131
                        break;
132
                }
133
        }
134
135
        /**
136
        * Get property from file object
137
        */
138
        function get($property)
139
        {
140
                if ($this->init_error || !isset($this->$property))
141
                {
142
                        return false;
143
                }
144
145
                return $this->$property;
146
        }
147
148
        /**
149
        * Check if file is an image (mimetype)
150
        *
151
        * @return true if it is an image, false if not
152
        */
153
        function is_image()
154
        {
155
                return (strpos($this->mimetype, 'image/') !== false) ? true : false;
156
        }
157
158
        /**
159
        * Check if the file got correctly uploaded
160
        *
161
        * @return true if it is a valid upload, false if not
162
        */
163
        function is_uploaded()
164
        {
165
                if (!$this->local && !is_uploaded_file($this->filename))
166
                {
167
                        return false;
168
                }
169
170
                if ($this->local && !file_exists($this->filename))
171
                {
172
                        return false;
173
                }
174
175
                return true;
176
        }
177
178
        /**
179
        * Remove file
180
        */
181
        function remove()
182
        {
183
                if ($this->file_moved)
184
                {
185
                        @unlink($this->destination_file);
186
                }
187
        }
188
189
        /**
190
        * Get file extension
191
        */
192
        function get_extension($filename)
193
        {
194
                if (strpos($filename, '.') === false)
195
                {
196
                        return '';
197
                }
198
199
                $filename = explode('.', $filename);
200
                return array_pop($filename);
201
        }
202
203
        /**
204
        * Get mimetype. Utilize mime_content_type if the function exist.
205
        * Not used at the moment...
206
        */
207
        function get_mimetype($filename)
208
        {
209
                $mimetype = '';
210
211
                if (function_exists('mime_content_type'))
212
                {
213
                        $mimetype = mime_content_type($filename);
214
                }
215
216
                // Some browsers choke on a mimetype of application/octet-stream
217
                if (!$mimetype || $mimetype == 'application/octet-stream')
218
                {
219
                        $mimetype = 'application/octetstream';
220
                }
221
222
                return $mimetype;
223
        }
224
225
        /**
226
        * Get filesize
227
        */
228
        function get_filesize($filename)
229
        {
230
                return @filesize($filename);
231
        }
232
233
234
        /**
235
        * Check the first 256 bytes for forbidden content
236
        */
237
        function check_content($disallowed_content)
238
        {
239
                if (empty($disallowed_content))
240
                {
241
                        return true;
242
                }
243
244
                $fp = @fopen($this->filename, 'rb');
245
246
                if ($fp !== false)
247
                {
248
                        $ie_mime_relevant = fread($fp, 256);
249
                        fclose($fp);
250
                        foreach ($disallowed_content as $forbidden)
251
                        {
252
                                if (stripos($ie_mime_relevant, '<' . $forbidden) !== false)
253
                                {
254
                                        return false;
255
                                }
256
                        }
257
                }
258
                return true;
259
        }
260
261
        /**
262
        * Move file to destination folder
263
        * The phpbb_root_path variable will be applied to the destination path
264
        *
265
        * @param string $destination_path Destination path, for example $config['avatar_path']
266
        * @param bool $overwrite If set to true, an already existing file will be overwritten
267
        * @param string $chmod Permission mask for chmodding the file after a successful move. The mode entered here reflects the mode defined by {@link phpbb_chmod()}
268
        *
269
        * @access public
270
        */
271
        function move_file($destination, $overwrite = false, $skip_image_check = false, $chmod = false)
272
        {
273
                global $user, $phpbb_root_path;
274
275
                if (sizeof($this->error))
276
                {
277
                        return false;
278
                }
279
280
                $chmod = ($chmod === false) ? CHMOD_READ | CHMOD_WRITE : $chmod;
281
282
                // We need to trust the admin in specifying valid upload directories and an attacker not being able to overwrite it...
283
                $this->destination_path = $phpbb_root_path . $destination;
284
285
                // Check if the destination path exist...
286
                if (!file_exists($this->destination_path))
287
                {
288
                        @unlink($this->filename);
289
                        return false;
290
                }
291
292
                $upload_mode = (@ini_get('open_basedir') || @ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == 'on') ? 'move' : 'copy';
293
                $upload_mode = ($this->local) ? 'local' : $upload_mode;
294
                $this->destination_file = $this->destination_path . '/' . utf8_basename($this->realname);
295
296
                // Check if the file already exist, else there is something wrong...
297
                if (file_exists($this->destination_file) && !$overwrite)
298
                {
299
                        @unlink($this->filename);
300
                }
301
                else
302
                {
303
                        if (file_exists($this->destination_file))
304
                        {
305
                                @unlink($this->destination_file);
306
                        }
307
308
                        switch ($upload_mode)
309
                        {
310
                                case 'copy':
311
312
                                        if (!@copy($this->filename, $this->destination_file))
313
                                        {
314
                                                if (!@move_uploaded_file($this->filename, $this->destination_file))
315
                                                {
316
                                                        $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file);
317
                                                }
318
                                        }
319
320
                                break;
321
322
                                case 'move':
323
324
                                        if (!@move_uploaded_file($this->filename, $this->destination_file))
325
                                        {
326
                                                if (!@copy($this->filename, $this->destination_file))
327
                                                {
328
                                                        $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file);
329
                                                }
330
                                        }
331
332
                                break;
333
334
                                case 'local':
335
336
                                        if (!@copy($this->filename, $this->destination_file))
337
                                        {
338
                                                $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file);
339
                                        }
340
341
                                break;
342
                        }
343
344
                        // Remove temporary filename
345
                        @unlink($this->filename);
346
347
                        if (sizeof($this->error))
348
                        {
349
                                return false;
350
                        }
351
352
                        phpbb_chmod($this->destination_file, $chmod);
353
                }
354
355
                // Try to get real filesize from destination folder
356
                $this->filesize = (@filesize($this->destination_file)) ? @filesize($this->destination_file) : $this->filesize;
357
358
                if ($this->is_image() && !$skip_image_check)
359
                {
360
                        $this->width = $this->height = 0;
361
362
                        if (($this->image_info = @getimagesize($this->destination_file)) !== false)
363
                        {
364
                                $this->width = $this->image_info[0];
365
                                $this->height = $this->image_info[1];
366
367
                                if (!empty($this->image_info['mime']))
368
                                {
369
                                        $this->mimetype = $this->image_info['mime'];
370
                                }
371
372
                                // Check image type
373
                                $types = $this->upload->image_types();
374
375
                                if (!isset($types[$this->image_info[2]]) || !in_array($this->extension, $types[$this->image_info[2]]))
376
                                {
377
                                        if (!isset($types[$this->image_info[2]]))
378
                                        {
379
                                                $this->error[] = sprintf($user->lang['IMAGE_FILETYPE_INVALID'], $this->image_info[2], $this->mimetype);
380
                                        }
381
                                        else
382
                                        {
383
                                                $this->error[] = sprintf($user->lang['IMAGE_FILETYPE_MISMATCH'], $types[$this->image_info[2]][0], $this->extension);
384
                                        }
385
                                }
386
387
                                // Make sure the dimensions match a valid image
388
                                if (empty($this->width) || empty($this->height))
389
                                {
390
                                        $this->error[] = $user->lang['ATTACHED_IMAGE_NOT_IMAGE'];
391
                                }
392
                        }
393
                        else
394
                        {
395
                                $this->error[] = $user->lang['UNABLE_GET_IMAGE_SIZE'];
396
                        }
397
                }
398
399
                $this->file_moved = true;
400
                $this->additional_checks();
401
                unset($this->upload);
402
403
                return true;
404
        }
405
406
        /**
407
        * Performing additional checks
408
        */
409
        function additional_checks()
410
        {
411
                global $user;
412
413
                if (!$this->file_moved)
414
                {
415
                        return false;
416
                }
417
418
                // Filesize is too big or it's 0 if it was larger than the maxsize in the upload form
419
                if ($this->upload->max_filesize && ($this->get('filesize') > $this->upload->max_filesize || $this->filesize == 0))
420
                {
421
                        $max_filesize = get_formatted_filesize($this->upload->max_filesize, false);
422
423
                        $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']);
424
425
                        return false;
426
                }
427
428
                if (!$this->upload->valid_dimensions($this))
429
                {
430
                        $this->error[] = sprintf($user->lang[$this->upload->error_prefix . 'WRONG_SIZE'], $this->upload->min_width, $this->upload->min_height, $this->upload->max_width, $this->upload->max_height, $this->width, $this->height);
431
432
                        return false;
433
                }
434
435
                return true;
436
        }
437
}
438
439
/**
440
* Class for assigning error messages before a real filespec class can be assigned
441
*
442
* @package phpBB3
443
*/
444
class fileerror extends filespec
445
{
446
        function fileerror($error_msg)
447
        {
448
                $this->error[] = $error_msg;
449
        }
450
}
451
452
/**
453
* File upload class
454
* Init class (all parameters optional and able to be set/overwritten separately) - scope is global and valid for all uploads
455
*
456
* @package phpBB3
457
*/
458
class fileupload
459
{
460
        var $allowed_extensions = array();
461
        var $disallowed_content = array('body', 'head', 'html', 'img', 'plaintext', 'a href', 'pre', 'script', 'table', 'title'); 
462
        var $max_filesize = 0;
463
        var $min_width = 0;
464
        var $min_height = 0;
465
        var $max_width = 0;
466
        var $max_height = 0;
467
        var $error_prefix = '';
468
469
        /**
470
        * Init file upload class.
471
        *
472
        * @param string $error_prefix Used error messages will get prefixed by this string
473
        * @param array $allowed_extensions Array of allowed extensions, for example array('jpg', 'jpeg', 'gif', 'png')
474
        * @param int $max_filesize Maximum filesize
475
        * @param int $min_width Minimum image width (only checked for images)
476
        * @param int $min_height Minimum image height (only checked for images)
477
        * @param int $max_width Maximum image width (only checked for images)
478
        * @param int $max_height Maximum image height (only checked for images)
479
        *
480
        */
481
        function fileupload($error_prefix = '', $allowed_extensions = false, $max_filesize = false, $min_width = false, $min_height = false, $max_width = false, $max_height = false, $disallowed_content = false)
482
        {
483
                $this->set_allowed_extensions($allowed_extensions);
484
                $this->set_max_filesize($max_filesize);
485
                $this->set_allowed_dimensions($min_width, $min_height, $max_width, $max_height);
486
                $this->set_error_prefix($error_prefix);
487
                $this->set_disallowed_content($disallowed_content);
488
        }
489
490
        /**
491
        * Reset vars
492
        */
493
        function reset_vars()
494
        {
495
                $this->max_filesize = 0;
496
                $this->min_width = $this->min_height = $this->max_width = $this->max_height = 0;
497
                $this->error_prefix = '';
498
                $this->allowed_extensions = array();
499
                $this->disallowed_content = array();
500
        }
501
502
        /**
503
        * Set allowed extensions
504
        */
505
        function set_allowed_extensions($allowed_extensions)
506
        {
507
                if ($allowed_extensions !== false && is_array($allowed_extensions))
508
                {
509
                        $this->allowed_extensions = $allowed_extensions;
510
                }
511
        }
512
513
        /**
514
        * Set allowed dimensions
515
        */
516
        function set_allowed_dimensions($min_width, $min_height, $max_width, $max_height)
517
        {
518
                $this->min_width = (int) $min_width;
519
                $this->min_height = (int) $min_height;
520
                $this->max_width = (int) $max_width;
521
                $this->max_height = (int) $max_height;
522
        }
523
524
        /**
525
        * Set maximum allowed filesize
526
        */
527
        function set_max_filesize($max_filesize)
528
        {
529
                if ($max_filesize !== false && (int) $max_filesize)
530
                {
531
                        $this->max_filesize = (int) $max_filesize;
532
                }
533
        }
534
535
        /**
536
        * Set disallowed strings
537
        */
538
        function set_disallowed_content($disallowed_content)
539
        {
540
                if ($disallowed_content !== false && is_array($disallowed_content))
541
                {
542
                        $this->disallowed_content = array_diff($disallowed_content, array(''));
543
                }
544
        }
545
546
        /**
547
        * Set error prefix
548
        */
549
        function set_error_prefix($error_prefix)
550
        {
551
                $this->error_prefix = $error_prefix;
552
        }
553
554
        /**
555
        * Form upload method
556
        * Upload file from users harddisk
557
        *
558
        * @param string $form_name Form name assigned to the file input field (if it is an array, the key has to be specified)
559
        * @return object $file Object "filespec" is returned, all further operations can be done with this object
560
        * @access public
561
        */
562
        function form_upload($form_name)
563
        {
564
                global $user;
565
566
                unset($_FILES[$form_name]['local_mode']);
567
                $file = new filespec($_FILES[$form_name], $this);
568
569
                if ($file->init_error)
570
                {
571
                        $file->error[] = '';
572
                        return $file;
573
                }
574
575
                // Error array filled?
576
                if (isset($_FILES[$form_name]['error']))
577
                {
578
                        $error = $this->assign_internal_error($_FILES[$form_name]['error']);
579
580
                        if ($error !== false)
581
                        {
582
                                $file->error[] = $error;
583
                                return $file;
584
                        }
585
                }
586
587
                // Check if empty file got uploaded (not catched by is_uploaded_file)
588
                if (isset($_FILES[$form_name]['size']) && $_FILES[$form_name]['size'] == 0)
589
                {
590
                        $file->error[] = $user->lang[$this->error_prefix . 'EMPTY_FILEUPLOAD'];
591
                        return $file;
592
                }
593
594
                // PHP Upload filesize exceeded
595
                if ($file->get('filename') == 'none')
596
                {
597
                        $max_filesize = @ini_get('upload_max_filesize');
598
                        $unit = 'MB';
599
600
                        if (!empty($max_filesize))
601
                        {
602
                                $unit = strtolower(substr($max_filesize, -1, 1));
603
                                $max_filesize = (int) $max_filesize;
604
605
                                $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB');
606
                        }
607
608
                        $file->error[] = (empty($max_filesize)) ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], $max_filesize, $user->lang[$unit]);
609
                        return $file;
610
                }
611
612
                // Not correctly uploaded
613
                if (!$file->is_uploaded())
614
                {
615
                        $file->error[] = $user->lang[$this->error_prefix . 'NOT_UPLOADED'];
616
                        return $file;
617
                }
618
619
                $this->common_checks($file);
620
621
                return $file;
622
        }
623
624
        /**
625
        * Move file from another location to phpBB
626
        */
627
        function local_upload($source_file, $filedata = false)
628
        {
629
                global $user;
630
631
                $form_name = 'local';
632
633
                $_FILES[$form_name]['local_mode'] = true;
634
                $_FILES[$form_name]['tmp_name'] = $source_file;
635
636
                if ($filedata === false)
637
                {
638
                        $_FILES[$form_name]['name'] = utf8_basename($source_file);
639
                        $_FILES[$form_name]['size'] = 0;
640
                        $mimetype = '';
641
642
                        if (function_exists('mime_content_type'))
643
                        {
644
                                $mimetype = mime_content_type($source_file);
645
                        }
646
647
                        // Some browsers choke on a mimetype of application/octet-stream
648
                        if (!$mimetype || $mimetype == 'application/octet-stream')
649
                        {
650
                                $mimetype = 'application/octetstream';
651
                        }
652
653
                        $_FILES[$form_name]['type'] = $mimetype;
654
                }
655
                else
656
                {
657
                        $_FILES[$form_name]['name'] = $filedata['realname'];
658
                        $_FILES[$form_name]['size'] = $filedata['size'];
659
                        $_FILES[$form_name]['type'] = $filedata['type'];
660
                }
661
662
                $file = new filespec($_FILES[$form_name], $this);
663
664
                if ($file->init_error)
665
                {
666
                        $file->error[] = '';
667
                        return $file;
668
                }
669
670
                if (isset($_FILES[$form_name]['error']))
671
                {
672
                        $error = $this->assign_internal_error($_FILES[$form_name]['error']);
673
674
                        if ($error !== false)
675
                        {
676
                                $file->error[] = $error;
677
                                return $file;
678
                        }
679
                }
680
681
                // PHP Upload filesize exceeded
682
                if ($file->get('filename') == 'none')
683
                {
684
                        $max_filesize = @ini_get('upload_max_filesize');
685
                        $unit = 'MB';
686
687
                        if (!empty($max_filesize))
688
                        {
689
                                $unit = strtolower(substr($max_filesize, -1, 1));
690
                                $max_filesize = (int) $max_filesize;
691
692
                                $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB');
693
                        }
694
695
                        $file->error[] = (empty($max_filesize)) ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], $max_filesize, $user->lang[$unit]);
696
                        return $file;
697
                }
698
699
                // Not correctly uploaded
700
                if (!$file->is_uploaded())
701
                {
702
                        $file->error[] = $user->lang[$this->error_prefix . 'NOT_UPLOADED'];
703
                        return $file;
704
                }
705
706
                $this->common_checks($file);
707
708
                return $file;
709
        }
710
711
        /**
712
        * Remote upload method
713
        * Uploads file from given url
714
        *
715
        * @param string $upload_url URL pointing to file to upload, for example http://www.foobar.com/example.gif
716
        * @return object $file Object "filespec" is returned, all further operations can be done with this object
717
        * @access public
718
        */
719
        function remote_upload($upload_url)
720
        {
721
                global $user, $phpbb_root_path;
722
723
                $upload_ary = array();
724
                $upload_ary['local_mode'] = true;
725
726
                if (!preg_match('#^(https?://).*?\.(' . implode('|', $this->allowed_extensions) . ')$#i', $upload_url, $match))
727
                {
728
                        $file = new fileerror($user->lang[$this->error_prefix . 'URL_INVALID']);
729
                        return $file;
730
                }
731
732
                if (empty($match[2]))
733
                {
734
                        $file = new fileerror($user->lang[$this->error_prefix . 'URL_INVALID']);
735
                        return $file;
736
                }
737
738
                $url = parse_url($upload_url);
739
740
                $host = $url['host'];
741
                $path = $url['path'];
742
                $port = (!empty($url['port'])) ? (int) $url['port'] : 80;
743
744
                $upload_ary['type'] = 'application/octet-stream';
745
746
                $url['path'] = explode('.', $url['path']);
747
                $ext = array_pop($url['path']);
748
749
                $url['path'] = implode('', $url['path']);
750
                $upload_ary['name'] = utf8_basename($url['path']) . (($ext) ? '.' . $ext : '');
751
                $filename = $url['path'];
752
                $filesize = 0;
753
754
                $errno = 0;
755
                $errstr = '';
756
757
                if (!($fsock = @fsockopen($host, $port, $errno, $errstr)))
758
                {
759
                        $file = new fileerror($user->lang[$this->error_prefix . 'NOT_UPLOADED']);
760
                        return $file;
761
                }
762
763
                // Make sure $path not beginning with /
764
                if (strpos($path, '/') === 0)
765
                {
766
                        $path = substr($path, 1);
767
                }
768
769
                fputs($fsock, 'GET /' . $path . " HTTP/1.1\r\n");
770
                fputs($fsock, "HOST: " . $host . "\r\n");
771
                fputs($fsock, "Connection: close\r\n\r\n");
772
773
                $get_info = false;
774
                $data = '';
775
                while (!@feof($fsock))
776
                {
777
                        if ($get_info)
778
                        {
779
                                $block = @fread($fsock, 1024);
780
                                $filesize += strlen($block);
781
782
                                if ($this->max_filesize && $filesize > $this->max_filesize)
783
                                {
784
                                        $max_filesize = get_formatted_filesize($this->max_filesize, false);
785
786
                                        $file = new fileerror(sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']));
787
                                        return $file;
788
                                }
789
790
                                $data .= $block;
791
                        }
792
                        else
793
                        {
794
                                $line = @fgets($fsock, 1024);
795
796
                                if ($line == "\r\n")
797
                                {
798
                                        $get_info = true;
799
                                }
800
                                else
801
                                {
802
                                        if (stripos($line, 'content-type: ') !== false)
803
                                        {
804
                                                $upload_ary['type'] = rtrim(str_replace('content-type: ', '', strtolower($line)));
805
                                        }
806
                                        else if ($this->max_filesize && stripos($line, 'content-length: ') !== false)
807
                                        {
808
                                                $length = (int) str_replace('content-length: ', '', strtolower($line));
809
810
                                                if ($length && $length > $this->max_filesize)
811
                                                {
812
                                                        $max_filesize = get_formatted_filesize($this->max_filesize, false);
813
814
                                                        $file = new fileerror(sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']));
815
                                                        return $file;
816
                                                }
817
                                        }
818
                                        else if (stripos($line, '404 not found') !== false)
819
                                        {
820
                                                $file = new fileerror($user->lang[$this->error_prefix . 'URL_NOT_FOUND']);
821
                                                return $file;
822
                                        }
823
                                }
824
                        }
825
                }
826
                @fclose($fsock);
827
828
                if (empty($data))
829
                {
830
                        $file = new fileerror($user->lang[$this->error_prefix . 'EMPTY_REMOTE_DATA']);
831
                        return $file;
832
                }
833
834
                $tmp_path = (!@ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == 'off') ? false : $phpbb_root_path . 'cache';
835
                $filename = tempnam($tmp_path, unique_id() . '-');
836
837
                if (!($fp = @fopen($filename, 'wb')))
838
                {
839
                        $file = new fileerror($user->lang[$this->error_prefix . 'NOT_UPLOADED']);
840
                        return $file;
841
                }
842
843
                $upload_ary['size'] = fwrite($fp, $data);
844
                fclose($fp);
845
                unset($data);
846
847
                $upload_ary['tmp_name'] = $filename;
848
849
                $file = new filespec($upload_ary, $this);
850
                $this->common_checks($file);
851
852
                return $file;
853
        }
854
855
        /**
856
        * Assign internal error
857
        * @access private
858
        */
859
        function assign_internal_error($errorcode)
860
        {
861
                global $user;
862
863
                switch ($errorcode)
864
                {
865
                        case 1:
866
                                $max_filesize = @ini_get('upload_max_filesize');
867
                                $unit = 'MB';
868
869
                                if (!empty($max_filesize))
870
                                {
871
                                        $unit = strtolower(substr($max_filesize, -1, 1));
872
                                        $max_filesize = (int) $max_filesize;
873
874
                                        $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB');
875
                                }
876
877
                                $error = (empty($max_filesize)) ? $user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : sprintf($user->lang[$this->error_prefix . 'PHP_SIZE_OVERRUN'], $max_filesize, $user->lang[$unit]);
878
                        break;
879
880
                        case 2:
881
                                $max_filesize = get_formatted_filesize($this->max_filesize, false);
882
883
                                $error = sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']);
884
                        break;
885
886
                        case 3:
887
                                $error = $user->lang[$this->error_prefix . 'PARTIAL_UPLOAD'];
888
                        break;
889
890
                        case 4:
891
                                $error = $user->lang[$this->error_prefix . 'NOT_UPLOADED'];
892
                        break;
893
894
                        case 6:
895
                                $error = 'Temporary folder could not be found. Please check your PHP installation.';
896
                        break;
897
898
                        default:
899
                                $error = false;
900
                        break;
901
                }
902
903
                return $error;
904
        }
905
906
        /**
907
        * Perform common checks
908
        */
909
        function common_checks(&$file)
910
        {
911
                global $user;
912
913
                // Filesize is too big or it's 0 if it was larger than the maxsize in the upload form
914
                if ($this->max_filesize && ($file->get('filesize') > $this->max_filesize || $file->get('filesize') == 0))
915
                {
916
                        $max_filesize = get_formatted_filesize($this->max_filesize, false);
917
918
                        $file->error[] = sprintf($user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize['value'], $max_filesize['unit']);
919
                }
920
921
                // check Filename
922
                if (preg_match("#[\\/:*?\"<>|]#i", $file->get('realname')))
923
                {
924
                        $file->error[] = sprintf($user->lang[$this->error_prefix . 'INVALID_FILENAME'], $file->get('realname'));
925
                }
926
927
                // Invalid Extension
928
                if (!$this->valid_extension($file))
929
                {
930
                        $file->error[] = sprintf($user->lang[$this->error_prefix . 'DISALLOWED_EXTENSION'], $file->get('extension'));
931
                }
932
933
                // MIME Sniffing
934
                if (!$this->valid_content($file))
935
                {
936
                        $file->error[] = sprintf($user->lang[$this->error_prefix . 'DISALLOWED_CONTENT']);
937
                }
938
        }
939
940
        /**
941
        * Check for allowed extension
942
        */
943
        function valid_extension(&$file)
944
        {
945
                return (in_array($file->get('extension'), $this->allowed_extensions)) ? true : false;
946
        }
947
948
        /**
949
        * Check for allowed dimension
950
        */
951
        function valid_dimensions(&$file)
952
        {
953
                if (!$this->max_width && !$this->max_height && !$this->min_width && !$this->min_height)
954
                {
955
                        return true;
956
                }
957
958
                if (($file->get('width') > $this->max_width && $this->max_width) ||
959
                        ($file->get('height') > $this->max_height && $this->max_height) ||
960
                        ($file->get('width') < $this->min_width && $this->min_width) ||
961
                        ($file->get('height') < $this->min_height && $this->min_height))
962
                {
963
                        return false;
964
                }
965
966
                return true;
967
        }
968
969
        /**
970
        * Check if form upload is valid
971
        */
972
        function is_valid($form_name)
973
        {
974
                return (isset($_FILES[$form_name]) && $_FILES[$form_name]['name'] != 'none') ? true : false;
975
        }
976
977
978
        /**
979
        * Check for allowed extension
980
        */
981
        function valid_content(&$file)
982
        {
983
                return ($file->check_content($this->disallowed_content));
984
        }
985
986
        /**
987
        * Return image type/extension mapping
988
        */
989
        function image_types()
990
        {
991
                return array(
992
                        1 => array('gif'),
993
                        2 => array('jpg', 'jpeg'),
994
                        3 => array('png'),
995
                        4 => array('swf'),
996
                        5 => array('psd'),
997
                        6 => array('bmp'),
998
                        7 => array('tif', 'tiff'),
999
                        8 => array('tif', 'tiff'),
1000
                        9 => array('jpg', 'jpeg'),
1001
                        10 => array('jpg', 'jpeg'),
1002
                        11 => array('jpg', 'jpeg'),
1003
                        12 => array('jpg', 'jpeg'),
1004
                        13 => array('swc'),
1005
                        14 => array('iff'),
1006
                        15 => array('wbmp'),
1007
                        16 => array('xbm'),
1008
                );
1009
        }
1010
}
1011
1012
?>