Passed
Push — master ( 2ffb1a...5c126f )
by Julito
11:51
created

create_unexisting_directory()   B

Complexity

Conditions 9
Paths 25

Size

Total Lines 149
Code Lines 62

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 9
eloc 62
nc 25
nop 11
dl 0
loc 149
rs 7.2735
c 3
b 0
f 0

How to fix   Long Method    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CoreBundle\Framework\Container;
5
use Chamilo\CourseBundle\Entity\CDocument;
6
7
/**
8
 * FILE UPLOAD LIBRARY.
9
 *
10
 * This is the file upload library for Chamilo.
11
 * Include/require it in your code to use its functionality.
12
 *
13
 * @package chamilo.library
14
 *
15
 * @todo test and reorganise
16
 */
17
18
/**
19
 * Changes the file name extension from .php to .phps
20
 * Useful for securing a site.
21
 *
22
 * @author Hugues Peeters <[email protected]>
23
 *
24
 * @param string $file_name Name of a file
25
 *
26
 * @return string the filename phps'ized
27
 */
28
function php2phps($file_name)
29
{
30
    return preg_replace('/\.(php.?|phtml.?)(\.){0,1}.*$/i', '.phps', $file_name);
31
}
32
33
/**
34
 * Renames .htaccess & .HTACCESS to htaccess.txt.
35
 *
36
 * @param string $filename
37
 *
38
 * @return string
39
 */
40
function htaccess2txt($filename)
41
{
42
    return str_replace(['.htaccess', '.HTACCESS'], ['htaccess.txt', 'htaccess.txt'], $filename);
43
}
44
45
/**
46
 * This function executes our safety precautions
47
 * more functions can be added.
48
 *
49
 * @param string $filename
50
 *
51
 * @return string
52
 *
53
 * @see php2phps()
54
 * @see htaccess2txt()
55
 */
56
function disable_dangerous_file($filename)
57
{
58
    return htaccess2txt(php2phps($filename));
59
}
60
61
/**
62
 * Returns the name without extension, used for the title.
63
 *
64
 * @param string $name
65
 *
66
 * @return name without the extension
67
 */
68
function get_document_title($name)
69
{
70
    // If they upload .htaccess...
71
    $name = disable_dangerous_file($name);
72
    $ext = substr(strrchr($name, '.'), 0);
73
74
    return substr($name, 0, strlen($name) - strlen(strstr($name, $ext)));
75
}
76
77
/**
78
 * This function checks if the upload succeeded.
79
 *
80
 * @param array $uploaded_file ($_FILES)
81
 *
82
 * @return true if upload succeeded
83
 */
84
function process_uploaded_file($uploaded_file, $show_output = true)
85
{
86
    // Checking the error code sent with the file upload.
87
    if (isset($uploaded_file['error'])) {
88
        switch ($uploaded_file['error']) {
89
            case 1:
90
                // The uploaded file exceeds the upload_max_filesize directive in php.ini.
91
                if ($show_output) {
92
                    Display::addFlash(
93
                        Display::return_message(
94
                            get_lang('UplExceedMaxServerUpload').ini_get('upload_max_filesize'),
95
                            'error'
96
                        )
97
                    );
98
                }
99
100
                return false;
101
            case 2:
102
                // The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.
103
                // Not used at the moment, but could be handy if we want to limit the size of an upload
104
                // (e.g. image upload in html editor).
105
                $max_file_size = intval($_POST['MAX_FILE_SIZE']);
106
                if ($show_output) {
107
                    Display::addFlash(
108
                        Display::return_message(
109
                            get_lang('UplExceedMaxPostSize').format_file_size($max_file_size),
110
                            'error'
111
                        )
112
                    );
113
                }
114
115
                return false;
116
            case 3:
117
                // The uploaded file was only partially uploaded.
118
                if ($show_output) {
119
                    Display::addFlash(
120
                        Display::return_message(
121
                            get_lang('UplPartialUpload').' '.get_lang('PleaseTryAgain'),
122
                            'error'
123
                        )
124
                    );
125
                }
126
127
                return false;
128
            case 4:
129
                // No file was uploaded.
130
                if ($show_output) {
131
                    Display::addFlash(
132
                        Display::return_message(
133
                            get_lang('UplNoFileUploaded').' '.get_lang('UplSelectFileFirst'),
134
                            'error'
135
                        )
136
                    );
137
                }
138
139
                return false;
140
        }
141
    }
142
143
    if (!file_exists($uploaded_file['tmp_name'])) {
144
        // No file was uploaded.
145
        if ($show_output) {
146
            Display::addFlash(Display::return_message(get_lang('UplUploadFailed'), 'error'));
147
        }
148
149
        return false;
150
    }
151
152
    if (file_exists($uploaded_file['tmp_name'])) {
153
        $filesize = filesize($uploaded_file['tmp_name']);
154
        if (empty($filesize)) {
155
            // No file was uploaded.
156
            if ($show_output) {
157
                Display::addFlash(
158
                    Display::return_message(
159
                        get_lang('UplUploadFailedSizeIsZero'),
160
                        'error'
161
                    )
162
                );
163
            }
164
165
            return false;
166
        }
167
    }
168
169
    $course_id = api_get_course_id();
170
171
    //Checking course quota if we are in a course
172
    if (!empty($course_id)) {
173
        $max_filled_space = DocumentManager::get_course_quota();
174
        // Check if there is enough space to save the file
175
        if (!DocumentManager::enough_space($uploaded_file['size'], $max_filled_space)) {
176
            if ($show_output) {
177
                Display::addFlash(
178
                    Display::return_message(
179
                        get_lang('UplNotEnoughSpace'),
180
                        'error'
181
                    )
182
                );
183
            }
184
185
            return false;
186
        }
187
    }
188
189
    // case 0: default: We assume there is no error, the file uploaded with success.
190
    return true;
191
}
192
193
/**
194
 * This function does the save-work for the documents.
195
 * It handles the uploaded file and adds the properties to the database
196
 * If unzip=1 and the file is a zipfile, it is extracted
197
 * If we decide to save ALL kinds of documents in one database,
198
 * we could extend this with a $type='document', 'scormdocument',...
199
 *
200
 * @param array  $courseInfo
201
 * @param array  $uploadedFile            ($_FILES)
202
 *                                        array(
203
 *                                        'name' => 'picture.jpg',
204
 *                                        'tmp_name' => '...', // absolute path
205
 *                                        );
206
 * @param string $documentDir             Example: /var/www/chamilo/courses/ABC/document
207
 * @param string $uploadPath              Example: /folder1/folder2/
208
 * @param int    $userId
209
 * @param int    $groupId                 group.id
210
 * @param int    $toUserId                User ID, or NULL for everybody
211
 * @param int    $unzip                   1/0
212
 * @param string $whatIfFileExists        overwrite, rename or warn if exists (default)
213
 * @param bool   $output                  optional output parameter
214
 * @param bool   $onlyUploadFile
215
 * @param string $comment
216
 * @param int    $sessionId
217
 * @param bool   $treat_spaces_as_hyphens
218
 * @param string $uploadKey
219
 * @param int    $parentId
220
 *
221
 * So far only use for unzip_uploaded_document function.
222
 * If no output wanted on success, set to false.
223
 *
224
 * @return CDocument|false
225
 */
226
function handle_uploaded_document(
227
    $courseInfo,
228
    $uploadedFile,
229
    $documentDir,
230
    $uploadPath,
231
    $userId,
232
    $groupId = 0,
233
    $toUserId = null,
234
    $unzip = 0,
235
    $whatIfFileExists = '',
236
    $output = true,
237
    $onlyUploadFile = false,
238
    $comment = null,
239
    $sessionId = null,
240
    $treat_spaces_as_hyphens = true,
241
    $uploadKey = '',
242
    $parentId = 0
243
) {
244
    if (!$userId) {
245
        return false;
246
    }
247
248
    $userInfo = api_get_user_info();
249
    $uploadedFile['name'] = stripslashes($uploadedFile['name']);
250
    // Add extension to files without one (if possible)
251
    $uploadedFile['name'] = add_ext_on_mime($uploadedFile['name'], $uploadedFile['type']);
252
    $sessionId = (int) $sessionId;
253
    if (empty($sessionId)) {
254
        $sessionId = api_get_session_id();
255
    }
256
257
    $groupInfo = [];
258
    if (!empty($groupId)) {
259
        $groupInfo = GroupManager::get_group_properties($groupId);
260
    }
261
262
    // Just in case process_uploaded_file is not called
263
    $maxSpace = DocumentManager::get_course_quota();
264
265
    // Check if there is enough space to save the file
266
    if (!DocumentManager::enough_space($uploadedFile['size'], $maxSpace)) {
267
        if ($output) {
268
            Display::addFlash(Display::return_message(get_lang('UplNotEnoughSpace'), 'error'));
269
        }
270
271
        return false;
272
    }
273
274
    // If the want to unzip, check if the file has a .zip (or ZIP,Zip,ZiP,...) extension
275
    if ($unzip == 1 && preg_match('/.zip$/', strtolower($uploadedFile['name']))) {
276
        return unzip_uploaded_document(
277
            $courseInfo,
278
            $userInfo,
279
            $uploadedFile,
280
            $uploadPath,
281
            $documentDir,
282
            $maxSpace,
283
            $sessionId,
284
            $groupId,
285
            $output,
286
            $onlyUploadFile,
287
            $whatIfFileExists
288
        );
289
    } elseif ($unzip == 1 && !preg_match('/.zip$/', strtolower($uploadedFile['name']))) {
290
        // We can only unzip ZIP files (no gz, tar,...)
291
        if ($output) {
292
            Display::addFlash(
293
                Display::return_message(get_lang('UplNotAZip')." ".get_lang('PleaseTryAgain'), 'error')
294
            );
295
        }
296
297
        return false;
298
    } else {
299
        // Clean up the name, only ASCII characters should stay. (and strict)
300
        $cleanName = api_replace_dangerous_char($uploadedFile['name'], $treat_spaces_as_hyphens);
301
302
        // No "dangerous" files
303
        $cleanName = disable_dangerous_file($cleanName);
304
305
        // Checking file extension
306
        if (!filter_extension($cleanName)) {
307
            if ($output) {
308
                Display::addFlash(
309
                    Display::return_message(get_lang('UplUnableToSaveFileFilteredExtension'), 'error')
310
                );
311
            }
312
313
            return false;
314
        } else {
315
            // If the upload path differs from / (= root) it will need a slash at the end
316
            if ($uploadPath != '/') {
317
                $uploadPath = $uploadPath.'/';
318
            }
319
320
            // Full path to where we want to store the file with trailing slash
321
            $whereToSave = $documentDir.$uploadPath;
322
323
            // At least if the directory doesn't exist, tell so
324
            /*if (!is_dir($whereToSave)) {
325
                if (!mkdir($whereToSave, api_get_permissions_for_new_directories())) {
326
                    if ($output) {
327
                        Display::addFlash(
328
                            Display::return_message(
329
                                get_lang('DestDirectoryDoesntExist').' ('.$uploadPath.')',
330
                                'error'
331
                            )
332
                        );
333
                    }
334
335
                    return false;
336
                }
337
            }*/
338
339
            // Just upload the file "as is"
340
            if ($onlyUploadFile) {
341
                $errorResult = moveUploadedFile($uploadedFile, $whereToSave.$cleanName);
342
                if ($errorResult) {
343
                    return $whereToSave.$cleanName;
344
                } else {
345
                    return $errorResult;
346
                }
347
            }
348
349
            /*
350
                Based in the clean name we generate a new filesystem name
351
                Using the session_id and group_id if values are not empty
352
            */
353
            $fileSystemName = DocumentManager::fixDocumentName(
354
                $cleanName,
355
                'file',
356
                $courseInfo,
357
                $sessionId,
358
                $groupId
359
            );
360
361
            // Name of the document without the extension (for the title)
362
            $documentTitle = get_document_title($uploadedFile['name']);
363
364
            // Size of the uploaded file (in bytes)
365
            $fileSize = $uploadedFile['size'];
366
367
            // File permissions
368
            $filePermissions = api_get_permissions_for_new_files();
369
370
            // Example: /var/www/chamilo/courses/xxx/document/folder/picture.jpg
371
            $fullPath = $whereToSave.$fileSystemName;
372
373
            // Example: /folder/picture.jpg
374
            $filePath = $uploadPath.$fileSystemName;
375
376
            $docId = DocumentManager::get_document_id(
377
                $courseInfo,
378
                $filePath,
379
                $sessionId
380
            );
381
382
            // What to do if the target file exists
383
            switch ($whatIfFileExists) {
384
                // Overwrite the file if it exists
385
                case 'overwrite':
386
                    // Check if the target file exists, so we can give another message
387
                    $fileExists = file_exists($fullPath);
388
389
                    if (moveUploadedFile($uploadedFile, $fullPath)) {
390
                        chmod($fullPath, $filePermissions);
391
392
                        if ($fileExists && $docId) {
393
                            // UPDATE DATABASE
394
                            $documentId = DocumentManager::get_document_id(
395
                                $courseInfo,
396
                                $filePath
397
                            );
398
                            if (is_numeric($documentId)) {
399
                                // Update file size
400
                                update_existing_document(
401
                                    $courseInfo,
402
                                    $documentId,
403
                                    $uploadedFile['size']
404
                                );
405
406
                                // Update document item_property
407
                                api_item_property_update(
408
                                    $courseInfo,
409
                                    TOOL_DOCUMENT,
410
                                    $documentId,
411
                                    'DocumentUpdated',
412
                                    $userId,
413
                                    $groupInfo,
414
                                    $toUserId,
415
                                    null,
416
                                    null,
417
                                    $sessionId
418
                                );
419
420
                                // Redo visibility
421
                                api_set_default_visibility(
422
                                    $documentId,
423
                                    TOOL_DOCUMENT,
424
                                    null,
425
                                    $courseInfo
426
                                );
427
                            } else {
428
                                // There might be cases where the file exists on disk but there is no registration of
429
                                // that in the database
430
                                // In this case, and if we are in overwrite mode, overwrite and create the db record
431
                                $documentId = DocumentManager::addDocument(
432
                                    $courseInfo,
433
                                    $filePath,
434
                                    'file',
435
                                    $fileSize,
436
                                    $documentTitle,
437
                                    $comment,
438
                                    0,
439
                                    true,
440
                                    $groupId,
441
                                    $sessionId
442
                                );
443
444
                                if ($documentId) {
445
                                    // Put the document in item_property update
446
                                    api_item_property_update(
447
                                        $courseInfo,
448
                                        TOOL_DOCUMENT,
449
                                        $documentId,
450
                                        'DocumentAdded',
451
                                        $userId,
452
                                        $groupInfo,
453
                                        $toUserId,
454
                                        null,
455
                                        null,
456
                                        $sessionId
457
                                    );
458
459
                                    // Redo visibility
460
                                    api_set_default_visibility(
461
                                        $documentId,
462
                                        TOOL_DOCUMENT,
463
                                        null,
464
                                        $courseInfo
465
                                    );
466
                                }
467
                            }
468
469
                            // If the file is in a folder, we need to update all parent folders
470
                            item_property_update_on_folder($courseInfo, $uploadPath, $userId);
471
472
                            // Display success message with extra info to user
473
                            if ($output) {
474
                                Display::addFlash(
475
                                    Display::return_message(
476
                                        get_lang('UplUploadSucceeded').'<br /> '.
477
                                        $documentTitle.' '.get_lang('UplFileOverwritten'),
478
                                        'confirmation',
479
                                        false
480
                                    )
481
                                );
482
                            }
483
484
                            return $filePath;
485
                        } else {
486
                            // Put the document data in the database
487
                            $documentId = DocumentManager::addDocument(
488
                                $courseInfo,
489
                                $filePath,
490
                                'file',
491
                                $fileSize,
492
                                $documentTitle,
493
                                $comment,
494
                                0,
495
                                true,
496
                                $groupId,
497
                                $sessionId
498
                            );
499
500
                            if ($documentId) {
501
                                // Put the document in item_property update
502
                                api_item_property_update(
503
                                    $courseInfo,
504
                                    TOOL_DOCUMENT,
505
                                    $documentId,
506
                                    'DocumentAdded',
507
                                    $userId,
508
                                    $groupInfo,
509
                                    $toUserId,
510
                                    null,
511
                                    null,
512
                                    $sessionId
513
                                );
514
515
                                // Redo visibility
516
                                api_set_default_visibility($documentId, TOOL_DOCUMENT, null, $courseInfo);
517
                            }
518
519
                            // If the file is in a folder, we need to update all parent folders
520
                            item_property_update_on_folder($courseInfo, $uploadPath, $userId);
521
522
                            // Display success message to user
523
                            if ($output) {
524
                                Display::addFlash(
525
                                    Display::return_message(
526
                                        get_lang('UplUploadSucceeded').'<br /> '.$documentTitle,
527
                                        'confirmation',
528
                                        false
529
                                    )
530
                                );
531
                            }
532
533
                            return $filePath;
534
                        }
535
                    } else {
536
                        if ($output) {
537
                            Display::addFlash(
538
                                Display::return_message(
539
                                    get_lang('UplUnableToSaveFile'),
540
                                    'error',
541
                                    false
542
                                )
543
                            );
544
                        }
545
546
                        return false;
547
                    }
548
                    break;
549
                case 'rename':
550
                    // Rename the file if it exists
551
                    $cleanName = DocumentManager::getUniqueFileName(
552
                        $uploadPath,
553
                        $cleanName,
554
                        $courseInfo,
555
                        $sessionId,
556
                        $groupId
557
                    );
558
559
                    $fileSystemName = DocumentManager::fixDocumentName(
560
                        $cleanName,
561
                        'file',
562
                        $courseInfo,
563
                        $sessionId,
564
                        $groupId
565
                    );
566
567
                    $documentTitle = disable_dangerous_file($cleanName);
568
                    $filePath = $uploadPath.$fileSystemName;
569
570
                    $request = Container::getRequest();
571
                    $content = $request->files->get($uploadKey);
572
                    if (is_array($content)) {
573
                        $content = $content[0];
574
                    }
575
576
                    //if (moveUploadedFile($uploadedFile, $fullPath)) {
577
                    if (true) {
578
                        ///chmod($fullPath, $filePermissions);
579
                        // Put the document data in the database
580
                        $document = DocumentManager::addDocument(
581
                            $courseInfo,
582
                            $filePath,
583
                            'file',
584
                            $fileSize,
585
                            $documentTitle,
586
                            $comment, // comment
587
                            0, // read only
588
                            true, // save visibility
589
                            $groupId,
590
                            $sessionId,
591
                            0,
592
                            true,
593
                            $content,
594
                            $parentId
595
                        );
596
597
                        // Display success message to user
598
                        if ($output) {
599
                            Display::addFlash(
600
                                Display::return_message(
601
                                    get_lang('UplUploadSucceeded').'<br />'.
602
                                    get_lang('UplFileSavedAs').' '.$document->getTitle(),
603
                                    'success',
604
                                    false
605
                                )
606
                            );
607
                        }
608
609
                        return $document;
610
                    } else {
611
                        /*if ($output) {
612
                            Display::addFlash(
613
                                Display::return_message(
614
                                    get_lang('UplUnableToSaveFile'),
615
                                    'error',
616
                                    false
617
                                )
618
                            );
619
                        }
620
621
                        return false;*/
622
                    }
623
                    break;
624
                case 'nothing':
625
                    $fileExists = file_exists($fullPath);
626
                    if ($fileExists) {
627
                        if ($output) {
628
                            Display::addFlash(
629
                                Display::return_message(
630
                                    $uploadPath.$cleanName.' '.get_lang('UplAlreadyExists'),
631
                                    'warning',
632
                                    false
633
                                )
634
                            );
635
                        }
636
                        break;
637
                    }
638
                    // no break
639
                default:
640
                    // Only save the file if it doesn't exist or warn user if it does exist
641
                    if (file_exists($fullPath) && $docId) {
642
                        if ($output) {
643
                            Display::addFlash(
644
                                Display::return_message($cleanName.' '.get_lang('UplAlreadyExists'), 'warning', false)
645
                            );
646
                        }
647
                    } else {
648
                        if (moveUploadedFile($uploadedFile, $fullPath)) {
649
                            //chmod($fullPath, $filePermissions);
650
651
                            // Put the document data in the database
652
                            $documentId = DocumentManager::addDocument(
653
                                $courseInfo,
654
                                $filePath,
655
                                'file',
656
                                $fileSize,
657
                                $documentTitle,
658
                                $comment,
659
                                0,
660
                                true,
661
                                $groupId,
662
                                $sessionId
663
                            );
664
665
                            if ($documentId) {
666
                                // Update document item_property
667
                                api_item_property_update(
668
                                    $courseInfo,
669
                                    TOOL_DOCUMENT,
670
                                    $documentId,
671
                                    'DocumentAdded',
672
                                    $userId,
673
                                    $groupInfo,
674
                                    $toUserId,
675
                                    null,
676
                                    null,
677
                                    $sessionId
678
                                );
679
                                // Redo visibility
680
                                api_set_default_visibility($documentId, TOOL_DOCUMENT, null, $courseInfo);
681
                            }
682
683
                            // If the file is in a folder, we need to update all parent folders
684
                            item_property_update_on_folder(
685
                                $courseInfo,
686
                                $uploadPath,
687
                                $userId
688
                            );
689
690
                            // Display success message to user
691
                            if ($output) {
692
                                Display::addFlash(
693
                                    Display::return_message(
694
                                        get_lang('UplUploadSucceeded').'<br /> '.$documentTitle,
695
                                        'confirm',
696
                                        false
697
                                    )
698
                                );
699
                            }
700
701
                            return $filePath;
702
                        } else {
703
                            if ($output) {
704
                                Display::addFlash(
705
                                    Display::return_message(
706
                                        get_lang('UplUnableToSaveFile'),
707
                                        'error',
708
                                        false
709
                                    )
710
                                );
711
                            }
712
713
                            return false;
714
                        }
715
                    }
716
                    break;
717
            }
718
        }
719
    }
720
}
721
722
/**
723
 * @param string $file
724
 * @param string $storePath
725
 *
726
 * @return bool
727
 */
728
function moveUploadedFile($file, $storePath)
729
{
730
    $handleFromFile = isset($file['from_file']) && $file['from_file'] ? true : false;
731
    $moveFile = isset($file['move_file']) && $file['move_file'] ? true : false;
732
    if ($moveFile) {
733
        copy($file['tmp_name'], $storePath);
734
    }
735
    if ($handleFromFile) {
736
        return file_exists($file['tmp_name']);
737
    } else {
738
        return move_uploaded_file($file['tmp_name'], $storePath);
739
    }
740
}
741
742
/**
743
 * Checks if there is enough place to add a file on a directory
744
 * on the base of a maximum directory size allowed
745
 * deprecated: use enough_space instead!
746
 *
747
 * @author Hugues Peeters <[email protected]>
748
 *
749
 * @param int    $file_size     Size of the file in byte
750
 * @param string $dir           Path of the directory where the file should be added
751
 * @param int    $max_dir_space Maximum size of the diretory in byte
752
 *
753
 * @return bool true if there is enough space, false otherwise
754
 *
755
 * @see enough_size() uses  dir_total_space() function
756
 */
757
function enough_size($file_size, $dir, $max_dir_space)
758
{
759
    // If the directory is the archive directory, safely ignore the size limit
760
    if (api_get_path(SYS_ARCHIVE_PATH) == $dir) {
761
        return true;
762
    }
763
764
    if ($max_dir_space) {
765
        $already_filled_space = dir_total_space($dir);
766
        if (($file_size + $already_filled_space) > $max_dir_space) {
767
            return false;
768
        }
769
    }
770
771
    return true;
772
}
773
774
/**
775
 * Computes the size already occupied by a directory and is subdirectories.
776
 *
777
 * @author Hugues Peeters <[email protected]>
778
 *
779
 * @param string $dir_path Size of the file in byte
780
 *
781
 * @return int Return the directory size in bytes
782
 */
783
function dir_total_space($dir_path)
784
{
785
    $save_dir = getcwd();
786
    chdir($dir_path);
787
    $handle = opendir($dir_path);
788
    $sumSize = 0;
789
    $dirList = [];
790
    while ($element = readdir($handle)) {
791
        if ($element == '.' || $element == '..') {
792
            continue; // Skip the current and parent directories
793
        }
794
        if (is_file($element)) {
795
            $sumSize += filesize($element);
796
        }
797
        if (is_dir($element)) {
798
            $dirList[] = $dir_path.'/'.$element;
799
        }
800
    }
801
802
    closedir($handle);
803
804
    if (sizeof($dirList) > 0) {
805
        foreach ($dirList as $j) {
806
            $sizeDir = dir_total_space($j); // Recursivity
807
            $sumSize += $sizeDir;
808
        }
809
    }
810
    chdir($save_dir); // Return to initial position
811
812
    return $sumSize;
813
}
814
815
/**
816
 * Tries to add an extension to files without extension
817
 * Some applications on Macintosh computers don't add an extension to the files.
818
 * This subroutine try to fix this on the basis of the MIME type sent
819
 * by the browser.
820
 *
821
 * Note : some browsers don't send the MIME Type (e.g. Netscape 4).
822
 *        We don't have solution for this kind of situation
823
 *
824
 * @author Hugues Peeters <[email protected]>
825
 * @author Bert Vanderkimpen
826
 *
827
 * @param string $file_name Name of the file
828
 * @param string $file_type Type of the file
829
 *
830
 * @return string File name
831
 */
832
function add_ext_on_mime($file_name, $file_type)
833
{
834
    // Check whether the file has an extension AND whether the browser has sent a MIME Type
835
836
    if (!preg_match('/^.*\.[a-zA-Z_0-9]+$/', $file_name) && $file_type) {
837
        // Build a "MIME-types / extensions" connection table
838
        static $mime_type = [];
839
840
        $mime_type[] = 'application/msword';
841
        $extension[] = '.doc';
842
        $mime_type[] = 'application/rtf';
843
        $extension[] = '.rtf';
844
        $mime_type[] = 'application/vnd.ms-powerpoint';
845
        $extension[] = '.ppt';
846
        $mime_type[] = 'application/vnd.ms-excel';
847
        $extension[] = '.xls';
848
        $mime_type[] = 'application/pdf';
849
        $extension[] = '.pdf';
850
        $mime_type[] = 'application/postscript';
851
        $extension[] = '.ps';
852
        $mime_type[] = 'application/mac-binhex40';
853
        $extension[] = '.hqx';
854
        $mime_type[] = 'application/x-gzip';
855
        $extension[] = 'tar.gz';
856
        $mime_type[] = 'application/x-shockwave-flash';
857
        $extension[] = '.swf';
858
        $mime_type[] = 'application/x-stuffit';
859
        $extension[] = '.sit';
860
        $mime_type[] = 'application/x-tar';
861
        $extension[] = '.tar';
862
        $mime_type[] = 'application/zip';
863
        $extension[] = '.zip';
864
        $mime_type[] = 'application/x-tar';
865
        $extension[] = '.tar';
866
        $mime_type[] = 'text/html';
867
        $extension[] = '.html';
868
        $mime_type[] = 'text/plain';
869
        $extension[] = '.txt';
870
        $mime_type[] = 'text/rtf';
871
        $extension[] = '.rtf';
872
        $mime_type[] = 'img/gif';
873
        $extension[] = '.gif';
874
        $mime_type[] = 'img/jpeg';
875
        $extension[] = '.jpg';
876
        $mime_type[] = 'img/png';
877
        $extension[] = '.png';
878
        $mime_type[] = 'audio/midi';
879
        $extension[] = '.mid';
880
        $mime_type[] = 'audio/mpeg';
881
        $extension[] = '.mp3';
882
        $mime_type[] = 'audio/x-aiff';
883
        $extension[] = '.aif';
884
        $mime_type[] = 'audio/x-pn-realaudio';
885
        $extension[] = '.rm';
886
        $mime_type[] = 'audio/x-pn-realaudio-plugin';
887
        $extension[] = '.rpm';
888
        $mime_type[] = 'audio/x-wav';
889
        $extension[] = '.wav';
890
        $mime_type[] = 'video/mpeg';
891
        $extension[] = '.mpg';
892
        $mime_type[] = 'video/mpeg4-generic';
893
        $extension[] = '.mp4';
894
        $mime_type[] = 'video/quicktime';
895
        $extension[] = '.mov';
896
        $mime_type[] = 'video/x-msvideo';
897
        $extension[] = '.avi';
898
899
        $mime_type[] = 'video/x-ms-wmv';
900
        $extension[] = '.wmv';
901
        $mime_type[] = 'video/x-flv';
902
        $extension[] = '.flv';
903
        $mime_type[] = 'image/svg+xml';
904
        $extension[] = '.svg';
905
        $mime_type[] = 'image/svg+xml';
906
        $extension[] = '.svgz';
907
        $mime_type[] = 'video/ogg';
908
        $extension[] = '.ogv';
909
        $mime_type[] = 'audio/ogg';
910
        $extension[] = '.oga';
911
        $mime_type[] = 'application/ogg';
912
        $extension[] = '.ogg';
913
        $mime_type[] = 'application/ogg';
914
        $extension[] = '.ogx';
915
        $mime_type[] = 'application/x-freemind';
916
        $extension[] = '.mm';
917
918
        $mime_type[] = 'application/vnd.ms-word.document.macroEnabled.12';
919
        $extension[] = '.docm';
920
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
921
        $extension[] = '.docx';
922
        $mime_type[] = 'application/vnd.ms-word.template.macroEnabled.12';
923
        $extension[] = '.dotm';
924
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.wordprocessingml.template';
925
        $extension[] = '.dotx';
926
        $mime_type[] = 'application/vnd.ms-powerpoint.template.macroEnabled.12';
927
        $extension[] = '.potm';
928
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.presentationml.template';
929
        $extension[] = '.potx';
930
        $mime_type[] = 'application/vnd.ms-powerpoint.addin.macroEnabled.12';
931
        $extension[] = '.ppam';
932
        $mime_type[] = 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12';
933
        $extension[] = '.ppsm';
934
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.presentationml.slideshow';
935
        $extension[] = '.ppsx';
936
        $mime_type[] = 'application/vnd.ms-powerpoint.presentation.macroEnabled.12';
937
        $extension[] = '.pptm';
938
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.presentationml.presentation';
939
        $extension[] = '.pptx';
940
        $mime_type[] = 'application/vnd.ms-excel.addin.macroEnabled.12';
941
        $extension[] = '.xlam';
942
        $mime_type[] = 'application/vnd.ms-excel.sheet.binary.macroEnabled.12';
943
        $extension[] = '.xlsb';
944
        $mime_type[] = 'application/vnd.ms-excel.sheet.macroEnabled.12';
945
        $extension[] = '.xlsm';
946
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
947
        $extension[] = '.xlsx';
948
        $mime_type[] = 'application/vnd.ms-excel.template.macroEnabled.12';
949
        $extension[] = '.xltm';
950
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.template';
951
        $extension[] = '.xltx';
952
953
        // Test on PC (files with no extension get application/octet-stream)
954
        //$mime_type[] = 'application/octet-stream';      $extension[] = '.ext';
955
        // Check whether the MIME type sent by the browser is within the table
956
        foreach ($mime_type as $key => &$type) {
957
            if ($type == $file_type) {
958
                $file_name .= $extension[$key];
959
                break;
960
            }
961
        }
962
963
        unset($mime_type, $extension, $type, $key); // Delete to eschew possible collisions
964
    }
965
966
    return $file_name;
967
}
968
969
/**
970
 * Manages all the unzipping process of an uploaded file.
971
 *
972
 * @author Hugues Peeters <[email protected]>
973
 *
974
 * @param array  $uploaded_file    - follows the $_FILES Structure
975
 * @param string $upload_path      - destination of the upload.
976
 *                                 This path is to append to $base_work_dir
977
 * @param string $base_work_dir    - base working directory of the module
978
 * @param int    $max_filled_space - amount of bytes to not exceed in the base
979
 *                                 working directory
980
 *
981
 * @return bool true if it succeeds false otherwise
982
 */
983
function unzip_uploaded_file($uploaded_file, $upload_path, $base_work_dir, $max_filled_space)
984
{
985
    $zip_file = new PclZip($uploaded_file['tmp_name']);
986
987
    // Check the zip content (real size and file extension)
988
    if (file_exists($uploaded_file['tmp_name'])) {
989
        $zip_content_array = $zip_file->listContent();
990
        $ok_scorm = false;
991
        $realFileSize = 0;
992
        foreach ($zip_content_array as &$this_content) {
993
            if (preg_match('~.(php.*|phtml)$~i', $this_content['filename'])) {
994
                Display::addFlash(
995
                    Display::return_message(get_lang('ZipNoPhp'))
996
                );
997
998
                return false;
999
            } elseif (stristr($this_content['filename'], 'imsmanifest.xml')) {
1000
                $ok_scorm = true;
1001
            } elseif (stristr($this_content['filename'], 'LMS')) {
1002
                $ok_plantyn_scorm1 = true;
1003
            } elseif (stristr($this_content['filename'], 'REF')) {
1004
                $ok_plantyn_scorm2 = true;
1005
            } elseif (stristr($this_content['filename'], 'SCO')) {
1006
                $ok_plantyn_scorm3 = true;
1007
            } elseif (stristr($this_content['filename'], 'AICC')) {
1008
                $ok_aicc_scorm = true;
1009
            }
1010
            $realFileSize += $this_content['size'];
1011
        }
1012
1013
        if (($ok_plantyn_scorm1 && $ok_plantyn_scorm2 && $ok_plantyn_scorm3) || $ok_aicc_scorm) {
1014
            $ok_scorm = true;
1015
        }
1016
1017
        if (!$ok_scorm && defined('CHECK_FOR_SCORM') && CHECK_FOR_SCORM) {
1018
            Display::addFlash(
1019
                Display::return_message(get_lang('NotScormContent'))
1020
            );
1021
1022
            return false;
1023
        }
1024
1025
        if (!enough_size($realFileSize, $base_work_dir, $max_filled_space)) {
1026
            Display::addFlash(
1027
                Display::return_message(get_lang('NoSpace'))
1028
            );
1029
1030
            return false;
1031
        }
1032
1033
        // It happens on Linux that $upload_path sometimes doesn't start with '/'
1034
        if ($upload_path[0] != '/' && substr($base_work_dir, -1, 1) != '/') {
1035
            $upload_path = '/'.$upload_path;
1036
        }
1037
1038
        if ($upload_path[strlen($upload_path) - 1] == '/') {
1039
            $upload_path = substr($upload_path, 0, -1);
1040
        }
1041
1042
        /*	Uncompressing phase */
1043
1044
        /*
1045
            The first version, using OS unzip, is not used anymore
1046
            because it does not return enough information.
1047
            We need to process each individual file in the zip archive to
1048
            - add it to the database
1049
            - parse & change relative html links
1050
        */
1051
        if (PHP_OS == 'Linux' && !get_cfg_var('safe_mode') && false) { // *** UGent, changed by OC ***
1052
            // Shell Method - if this is possible, it gains some speed
1053
            exec("unzip -d \"".$base_work_dir.$upload_path."/\"".$uploaded_file['name']." ".$uploaded_file['tmp_name']);
1054
        } else {
1055
            // PHP method - slower...
1056
            $save_dir = getcwd();
1057
            chdir($base_work_dir.$upload_path);
1058
            $unzippingState = $zip_file->extract();
1059
            for ($j = 0; $j < count($unzippingState); $j++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
1060
                $state = $unzippingState[$j];
1061
1062
                // Fix relative links in html files
1063
                $extension = strrchr($state['stored_filename'], '.');
1064
            }
1065
            if ($dir = @opendir($base_work_dir.$upload_path)) {
1066
                while ($file = readdir($dir)) {
1067
                    if ($file != '.' && $file != '..') {
1068
                        $filetype = 'file';
1069
                        if (is_dir($base_work_dir.$upload_path.'/'.$file)) {
1070
                            $filetype = 'folder';
1071
                        }
1072
1073
                        $safe_file = api_replace_dangerous_char($file);
1074
                        @rename($base_work_dir.$upload_path.'/'.$file, $base_work_dir.$upload_path.'/'.$safe_file);
1075
                        set_default_settings($upload_path, $safe_file, $filetype);
1076
                    }
1077
                }
1078
1079
                closedir($dir);
1080
            } else {
1081
                error_log('Could not create directory '.$base_work_dir.$upload_path.' to unzip files');
1082
            }
1083
            chdir($save_dir); // Back to previous dir position
1084
        }
1085
    }
1086
1087
    return true;
1088
}
1089
1090
/**
1091
 * Manages all the unzipping process of an uploaded document
1092
 * This uses the item_property table for properties of documents.
1093
 *
1094
 * @author Hugues Peeters <[email protected]>
1095
 * @author Bert Vanderkimpen
1096
 *
1097
 * @param array  $courseInfo
1098
 * @param array  $userInfo
1099
 * @param array  $uploaded_file    - follows the $_FILES Structure
1100
 * @param string $uploadPath       - destination of the upload.
1101
 *                                 This path is to append to $base_work_dir
1102
 * @param string $base_work_dir    - base working directory of the module
1103
 * @param int    $maxFilledSpace   - amount of bytes to not exceed in the base
1104
 *                                 working directory
1105
 * @param int    $sessionId
1106
 * @param int    $groupId          group.id
1107
 * @param bool   $output           Optional. If no output not wanted on success, set to false.
1108
 * @param bool   $onlyUploadFile
1109
 * @param string $whatIfFileExists (only works if $onlyUploadFile is false)
1110
 *
1111
 * @return bool true if it succeeds false otherwise
1112
 */
1113
function unzip_uploaded_document(
1114
    $courseInfo,
1115
    $userInfo,
1116
    $uploaded_file,
1117
    $uploadPath,
1118
    $base_work_dir,
1119
    $maxFilledSpace,
1120
    $sessionId = 0,
1121
    $groupId = 0,
1122
    $output = true,
1123
    $onlyUploadFile = false,
1124
    $whatIfFileExists = 'overwrite'
1125
) {
1126
    $zip = new PclZip($uploaded_file['tmp_name']);
1127
1128
    // Check the zip content (real size and file extension)
1129
    $zip_content_array = (array) $zip->listContent();
1130
    $realSize = 0;
1131
    foreach ($zip_content_array as &$this_content) {
1132
        $realSize += $this_content['size'];
1133
    }
1134
1135
    if (!DocumentManager::enough_space($realSize, $maxFilledSpace)) {
1136
        echo Display::return_message(get_lang('UplNotEnoughSpace'), 'error');
1137
1138
        return false;
1139
    }
1140
1141
    $folder = api_get_unique_id();
1142
    $destinationDir = api_get_path(SYS_ARCHIVE_PATH).$folder;
1143
    mkdir($destinationDir, api_get_permissions_for_new_directories(), true);
1144
1145
    // Uncompress zip file
1146
    // We extract using a callback function that "cleans" the path
1147
    $zip->extract(
1148
        PCLZIP_OPT_PATH,
1149
        $destinationDir,
1150
        PCLZIP_CB_PRE_EXTRACT,
1151
        'clean_up_files_in_zip',
1152
        PCLZIP_OPT_REPLACE_NEWER
1153
    );
1154
1155
    if ($onlyUploadFile === false) {
1156
        // Add all documents in the unzipped folder to the database
1157
        add_all_documents_in_folder_to_database(
1158
            $courseInfo,
1159
            $userInfo,
1160
            $base_work_dir,
1161
            $destinationDir,
1162
            $sessionId,
1163
            $groupId,
1164
            $output,
1165
            ['path' => $uploadPath],
1166
            $whatIfFileExists
1167
        );
1168
    } else {
1169
        // Copy result
1170
        $fs = new \Symfony\Component\Filesystem\Filesystem();
1171
        $fs->mirror($destinationDir, $base_work_dir.$uploadPath, null, ['overwrite']);
1172
    }
1173
1174
    if (is_dir($destinationDir)) {
1175
        rmdirr($destinationDir);
1176
    }
1177
1178
    return true;
1179
}
1180
1181
/**
1182
 * This function is a callback function that is used while extracting a zipfile
1183
 * http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_cb_pre_extract.
1184
 *
1185
 * @param array $p_event
1186
 * @param array $p_header
1187
 *
1188
 * @return int (If the function returns 1, then the extraction is resumed, if 0 the path was skipped)
1189
 */
1190
function clean_up_files_in_zip($p_event, &$p_header)
1191
{
1192
    $originalStoredFileName = $p_header['stored_filename'];
1193
    $baseName = basename($originalStoredFileName);
1194
    // Skip files
1195
    $skipFiles = [
1196
        '__MACOSX',
1197
        '.Thumbs.db',
1198
        'Thumbs.db',
1199
    ];
1200
    if (in_array($baseName, $skipFiles)) {
1201
        return 0;
1202
    }
1203
    $modifiedStoredFileName = clean_up_path($originalStoredFileName);
1204
    $p_header['filename'] = str_replace($originalStoredFileName, $modifiedStoredFileName, $p_header['filename']);
1205
1206
    return 1;
1207
}
1208
1209
/**
1210
 * This function cleans up a given path
1211
 * by eliminating dangerous file names and cleaning them.
1212
 *
1213
 * @param string $path
1214
 *
1215
 * @return string
1216
 *
1217
 * @see disable_dangerous_file()
1218
 * @see api_replace_dangerous_char()
1219
 */
1220
function clean_up_path($path)
1221
{
1222
    // Split the path in folders and files
1223
    $path_array = explode('/', $path);
1224
    // Clean up every folder and filename in the path
1225
    foreach ($path_array as $key => &$val) {
1226
        // We don't want to lose the dots in ././folder/file (cfr. zipfile)
1227
        if ($val != '.') {
1228
            $val = disable_dangerous_file(api_replace_dangerous_char($val));
1229
        }
1230
    }
1231
    // Join the "cleaned" path (modified in-place as passed by reference)
1232
    $path = implode('/', $path_array);
1233
    filter_extension($path);
1234
1235
    return $path;
1236
}
1237
1238
/**
1239
 * Checks if the file is dangerous, based on extension and/or mimetype.
1240
 * The list of extensions accepted/rejected can be found from
1241
 * api_get_setting('upload_extensions_exclude') and api_get_setting('upload_extensions_include').
1242
 *
1243
 * @param string $filename passed by reference. The filename will be modified
1244
 *                         if filter rules say so! (you can include path but the filename should look like 'abc.html')
1245
 *
1246
 * @return int 0 to skip file, 1 to keep file
1247
 */
1248
function filter_extension(&$filename)
1249
{
1250
    if (substr($filename, -1) == '/') {
1251
        return 1; // Authorize directories
1252
    }
1253
    $blacklist = api_get_setting('upload_extensions_list_type');
1254
    if ($blacklist != 'whitelist') { // if = blacklist
1255
        $extensions = explode(';', strtolower(api_get_setting('upload_extensions_blacklist')));
1256
1257
        $skip = api_get_setting('upload_extensions_skip');
1258
        $ext = strrchr($filename, '.');
1259
        $ext = substr($ext, 1);
1260
        if (empty($ext)) {
1261
            return 1; // We're in blacklist mode, so accept empty extensions
1262
        }
1263
        if (in_array(strtolower($ext), $extensions)) {
1264
            if ($skip == 'true') {
1265
                return 0;
1266
            } else {
1267
                $new_ext = api_get_setting('upload_extensions_replace_by');
1268
                $filename = str_replace('.'.$ext, '.'.$new_ext, $filename);
1269
1270
                return 1;
1271
            }
1272
        } else {
1273
            return 1;
1274
        }
1275
    } else {
1276
        $extensions = explode(';', strtolower(api_get_setting('upload_extensions_whitelist')));
1277
        $skip = api_get_setting('upload_extensions_skip');
1278
        $ext = strrchr($filename, '.');
1279
        $ext = substr($ext, 1);
1280
        if (empty($ext)) {
1281
            return 1; // Accept empty extensions
1282
        }
1283
        if (!in_array(strtolower($ext), $extensions)) {
1284
            if ($skip == 'true') {
1285
                return 0;
1286
            } else {
1287
                $new_ext = api_get_setting('upload_extensions_replace_by');
1288
                $filename = str_replace('.'.$ext, '.'.$new_ext, $filename);
1289
1290
                return 1;
1291
            }
1292
        } else {
1293
            return 1;
1294
        }
1295
    }
1296
}
1297
1298
/**
1299
 * Updates an existing document in the database
1300
 * as the file exists, we only need to change the size.
1301
 *
1302
 * @param array $_course
1303
 * @param int   $documentId
1304
 * @param int   $filesize
1305
 * @param int   $readonly
1306
 *
1307
 * @return bool true /false
1308
 */
1309
function update_existing_document($_course, $documentId, $filesize, $readonly = 0)
1310
{
1311
    $document_table = Database::get_course_table(TABLE_DOCUMENT);
1312
    $documentId = intval($documentId);
1313
    $filesize = intval($filesize);
1314
    $readonly = intval($readonly);
1315
    $course_id = $_course['real_id'];
1316
1317
    $sql = "UPDATE $document_table SET
1318
            size = '$filesize',
1319
            readonly = '$readonly'
1320
			WHERE c_id = $course_id AND id = $documentId";
1321
    if (Database::query($sql)) {
1322
        return true;
1323
    } else {
1324
        return false;
1325
    }
1326
}
1327
1328
/**
1329
 * This function updates the last_edit_date, last edit user id on all folders in a given path.
1330
 *
1331
 * @param array  $_course
1332
 * @param string $path
1333
 * @param int    $user_id
1334
 */
1335
function item_property_update_on_folder($_course, $path, $user_id)
1336
{
1337
    // If we are in the root, just return... no need to update anything
1338
    if ($path == '/') {
1339
        return;
1340
    }
1341
1342
    $user_id = intval($user_id);
1343
1344
    // If the given path ends with a / we remove it
1345
    $endchar = substr($path, strlen($path) - 1, 1);
1346
    if ($endchar == '/') {
1347
        $path = substr($path, 0, strlen($path) - 1);
1348
    }
1349
1350
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
1351
1352
    // Get the time
1353
    $time = api_get_utc_datetime();
1354
1355
    // Det all paths in the given path
1356
    // /folder/subfolder/subsubfolder/file
1357
    // if file is updated, subsubfolder, subfolder and folder are updated
1358
    $exploded_path = explode('/', $path);
1359
    $course_id = api_get_course_int_id();
1360
    $newpath = '';
1361
    foreach ($exploded_path as $key => &$value) {
1362
        // We don't want a slash before our first slash
1363
        if ($key != 0) {
1364
            $newpath .= '/'.$value;
1365
            // Select ID of given folder
1366
            $folder_id = DocumentManager::get_document_id($_course, $newpath);
1367
1368
            if ($folder_id) {
1369
                $sql = "UPDATE $table SET
1370
				        lastedit_date = '$time',
1371
				        lastedit_type = 'DocumentInFolderUpdated', 
1372
				        lastedit_user_id='$user_id'
1373
						WHERE 
1374
						    c_id = $course_id AND 
1375
						    tool='".TOOL_DOCUMENT."' AND 
1376
						    ref = '$folder_id'";
1377
                Database::query($sql);
1378
            }
1379
        }
1380
    }
1381
}
1382
1383
/**
1384
 * Adds file to document table in database
1385
 * deprecated: use file_set_default_settings instead.
1386
 *
1387
 * @author	Olivier Cauberghe <[email protected]>
1388
 *
1389
 * @param	path,filename
1390
 * action:	Adds an entry to the document table with the default settings
1391
 */
1392
function set_default_settings($upload_path, $filename, $filetype = 'file')
1393
{
1394
    $dbTable = Database::get_course_table(TABLE_DOCUMENT);
1395
    global $default_visibility;
1396
1397
    if (!$default_visibility) {
1398
        $default_visibility = 'v';
1399
    }
1400
    $filetype = Database::escape_string($filetype);
1401
1402
    $upload_path = str_replace('\\', '/', $upload_path);
1403
    $upload_path = str_replace('//', '/', $upload_path);
1404
1405
    if ($upload_path == '/') {
1406
        $upload_path = '';
1407
    } elseif (!empty($upload_path) && $upload_path[0] != '/') {
1408
        $upload_path = "/$upload_path";
1409
    }
1410
1411
    $endchar = substr($filename, strlen($filename) - 1, 1);
1412
1413
    if ($endchar == '/') {
1414
        $filename = substr($filename, 0, -1);
1415
    }
1416
    $filename = Database::escape_string($filename);
1417
    $query = "SELECT count(*) as bestaat FROM $dbTable
1418
              WHERE path='$upload_path/$filename'";
1419
    $result = Database::query($query);
1420
    $row = Database::fetch_array($result);
1421
    if ($row['bestaat'] > 0) {
1422
        $query = "UPDATE $dbTable SET
1423
		            path='$upload_path/$filename',
1424
		            visibility='$default_visibility',
1425
		            filetype='$filetype'
1426
		          WHERE path='$upload_path/$filename'";
1427
    } else {
1428
        $query = "INSERT INTO $dbTable (path,visibility,filetype)
1429
		          VALUES('$upload_path/$filename','$default_visibility','$filetype')";
1430
    }
1431
    Database::query($query);
1432
}
1433
1434
/**
1435
 * Retrieves the image path list in a html file.
1436
 *
1437
 * @author Hugues Peeters <[email protected]>
1438
 *
1439
 * @param string $html_file
1440
 *
1441
 * @return array -  images path list
1442
 */
1443
function search_img_from_html($html_file)
1444
{
1445
    $img_path_list = [];
1446
1447
    if (!$fp = fopen($html_file, 'r')) {
1448
        return;
1449
    }
1450
1451
    // Aearch and store occurences of the <img> tag in an array
1452
    $size_file = (filesize($html_file) === 0) ? 1 : filesize($html_file);
1453
    if (isset($fp) && $fp !== false) {
1454
        $buffer = fread($fp, $size_file);
1455
        if (strlen($buffer) >= 0 && $buffer !== false) {
1456
        } else {
1457
            die('<center>Can not read file.</center>');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
1458
        }
1459
    } else {
1460
        die('<center>Can not read file.</center>');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
1461
    }
1462
    $matches = [];
1463
    if (preg_match_all('~<[[:space:]]*img[^>]*>~i', $buffer, $matches)) {
1464
        $img_tag_list = $matches[0];
1465
    }
1466
1467
    fclose($fp);
1468
    unset($buffer);
1469
1470
    // Search the image file path from all the <IMG> tag detected
1471
1472
    if (sizeof($img_tag_list) > 0) {
1473
        foreach ($img_tag_list as &$this_img_tag) {
1474
            if (preg_match('~src[[:space:]]*=[[:space:]]*[\"]{1}([^\"]+)[\"]{1}~i', $this_img_tag, $matches)) {
1475
                $img_path_list[] = $matches[1];
1476
            }
1477
        }
1478
        $img_path_list = array_unique($img_path_list); // Remove duplicate entries
1479
    }
1480
1481
    return $img_path_list;
1482
}
1483
1484
/**
1485
 * Creates a new directory trying to find a directory name
1486
 * that doesn't already exist.
1487
 *
1488
 * @author  Hugues Peeters <[email protected]>
1489
 * @author  Bert Vanderkimpen
1490
 *
1491
 * @param array  $_course                 current course information
1492
 * @param int    $user_id                 current user id
1493
 * @param int    $session_id
1494
 * @param int    $to_group_id             group.id
1495
 * @param int    $to_user_id
1496
 * @param string $base_work_dir           /var/www/chamilo/courses/ABC/document
1497
 * @param string $desired_dir_name        complete path of the desired name
1498
 *                                        Example: /folder1/folder2
1499
 * @param string $title                   "folder2"
1500
 * @param int    $visibility              (0 for invisible, 1 for visible, 2 for deleted)
1501
 * @param bool   $generateNewNameIfExists
1502
 * @param bool   $sendNotification        depends in conf setting "send_notification_when_document_added"
1503
 *
1504
 * @return CDocument|false
1505
 */
1506
function create_unexisting_directory(
1507
    $_course,
1508
    $user_id,
1509
    $session_id,
1510
    $to_group_id,
1511
    $to_user_id,
1512
    $base_work_dir,
1513
    $desired_dir_name,
1514
    $title = '',
1515
    $visibility = '',
1516
    $generateNewNameIfExists = false,
1517
    $sendNotification = true
1518
) {
1519
    $course_id = $_course['real_id'];
1520
    $session_id = (int) $session_id;
1521
1522
    $folderExists = DocumentManager::folderExists(
1523
        $desired_dir_name,
1524
        $_course,
1525
        $session_id,
1526
        $to_group_id
1527
    );
1528
1529
    if ($folderExists === true) {
1530
        if ($generateNewNameIfExists) {
1531
            $counter = 1;
1532
            while (1) {
1533
                $folderExists = DocumentManager::folderExists(
1534
                    $desired_dir_name.'_'.$counter,
1535
                    $_course,
1536
                    $session_id,
1537
                    $to_group_id
1538
                );
1539
1540
                if ($folderExists === false) {
1541
                    break;
1542
                }
1543
                $counter++;
1544
            }
1545
            $desired_dir_name = $desired_dir_name.'_'.$counter;
1546
        } else {
1547
            return false;
1548
        }
1549
    }
1550
1551
    $systemFolderName = $desired_dir_name;
1552
1553
    // Adding suffix
1554
    $suffix = DocumentManager::getDocumentSuffix(
1555
        $_course,
1556
        $session_id,
1557
        $to_group_id
1558
    );
1559
1560
    $systemFolderName .= $suffix;
1561
1562
    if ($title == null) {
1563
        $title = basename($desired_dir_name);
1564
    }
1565
1566
    //if (!is_dir($base_work_dir.$systemFolderName)) {
1567
        /*$result = mkdir(
1568
            $base_work_dir.$systemFolderName,
1569
            api_get_permissions_for_new_directories(),
1570
            true
1571
        );*/
1572
        $result = true;
1573
        if ($result) {
1574
            // Check if pathname already exists inside document table
1575
            $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
1576
            $sql = "SELECT id, path FROM $tbl_document
1577
                    WHERE
1578
                        c_id = $course_id AND
1579
                        (
1580
                            path = '".Database::escape_string($systemFolderName)."'
1581
                        )
1582
            ";
1583
            $rs = Database::query($sql);
1584
            if (Database::num_rows($rs) == 0) {
1585
                $document = DocumentManager::addDocument(
1586
                    $_course,
1587
                    $systemFolderName,
1588
                    'folder',
1589
                    0,
1590
                    $title,
1591
                    null,
1592
                    0,
1593
                    true,
1594
                    $to_group_id,
1595
                    $session_id,
1596
                    $user_id,
1597
                    $sendNotification
1598
                );
1599
1600
                if ($document) {
1601
                    // Update document item_property
1602
                    /*if (!empty($visibility)) {
1603
                        $visibilities = [
1604
                            0 => 'invisible',
1605
                            1 => 'visible',
1606
                            2 => 'delete',
1607
                        ];
1608
                        api_item_property_update(
1609
                            $_course,
1610
                            TOOL_DOCUMENT,
1611
                            $document_id,
1612
                            $visibilities[$visibility],
1613
                            $user_id,
1614
                            $groupInfo,
1615
                            $to_user_id,
1616
                            null,
1617
                            null,
1618
                            $session_id
1619
                        );
1620
                    } else {
1621
                        api_item_property_update(
1622
                            $_course,
1623
                            TOOL_DOCUMENT,
1624
                            $document_id,
1625
                            'FolderCreated',
1626
                            $user_id,
1627
                            $groupInfo,
1628
                            $to_user_id,
1629
                            null,
1630
                            null,
1631
                            $session_id
1632
                        );
1633
                    }*/
1634
1635
                    return $document;
1636
                }
1637
            } else {
1638
                $document = Database::fetch_array($rs);
1639
                $documentData = DocumentManager::get_document_data_by_id(
1640
                    $document['id'],
1641
                    $_course['code'],
1642
                    false,
1643
                    $session_id
1644
                );
1645
1646
                $em = Database::getManager();
1647
                $document = $em->getRepository('ChamiloCourseBundle:CDocument')->find($documentData['iid']);
1648
1649
                return $document;
1650
            }
1651
        }
1652
    //}
1653
1654
    return false;
1655
}
1656
1657
/**
1658
 * Handles uploaded missing images.
1659
 *
1660
 * @author Hugues Peeters <[email protected]>
1661
 * @author Bert Vanderkimpen
1662
 *
1663
 * @param array  $_course
1664
 * @param array  $uploaded_file_collection - follows the $_FILES Structure
1665
 * @param string $base_work_dir
1666
 * @param string $missing_files_dir
1667
 * @param int    $user_id
1668
 * @param int    $to_group_id              group.id
1669
 */
1670
function move_uploaded_file_collection_into_directory(
1671
    $_course,
1672
    $uploaded_file_collection,
1673
    $base_work_dir,
1674
    $missing_files_dir,
1675
    $user_id,
1676
    $to_group_id,
1677
    $to_user_id,
1678
    $max_filled_space
1679
) {
1680
    $number_of_uploaded_images = count($uploaded_file_collection['name']);
1681
    $list = [];
1682
    for ($i = 0; $i < $number_of_uploaded_images; $i++) {
1683
        $missing_file['name'] = $uploaded_file_collection['name'][$i];
1684
        $missing_file['type'] = $uploaded_file_collection['type'][$i];
1685
        $missing_file['tmp_name'] = $uploaded_file_collection['tmp_name'][$i];
1686
        $missing_file['error'] = $uploaded_file_collection['error'][$i];
1687
        $missing_file['size'] = $uploaded_file_collection['size'][$i];
1688
1689
        $upload_ok = process_uploaded_file($missing_file);
1690
        if ($upload_ok) {
1691
            $list[] = handle_uploaded_document(
1692
                $_course,
1693
                $missing_file,
1694
                $base_work_dir,
1695
                $missing_files_dir,
1696
                $user_id,
1697
                $to_group_id,
1698
                $to_user_id,
1699
                $max_filled_space,
1700
                0,
1701
                'overwrite'
1702
            );
1703
        }
1704
        unset($missing_file);
1705
    }
1706
1707
    return $list;
1708
}
1709
1710
/**
1711
 * Opens the old html file and replace the src path into the img tag
1712
 * This also works for files in subdirectories.
1713
 *
1714
 * @param $original_img_path is an array
1715
 * @param $new_img_path is an array
1716
 */
1717
function replace_img_path_in_html_file($original_img_path, $new_img_path, $html_file)
1718
{
1719
    // Open the file
1720
    $fp = fopen($html_file, 'r');
1721
    $buffer = fread($fp, filesize($html_file));
1722
    $new_html_content = '';
1723
1724
    // Fix the image tags
1725
    for ($i = 0, $fileNb = count($original_img_path); $i < $fileNb; $i++) {
1726
        $replace_what = $original_img_path[$i];
1727
        // We only need the directory and the filename /path/to/file_html_files/missing_file.gif -> file_html_files/missing_file.gif
1728
        $exploded_file_path = explode('/', $new_img_path[$i]);
1729
        $replace_by = $exploded_file_path[count($exploded_file_path) - 2].'/'.$exploded_file_path[count($exploded_file_path) - 1];
1730
        $buffer = str_replace($replace_what, $replace_by, $buffer);
1731
    }
1732
1733
    $new_html_content .= $buffer;
1734
1735
    @fclose($fp);
1736
1737
    // Write the resulted new file
1738
1739
    if (!$fp = fopen($html_file, 'w')) {
1740
        return;
1741
    }
1742
1743
    if (!fwrite($fp, $new_html_content)) {
1744
        return;
1745
    }
1746
}
1747
1748
/**
1749
 * Checks the extension of a file, if it's .htm or .html
1750
 * we use search_img_from_html to get all image paths in the file.
1751
 *
1752
 * @param string $file
1753
 *
1754
 * @return array paths
1755
 *
1756
 * @see check_for_missing_files() uses search_img_from_html()
1757
 */
1758
function check_for_missing_files($file)
1759
{
1760
    if (strrchr($file, '.') == '.htm' || strrchr($file, '.') == '.html') {
1761
        $img_file_path = search_img_from_html($file);
1762
1763
        return $img_file_path;
1764
    }
1765
1766
    return false;
1767
}
1768
1769
/**
1770
 * This function builds a form that asks for the missing images in a html file
1771
 * maybe we should do this another way?
1772
 *
1773
 * @param array  $missing_files
1774
 * @param string $upload_path
1775
 * @param string $file_name
1776
 *
1777
 * @return string the form
1778
 */
1779
function build_missing_files_form($missing_files, $upload_path, $file_name)
1780
{
1781
    // Do we need a / or not?
1782
    $added_slash = ($upload_path == '/') ? '' : '/';
1783
    $folder_id = DocumentManager::get_document_id(api_get_course_info(), $upload_path);
1784
    // Build the form
1785
    $form = "<p><strong>".get_lang('MissingImagesDetected')."</strong></p>"
1786
        ."<form method=\"post\" action=\"".api_get_self()."\" enctype=\"multipart/form-data\">"
1787
        // Related_file is the path to the file that has missing images
1788
        ."<input type=\"hidden\" name=\"related_file\" value=\"".$upload_path.$added_slash.$file_name."\" />"
1789
        ."<input type=\"hidden\" name=\"upload_path\" value=\"".$upload_path."\" />"
1790
        ."<input type=\"hidden\" name=\"id\" value=\"".$folder_id."\" />"
1791
        ."<table border=\"0\">";
1792
    foreach ($missing_files as &$this_img_file_path) {
1793
        $form .= "<tr>"
1794
            ."<td>".basename($this_img_file_path)." : </td>"
1795
            ."<td>"
1796
            ."<input type=\"file\" name=\"img_file[]\"/>"
1797
            ."<input type=\"hidden\" name=\"img_file_path[]\" value=\"".$this_img_file_path."\" />"
1798
            ."</td>"
1799
            ."</tr>";
1800
    }
1801
    $form .= "</table>"
1802
        ."<button type='submit' name=\"cancel_submit_image\" value=\"".get_lang('Cancel')."\" class=\"cancel\">".get_lang('Cancel')."</button>"
1803
        ."<button type='submit' name=\"submit_image\" value=\"".get_lang('Ok')."\" class=\"save\">".get_lang('Ok')."</button>"
1804
        ."</form>";
1805
1806
    return $form;
1807
}
1808
1809
/**
1810
 * This recursive function can be used during the upgrade process form older
1811
 * versions of Chamilo
1812
 * It crawls the given directory, checks if the file is in the DB and adds
1813
 * it if it's not.
1814
 *
1815
 * @param array  $courseInfo
1816
 * @param array  $userInfo
1817
 * @param string $base_work_dir    course document dir
1818
 * @param string $folderPath       folder to read
1819
 * @param int    $sessionId
1820
 * @param int    $groupId          group.id
1821
 * @param bool   $output
1822
 * @param array  $parent
1823
 * @param string $whatIfFileExists
1824
 *
1825
 * @return bool
1826
 */
1827
function add_all_documents_in_folder_to_database(
1828
    $courseInfo,
1829
    $userInfo,
1830
    $base_work_dir,
1831
    $folderPath,
1832
    $sessionId = 0,
1833
    $groupId = 0,
1834
    $output = false,
1835
    $parent = [],
1836
    $whatIfFileExists = 'overwrite'
1837
) {
1838
    if (empty($userInfo) || empty($courseInfo)) {
1839
        return false;
1840
    }
1841
1842
    $userId = $userInfo['user_id'];
1843
1844
    // Open dir
1845
    $handle = opendir($folderPath);
1846
1847
    if (is_dir($folderPath)) {
1848
        // Run trough
1849
        while ($file = readdir($handle)) {
1850
            if ($file == '.' || $file == '..') {
1851
                continue;
1852
            }
1853
1854
            $parentPath = '';
1855
            if (!empty($parent) && isset($parent['path'])) {
1856
                $parentPath = $parent['path'];
1857
                if ($parentPath == '/') {
1858
                    $parentPath = '';
1859
                }
1860
            }
1861
1862
            $completePath = $parentPath.'/'.$file;
1863
            $sysFolderPath = $folderPath.'/'.$file;
1864
1865
            // Is directory?
1866
            if (is_dir($sysFolderPath)) {
1867
                $folderExists = DocumentManager::folderExists(
1868
                    $completePath,
1869
                    $courseInfo,
1870
                    $sessionId,
1871
                    $groupId
1872
                );
1873
1874
                if ($folderExists === true) {
1875
                    switch ($whatIfFileExists) {
1876
                        case 'overwrite':
1877
                            $documentId = DocumentManager::get_document_id($courseInfo, $completePath, $sessionId);
1878
                            if ($documentId) {
1879
                                $newFolderData = DocumentManager::get_document_data_by_id(
1880
                                    $documentId,
1881
                                    $courseInfo['code'],
1882
                                    false,
1883
                                    $sessionId
1884
                                );
1885
                            }
1886
                            break;
1887
                        case 'rename':
1888
                            $newFolderData = create_unexisting_directory(
1889
                                $courseInfo,
1890
                                $userId,
1891
                                $sessionId,
1892
                                $groupId,
1893
                                null,
1894
                                $base_work_dir,
1895
                                $completePath,
1896
                                null,
1897
                                null,
1898
                                true
1899
                            );
1900
                            break;
1901
                        case 'nothing':
1902
                            if ($output) {
1903
                                $documentId = DocumentManager::get_document_id($courseInfo, $completePath, $sessionId);
1904
                                if ($documentId) {
1905
                                    $folderData = DocumentManager::get_document_data_by_id(
1906
                                        $documentId,
1907
                                        $courseInfo['code'],
1908
                                        false,
1909
                                        $sessionId
1910
                                    );
1911
                                    Display::addFlash(
1912
                                        Display::return_message(
1913
                                            $folderData['path'].' '.get_lang('UplAlreadyExists'),
1914
                                            'warning'
1915
                                        )
1916
                                    );
1917
                                }
1918
                            }
1919
                            continue 2;
1920
                            break;
1921
                    }
1922
                } else {
1923
                    $newFolderData = create_unexisting_directory(
1924
                        $courseInfo,
1925
                        $userId,
1926
                        $sessionId,
1927
                        $groupId,
1928
                        null,
1929
                        $base_work_dir,
1930
                        $completePath,
1931
                        null,
1932
                        null,
1933
                        false
1934
                    );
1935
                }
1936
1937
                // Recursive
1938
                add_all_documents_in_folder_to_database(
1939
                    $courseInfo,
1940
                    $userInfo,
1941
                    $base_work_dir,
1942
                    $sysFolderPath,
1943
                    $sessionId,
1944
                    $groupId,
1945
                    $output,
1946
                    $newFolderData,
1947
                    $whatIfFileExists
1948
                );
1949
            } else {
1950
                // Rename
1951
                $uploadedFile = [
1952
                    'name' => $file,
1953
                    'tmp_name' => $sysFolderPath,
1954
                    'size' => filesize($sysFolderPath),
1955
                    'type' => null,
1956
                    'from_file' => true,
1957
                    'move_file' => true,
1958
                ];
1959
1960
                handle_uploaded_document(
1961
                    $courseInfo,
1962
                    $uploadedFile,
1963
                    $base_work_dir,
1964
                    $parentPath,
1965
                    $userId,
1966
                    $groupId,
1967
                    null,
1968
                    0,
1969
                    $whatIfFileExists,
1970
                    $output,
1971
                    false,
1972
                    null,
1973
                    $sessionId
1974
                );
1975
            }
1976
        }
1977
    }
1978
}
1979