Passed
Push — ofaj ( cdf2cf...7b6042 )
by
unknown
13:20 queued 02:03
created

sanitizeSvgFile()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 7
c 1
b 0
f 0
dl 0
loc 14
rs 10
cc 2
nc 2
nop 1
1
<?php
2
/* For licensing terms, see /license.txt */
3
4
/**
5
 * FILE UPLOAD LIBRARY.
6
 *
7
 * This is the file upload library for Chamilo.
8
 * Include/require it in your code to use its functionality.
9
 *
10
 * @package chamilo.library
11
 *
12
 * @todo test and reorganise
13
 */
14
15
use enshrined\svgSanitize\Sanitizer;
16
17
/**
18
 * Changes the file name extension from .php to .phps
19
 * Useful for securing a site.
20
 *
21
 * @author Hugues Peeters <[email protected]>
22
 *
23
 * @param string $file_name Name of a file
24
 *
25
 * @return string the filename phps'ized
26
 */
27
function php2phps($file_name)
28
{
29
    return preg_replace('/\.(phar.?|php.?|phtml.?)(\.){0,1}.*$/i', '.phps', $file_name);
30
}
31
32
/**
33
 * Renames .htaccess & .HTACCESS & .htAccess to htaccess.txt.
34
 *
35
 * @param string $filename
36
 *
37
 * @return string
38
 */
39
function htaccess2txt($filename)
40
{
41
    return str_ireplace('.htaccess', 'htaccess.txt', $filename);
42
}
43
44
/**
45
 * This function executes our safety precautions
46
 * more functions can be added.
47
 *
48
 * @param string $filename
49
 *
50
 * @return string
51
 *
52
 * @see php2phps()
53
 * @see htaccess2txt()
54
 */
55
function disable_dangerous_file($filename)
56
{
57
    return htaccess2txt(php2phps($filename));
58
}
59
60
/**
61
 * Returns the name without extension, used for the title.
62
 *
63
 * @param string $name
64
 *
65
 * @return name without the extension
66
 */
67
function get_document_title($name)
68
{
69
    // If they upload .htaccess...
70
    $name = disable_dangerous_file($name);
71
    $ext = substr(strrchr($name, '.'), 0);
72
73
    if (empty($ext)) {
74
        return substr($name, 0, strlen($name));
75
    }
76
77
    return substr($name, 0, strlen($name) - strlen(strstr($name, $ext)));
78
}
79
80
/**
81
 * This function checks if the upload succeeded.
82
 *
83
 * @param array $uploaded_file ($_FILES)
84
 *
85
 * @return true if upload succeeded
86
 */
87
function process_uploaded_file($uploaded_file, $show_output = true)
88
{
89
    // Checking the error code sent with the file upload.
90
    if (isset($uploaded_file['error'])) {
91
        switch ($uploaded_file['error']) {
92
            case 1:
93
                // The uploaded file exceeds the upload_max_filesize directive in php.ini.
94
                if ($show_output) {
95
                    Display::addFlash(
96
                        Display::return_message(
97
                            get_lang('UplExceedMaxServerUpload').ini_get('upload_max_filesize'),
98
                            'error'
99
                        )
100
                    );
101
                }
102
103
                return false;
104
            case 2:
105
                // The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.
106
                // Not used at the moment, but could be handy if we want to limit the size of an upload
107
                // (e.g. image upload in html editor).
108
                $max_file_size = (int) $_POST['MAX_FILE_SIZE'];
109
                if ($show_output) {
110
                    Display::addFlash(
111
                        Display::return_message(
112
                            get_lang('UplExceedMaxPostSize').format_file_size($max_file_size),
113
                            'error'
114
                        )
115
                    );
116
                }
117
118
                return false;
119
            case 3:
120
                // The uploaded file was only partially uploaded.
121
                if ($show_output) {
122
                    Display::addFlash(
123
                        Display::return_message(
124
                            get_lang('UplPartialUpload').' '.get_lang('PleaseTryAgain'),
125
                            'error'
126
                        )
127
                    );
128
                }
129
130
                return false;
131
            case 4:
132
                // No file was uploaded.
133
                if ($show_output) {
134
                    Display::addFlash(
135
                        Display::return_message(
136
                            get_lang('UplNoFileUploaded').' '.get_lang('UplSelectFileFirst'),
137
                            'error'
138
                        )
139
                    );
140
                }
141
142
                return false;
143
        }
144
    }
145
146
    if (!file_exists($uploaded_file['tmp_name'])) {
147
        // No file was uploaded.
148
        if ($show_output) {
149
            Display::addFlash(Display::return_message(get_lang('UplUploadFailed'), 'error'));
150
        }
151
152
        return false;
153
    }
154
155
    if (file_exists($uploaded_file['tmp_name'])) {
156
        $filesize = filesize($uploaded_file['tmp_name']);
157
        if (empty($filesize)) {
158
            // No file was uploaded.
159
            if ($show_output) {
160
                Display::addFlash(
161
                    Display::return_message(
162
                        get_lang('UplUploadFailedSizeIsZero'),
163
                        'error'
164
                    )
165
                );
166
            }
167
168
            return false;
169
        }
170
    }
171
172
    $course_id = api_get_course_id();
173
174
    //Checking course quota if we are in a course
175
    if (!empty($course_id)) {
176
        $max_filled_space = DocumentManager::get_course_quota();
177
        // Check if there is enough space to save the file
178
        if (!DocumentManager::enough_space($uploaded_file['size'], $max_filled_space)) {
179
            if ($show_output) {
180
                Display::addFlash(
181
                    Display::return_message(
182
                        get_lang('UplNotEnoughSpace'),
183
                        'error'
184
                    )
185
                );
186
            }
187
188
            return false;
189
        }
190
    }
191
192
    // case 0: default: We assume there is no error, the file uploaded with success.
193
    return true;
194
}
195
196
function sanitizeSvgFile(string $fullPath)
197
{
198
    $fileType = mime_content_type($fullPath);
199
200
    if ('image/svg+xml' !== $fileType) {
201
        return;
202
    }
203
204
    $svgContent = file_get_contents($fullPath);
205
206
    $sanitizer = new Sanitizer();
207
    $cleanSvg = $sanitizer->sanitize($svgContent);
208
209
    file_put_contents($fullPath, $cleanSvg);
210
}
211
212
/**
213
 * This function does the save-work for the documents.
214
 * It handles the uploaded file and adds the properties to the database
215
 * If unzip=1 and the file is a zipfile, it is extracted
216
 * If we decide to save ALL kinds of documents in one database,
217
 * we could extend this with a $type='document', 'scormdocument',...
218
 *
219
 * @param array  $courseInfo
220
 * @param array  $uploadedFile            ($_FILES)
221
 *                                        array(
222
 *                                        'name' => 'picture.jpg',
223
 *                                        'tmp_name' => '...', // absolute path
224
 *                                        );
225
 * @param string $documentDir             Example: /var/www/chamilo/courses/ABC/document
226
 * @param string $uploadPath              Example: /folder1/folder2/
227
 * @param int    $userId
228
 * @param int    $groupId                 group.id
229
 * @param int    $toUserId                User ID, or NULL for everybody
230
 * @param int    $unzip                   1/0
231
 * @param string $whatIfFileExists        overwrite, rename or warn if exists (default)
232
 * @param bool   $output                  optional output parameter
233
 * @param bool   $onlyUploadFile
234
 * @param string $comment
235
 * @param int    $sessionId
236
 * @param bool   $treat_spaces_as_hyphens
237
 *
238
 * So far only use for unzip_uploaded_document function.
239
 * If no output wanted on success, set to false.
240
 *
241
 * @return string path of the saved file
242
 */
243
function handle_uploaded_document(
244
    $courseInfo,
245
    $uploadedFile,
246
    $documentDir,
247
    $uploadPath,
248
    $userId,
249
    $groupId = 0,
250
    $toUserId = null,
251
    $unzip = 0,
252
    $whatIfFileExists = '',
253
    $output = true,
254
    $onlyUploadFile = false,
255
    $comment = null,
256
    $sessionId = null,
257
    $treat_spaces_as_hyphens = true
258
) {
259
    if (empty($uploadedFile) || empty($userId) || empty($courseInfo) || empty($documentDir) || empty($uploadPath)) {
260
        return false;
261
    }
262
263
    $userInfo = api_get_user_info();
264
    $uploadedFile['name'] = stripslashes($uploadedFile['name']);
265
    // Add extension to files without one (if possible)
266
    $uploadedFile['name'] = add_ext_on_mime($uploadedFile['name'], $uploadedFile['type']);
267
    $sessionId = (int) $sessionId;
268
    if (empty($sessionId)) {
269
        $sessionId = api_get_session_id();
270
    }
271
272
    $groupInfo = [];
273
    if (!empty($groupId)) {
274
        $groupInfo = GroupManager::get_group_properties($groupId);
275
    }
276
277
    // Just in case process_uploaded_file is not called
278
    $maxSpace = DocumentManager::get_course_quota();
279
280
    // Check if there is enough space to save the file
281
    if (!DocumentManager::enough_space($uploadedFile['size'], $maxSpace)) {
282
        if ($output) {
283
            Display::addFlash(Display::return_message(get_lang('UplNotEnoughSpace'), 'error'));
284
        }
285
286
        return false;
287
    }
288
289
    if (!Security::check_abs_path($documentDir.$uploadPath, $documentDir.'/')) {
290
        Display::addFlash(
291
            Display::return_message(
292
                get_lang('Forbidden'),
293
                'error'
294
            )
295
        );
296
297
        return false;
298
    }
299
    // If the want to unzip, check if the file has a .zip (or ZIP,Zip,ZiP,...) extension
300
    if ($unzip == 1 && preg_match('/.zip$/', strtolower($uploadedFile['name']))) {
301
        return unzip_uploaded_document(
302
            $courseInfo,
303
            $userInfo,
304
            $uploadedFile,
305
            $uploadPath,
306
            $documentDir,
307
            $maxSpace,
308
            $sessionId,
309
            $groupId,
310
            $output,
311
            $onlyUploadFile,
312
            $whatIfFileExists
313
        );
314
    } elseif ($unzip == 1 && !preg_match('/.zip$/', strtolower($uploadedFile['name']))) {
315
        // We can only unzip ZIP files (no gz, tar,...)
316
        if ($output) {
317
            Display::addFlash(
318
                Display::return_message(get_lang('UplNotAZip')." ".get_lang('PleaseTryAgain'), 'error')
319
            );
320
        }
321
322
        return false;
323
    } else {
324
        // Clean up the name, only ASCII characters should stay. (and strict)
325
        $cleanName = api_replace_dangerous_char($uploadedFile['name'], $treat_spaces_as_hyphens);
326
327
        // No "dangerous" files
328
        $cleanName = disable_dangerous_file($cleanName);
329
330
        // Checking file extension
331
        if (!filter_extension($cleanName)) {
332
            if ($output) {
333
                Display::addFlash(
334
                    Display::return_message(get_lang('UplUnableToSaveFileFilteredExtension'), 'error')
335
                );
336
            }
337
338
            return false;
339
        } else {
340
            // If the upload path differs from / (= root) it will need a slash at the end
341
            if ($uploadPath !== '/') {
342
                $uploadPath = $uploadPath.'/';
343
            }
344
345
            // Full path to where we want to store the file with trailing slash
346
            $whereToSave = $documentDir.$uploadPath;
347
348
            // At least if the directory doesn't exist, tell so
349
            if (!is_dir($whereToSave)) {
350
                if (!mkdir($whereToSave, api_get_permissions_for_new_directories())) {
351
                    if ($output) {
352
                        Display::addFlash(
353
                            Display::return_message(
354
                                get_lang('DestDirectoryDoesntExist').' ('.$uploadPath.')',
355
                                'error'
356
                            )
357
                        );
358
                    }
359
360
                    return false;
361
                }
362
            }
363
364
            // Just upload the file "as is"
365
            if ($onlyUploadFile) {
366
                $errorResult = moveUploadedFile($uploadedFile, $whereToSave.$cleanName);
367
                if ($errorResult) {
368
                    return $whereToSave.$cleanName;
369
                } else {
370
                    return $errorResult;
371
                }
372
            }
373
374
            /*
375
                Based in the clean name we generate a new filesystem name
376
                Using the session_id and group_id if values are not empty
377
            */
378
            $fileSystemName = DocumentManager::fixDocumentName(
379
                $cleanName,
380
                'file',
381
                $courseInfo,
382
                $sessionId,
383
                $groupId
384
            );
385
386
            // Name of the document without the extension (for the title)
387
            $documentTitle = get_document_title($uploadedFile['name']);
388
389
            // Size of the uploaded file (in bytes)
390
            $fileSize = $uploadedFile['size'];
391
392
            // File permissions
393
            $filePermissions = api_get_permissions_for_new_files();
394
395
            // Example: /var/www/chamilo/courses/xxx/document/folder/picture.jpg
396
            $fullPath = $whereToSave.$fileSystemName;
397
398
            // Example: /folder/picture.jpg
399
            $filePath = $uploadPath.$fileSystemName;
400
401
            $docId = DocumentManager::get_document_id(
402
                $courseInfo,
403
                $filePath,
404
                $sessionId
405
            );
406
407
            // What to do if the target file exists
408
            switch ($whatIfFileExists) {
409
                // Overwrite the file if it exists
410
                case 'overwrite':
411
                    // Check if the target file exists, so we can give another message
412
                    $fileExists = file_exists($fullPath);
413
414
                    if (moveUploadedFile($uploadedFile, $fullPath)) {
415
                        sanitizeSvgFile($fullPath);
416
                        chmod($fullPath, $filePermissions);
417
418
                        if ($fileExists && $docId) {
419
                            // UPDATE DATABASE
420
                            $documentId = DocumentManager::get_document_id(
421
                                $courseInfo,
422
                                $filePath
423
                            );
424
                            if (is_numeric($documentId)) {
425
                                // Update file size
426
                                update_existing_document(
427
                                    $courseInfo,
428
                                    $documentId,
429
                                    $uploadedFile['size']
430
                                );
431
432
                                // Update document item_property
433
                                api_item_property_update(
434
                                    $courseInfo,
435
                                    TOOL_DOCUMENT,
436
                                    $documentId,
437
                                    'DocumentUpdated',
438
                                    $userId,
439
                                    $groupInfo,
440
                                    $toUserId,
441
                                    null,
442
                                    null,
443
                                    $sessionId
444
                                );
445
446
                                // Redo visibility
447
                                api_set_default_visibility(
448
                                    $documentId,
449
                                    TOOL_DOCUMENT,
450
                                    null,
451
                                    $courseInfo
452
                                );
453
                            } else {
454
                                // There might be cases where the file exists on disk but there is no registration of
455
                                // that in the database
456
                                // In this case, and if we are in overwrite mode, overwrite and create the db record
457
                                $documentId = add_document(
458
                                    $courseInfo,
459
                                    $filePath,
460
                                    'file',
461
                                    $fileSize,
462
                                    $documentTitle,
463
                                    $comment,
464
                                    0,
465
                                    true,
466
                                    $groupId,
467
                                    $sessionId
468
                                );
469
470
                                if ($documentId) {
471
                                    // Put the document in item_property update
472
                                    api_item_property_update(
473
                                        $courseInfo,
474
                                        TOOL_DOCUMENT,
475
                                        $documentId,
476
                                        'DocumentAdded',
477
                                        $userId,
478
                                        $groupInfo,
479
                                        $toUserId,
480
                                        null,
481
                                        null,
482
                                        $sessionId
483
                                    );
484
485
                                    // Redo visibility
486
                                    api_set_default_visibility(
487
                                        $documentId,
488
                                        TOOL_DOCUMENT,
489
                                        null,
490
                                        $courseInfo
491
                                    );
492
                                }
493
                            }
494
495
                            // If the file is in a folder, we need to update all parent folders
496
                            item_property_update_on_folder($courseInfo, $uploadPath, $userId);
497
498
                            // Display success message with extra info to user
499
                            if ($output) {
500
                                Display::addFlash(
501
                                    Display::return_message(
502
                                        get_lang('UplUploadSucceeded').'<br /> '.
503
                                        $documentTitle.' '.get_lang('UplFileOverwritten'),
504
                                        'confirmation',
505
                                        false
506
                                    )
507
                                );
508
                            }
509
510
                            return $filePath;
511
                        } else {
512
                            // Put the document data in the database
513
                            $documentId = add_document(
514
                                $courseInfo,
515
                                $filePath,
516
                                'file',
517
                                $fileSize,
518
                                $documentTitle,
519
                                $comment,
520
                                0,
521
                                true,
522
                                $groupId,
523
                                $sessionId
524
                            );
525
526
                            if ($documentId) {
527
                                // Put the document in item_property update
528
                                api_item_property_update(
529
                                    $courseInfo,
530
                                    TOOL_DOCUMENT,
531
                                    $documentId,
532
                                    'DocumentAdded',
533
                                    $userId,
534
                                    $groupInfo,
535
                                    $toUserId,
536
                                    null,
537
                                    null,
538
                                    $sessionId
539
                                );
540
541
                                // Redo visibility
542
                                api_set_default_visibility($documentId, TOOL_DOCUMENT, null, $courseInfo);
543
                            }
544
545
                            // If the file is in a folder, we need to update all parent folders
546
                            item_property_update_on_folder($courseInfo, $uploadPath, $userId);
547
548
                            // Display success message to user
549
                            if ($output) {
550
                                Display::addFlash(
551
                                    Display::return_message(
552
                                        get_lang('UplUploadSucceeded').'<br /> '.$documentTitle,
553
                                        'confirmation',
554
                                        false
555
                                    )
556
                                );
557
                            }
558
559
                            return $filePath;
560
                        }
561
                    } else {
562
                        if ($output) {
563
                            Display::addFlash(
564
                                Display::return_message(
565
                                    get_lang('UplUnableToSaveFile'),
566
                                    'error',
567
                                    false
568
                                )
569
                            );
570
                        }
571
572
                        return false;
573
                    }
574
                    break;
575
                case 'rename':
576
                    // Rename the file if it exists
577
                    // Always rename.
578
                    $cleanName = DocumentManager::getUniqueFileName(
579
                        $uploadPath,
580
                        $cleanName,
581
                        $courseInfo,
582
                        $sessionId,
583
                        $groupId
584
                    );
585
586
                    $fileSystemName = DocumentManager::fixDocumentName(
587
                        $cleanName,
588
                        'file',
589
                        $courseInfo,
590
                        $sessionId,
591
                        $groupId
592
                    );
593
594
                    $documentTitle = disable_dangerous_file($cleanName);
595
                    $fullPath = $whereToSave.$fileSystemName;
596
                    $filePath = $uploadPath.$fileSystemName;
597
598
                    if (moveUploadedFile($uploadedFile, $fullPath)) {
599
                        sanitizeSvgFile($fullPath);
600
                        chmod($fullPath, $filePermissions);
601
                        // Put the document data in the database
602
                        $documentId = add_document(
603
                            $courseInfo,
604
                            $filePath,
605
                            'file',
606
                            $fileSize,
607
                            $documentTitle,
608
                            $comment, // comment
609
                            0, // read only
610
                            true, // save visibility
611
                            $groupId,
612
                            $sessionId
613
                        );
614
615
                        if ($documentId) {
616
                            // Update document item_property
617
                            api_item_property_update(
618
                                $courseInfo,
619
                                TOOL_DOCUMENT,
620
                                $documentId,
621
                                'DocumentAdded',
622
                                $userId,
623
                                $groupInfo,
624
                                $toUserId,
625
                                null,
626
                                null,
627
                                $sessionId
628
                            );
629
630
                            // Redo visibility
631
                            api_set_default_visibility($documentId, TOOL_DOCUMENT, null, $courseInfo);
632
                        }
633
634
                        // If the file is in a folder, we need to update all parent folders
635
                        item_property_update_on_folder($courseInfo, $uploadPath, $userId);
636
637
                        // Display success message to user
638
                        if ($output) {
639
                            Display::addFlash(
640
                                Display::return_message(
641
                                    get_lang('UplUploadSucceeded').'<br />'.
642
                                    get_lang('UplFileSavedAs').' '.$documentTitle,
643
                                    'success',
644
                                    false
645
                                )
646
                            );
647
                        }
648
649
                        return $filePath;
650
                    } else {
651
                        if ($output) {
652
                            Display::addFlash(
653
                                Display::return_message(
654
                                    get_lang('UplUnableToSaveFile'),
655
                                    'error',
656
                                    false
657
                                )
658
                            );
659
                        }
660
661
                        return false;
662
                    }
663
                    break;
664
                case 'nothing':
665
                    $fileExists = file_exists($fullPath);
666
                    if ($fileExists) {
667
                        if ($output) {
668
                            Display::addFlash(
669
                                Display::return_message(
670
                                    $uploadPath.$cleanName.' '.get_lang('UplAlreadyExists'),
671
                                    'warning',
672
                                    false
673
                                )
674
                            );
675
                        }
676
                        break;
677
                    }
678
                    // no break
679
                default:
680
                    // Only save the file if it doesn't exist or warn user if it does exist
681
                    if (file_exists($fullPath) && $docId) {
682
                        if ($output) {
683
                            Display::addFlash(
684
                                Display::return_message($cleanName.' '.get_lang('UplAlreadyExists'), 'warning', false)
685
                            );
686
                        }
687
                    } else {
688
                        if (moveUploadedFile($uploadedFile, $fullPath)) {
689
                            chmod($fullPath, $filePermissions);
690
691
                            // Put the document data in the database
692
                            $documentId = add_document(
693
                                $courseInfo,
694
                                $filePath,
695
                                'file',
696
                                $fileSize,
697
                                $documentTitle,
698
                                $comment,
699
                                0,
700
                                true,
701
                                $groupId,
702
                                $sessionId
703
                            );
704
705
                            if ($documentId) {
706
                                // Update document item_property
707
                                api_item_property_update(
708
                                    $courseInfo,
709
                                    TOOL_DOCUMENT,
710
                                    $documentId,
711
                                    'DocumentAdded',
712
                                    $userId,
713
                                    $groupInfo,
714
                                    $toUserId,
715
                                    null,
716
                                    null,
717
                                    $sessionId
718
                                );
719
                                // Redo visibility
720
                                api_set_default_visibility($documentId, TOOL_DOCUMENT, null, $courseInfo);
721
                            }
722
723
                            // If the file is in a folder, we need to update all parent folders
724
                            item_property_update_on_folder(
725
                                $courseInfo,
726
                                $uploadPath,
727
                                $userId
728
                            );
729
730
                            // Display success message to user
731
                            if ($output) {
732
                                Display::addFlash(
733
                                    Display::return_message(
734
                                        get_lang('UplUploadSucceeded').'<br /> '.$documentTitle,
735
                                        'confirm',
736
                                        false
737
                                    )
738
                                );
739
                            }
740
741
                            return $filePath;
742
                        } else {
743
                            if ($output) {
744
                                Display::addFlash(
745
                                    Display::return_message(
746
                                        get_lang('UplUnableToSaveFile'),
747
                                        'error',
748
                                        false
749
                                    )
750
                                );
751
                            }
752
753
                            return false;
754
                        }
755
                    }
756
                    break;
757
            }
758
        }
759
    }
760
}
761
762
/**
763
 * @param string $file
764
 * @param string $storePath
765
 *
766
 * @return bool
767
 */
768
function moveUploadedFile($file, $storePath)
769
{
770
    $handleFromFile = isset($file['from_file']) && $file['from_file'] ? true : false;
771
    $moveFile = isset($file['move_file']) && $file['move_file'] ? true : false;
772
    if ($moveFile) {
773
        $copied = copy($file['tmp_name'], $storePath);
774
775
        if (!$copied) {
776
            return false;
777
        }
778
    }
779
    if ($handleFromFile) {
780
        return file_exists($file['tmp_name']);
781
    } else {
782
        return move_uploaded_file($file['tmp_name'], $storePath);
783
    }
784
}
785
786
/**
787
 * Checks if there is enough place to add a file on a directory
788
 * on the base of a maximum directory size allowed
789
 * deprecated: use enough_space instead!
790
 *
791
 * @author Hugues Peeters <[email protected]>
792
 *
793
 * @param int    $file_size     Size of the file in byte
794
 * @param string $dir           Path of the directory where the file should be added
795
 * @param int    $max_dir_space Maximum size of the diretory in byte
796
 *
797
 * @return bool true if there is enough space, false otherwise
798
 *
799
 * @see enough_size() uses  dir_total_space() function
800
 */
801
function enough_size($file_size, $dir, $max_dir_space)
802
{
803
    // If the directory is the archive directory, safely ignore the size limit
804
    if (api_get_path(SYS_ARCHIVE_PATH) == $dir) {
805
        return true;
806
    }
807
808
    if ($max_dir_space) {
809
        $already_filled_space = dir_total_space($dir);
810
        if (($file_size + $already_filled_space) > $max_dir_space) {
811
            return false;
812
        }
813
    }
814
815
    return true;
816
}
817
818
/**
819
 * Computes the size already occupied by a directory and is subdirectories.
820
 *
821
 * @author Hugues Peeters <[email protected]>
822
 *
823
 * @param string $dir_path Size of the file in byte
824
 *
825
 * @return int Return the directory size in bytes
826
 */
827
function dir_total_space($dir_path)
828
{
829
    $save_dir = getcwd();
830
    chdir($dir_path);
831
    $handle = opendir($dir_path);
832
    $sumSize = 0;
833
    $dirList = [];
834
    while ($element = readdir($handle)) {
835
        if ($element == '.' || $element == '..') {
836
            continue; // Skip the current and parent directories
837
        }
838
        if (is_file($element)) {
839
            $sumSize += filesize($element);
840
        }
841
        if (is_dir($element)) {
842
            $dirList[] = $dir_path.'/'.$element;
843
        }
844
    }
845
846
    closedir($handle);
847
848
    if (sizeof($dirList) > 0) {
849
        foreach ($dirList as $j) {
850
            $sizeDir = dir_total_space($j); // Recursivity
851
            $sumSize += $sizeDir;
852
        }
853
    }
854
    chdir($save_dir); // Return to initial position
855
856
    return $sumSize;
857
}
858
859
/**
860
 * Tries to add an extension to files without extension
861
 * Some applications on Macintosh computers don't add an extension to the files.
862
 * This subroutine try to fix this on the basis of the MIME type sent
863
 * by the browser.
864
 *
865
 * Note : some browsers don't send the MIME Type (e.g. Netscape 4).
866
 *        We don't have solution for this kind of situation
867
 *
868
 * @author Hugues Peeters <[email protected]>
869
 * @author Bert Vanderkimpen
870
 *
871
 * @param string $file_name Name of the file
872
 * @param string $file_type Type of the file
873
 *
874
 * @return string File name
875
 */
876
function add_ext_on_mime($file_name, $file_type)
877
{
878
    // Check whether the file has an extension AND whether the browser has sent a MIME Type
879
880
    if (!preg_match('/^.*\.[a-zA-Z_0-9]+$/', $file_name) && $file_type) {
881
        // Build a "MIME-types / extensions" connection table
882
        static $mime_type = [];
883
884
        $mime_type[] = 'application/msword';
885
        $extension[] = '.doc';
886
        $mime_type[] = 'application/rtf';
887
        $extension[] = '.rtf';
888
        $mime_type[] = 'application/vnd.ms-powerpoint';
889
        $extension[] = '.ppt';
890
        $mime_type[] = 'application/vnd.ms-excel';
891
        $extension[] = '.xls';
892
        $mime_type[] = 'application/pdf';
893
        $extension[] = '.pdf';
894
        $mime_type[] = 'application/postscript';
895
        $extension[] = '.ps';
896
        $mime_type[] = 'application/mac-binhex40';
897
        $extension[] = '.hqx';
898
        $mime_type[] = 'application/x-gzip';
899
        $extension[] = 'tar.gz';
900
        $mime_type[] = 'application/x-shockwave-flash';
901
        $extension[] = '.swf';
902
        $mime_type[] = 'application/x-stuffit';
903
        $extension[] = '.sit';
904
        $mime_type[] = 'application/x-tar';
905
        $extension[] = '.tar';
906
        $mime_type[] = 'application/zip';
907
        $extension[] = '.zip';
908
        $mime_type[] = 'application/x-tar';
909
        $extension[] = '.tar';
910
        $mime_type[] = 'text/html';
911
        $extension[] = '.html';
912
        $mime_type[] = 'text/plain';
913
        $extension[] = '.txt';
914
        $mime_type[] = 'text/rtf';
915
        $extension[] = '.rtf';
916
        $mime_type[] = 'img/gif';
917
        $extension[] = '.gif';
918
        $mime_type[] = 'img/jpeg';
919
        $extension[] = '.jpg';
920
        $mime_type[] = 'img/png';
921
        $extension[] = '.png';
922
        $mime_type[] = 'audio/midi';
923
        $extension[] = '.mid';
924
        $mime_type[] = 'audio/mpeg';
925
        $extension[] = '.mp3';
926
        $mime_type[] = 'audio/x-aiff';
927
        $extension[] = '.aif';
928
        $mime_type[] = 'audio/x-pn-realaudio';
929
        $extension[] = '.rm';
930
        $mime_type[] = 'audio/x-pn-realaudio-plugin';
931
        $extension[] = '.rpm';
932
        $mime_type[] = 'audio/x-wav';
933
        $extension[] = '.wav';
934
        $mime_type[] = 'video/mpeg';
935
        $extension[] = '.mpg';
936
        $mime_type[] = 'video/mpeg4-generic';
937
        $extension[] = '.mp4';
938
        $mime_type[] = 'video/quicktime';
939
        $extension[] = '.mov';
940
        $mime_type[] = 'video/x-msvideo';
941
        $extension[] = '.avi';
942
943
        $mime_type[] = 'video/x-ms-wmv';
944
        $extension[] = '.wmv';
945
        $mime_type[] = 'video/x-flv';
946
        $extension[] = '.flv';
947
        $mime_type[] = 'image/svg+xml';
948
        $extension[] = '.svg';
949
        $mime_type[] = 'image/svg+xml';
950
        $extension[] = '.svgz';
951
        $mime_type[] = 'video/ogg';
952
        $extension[] = '.ogv';
953
        $mime_type[] = 'audio/ogg';
954
        $extension[] = '.oga';
955
        $mime_type[] = 'application/ogg';
956
        $extension[] = '.ogg';
957
        $mime_type[] = 'application/ogg';
958
        $extension[] = '.ogx';
959
        $mime_type[] = 'application/x-freemind';
960
        $extension[] = '.mm';
961
962
        $mime_type[] = 'application/vnd.ms-word.document.macroEnabled.12';
963
        $extension[] = '.docm';
964
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
965
        $extension[] = '.docx';
966
        $mime_type[] = 'application/vnd.ms-word.template.macroEnabled.12';
967
        $extension[] = '.dotm';
968
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.wordprocessingml.template';
969
        $extension[] = '.dotx';
970
        $mime_type[] = 'application/vnd.ms-powerpoint.template.macroEnabled.12';
971
        $extension[] = '.potm';
972
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.presentationml.template';
973
        $extension[] = '.potx';
974
        $mime_type[] = 'application/vnd.ms-powerpoint.addin.macroEnabled.12';
975
        $extension[] = '.ppam';
976
        $mime_type[] = 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12';
977
        $extension[] = '.ppsm';
978
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.presentationml.slideshow';
979
        $extension[] = '.ppsx';
980
        $mime_type[] = 'application/vnd.ms-powerpoint.presentation.macroEnabled.12';
981
        $extension[] = '.pptm';
982
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.presentationml.presentation';
983
        $extension[] = '.pptx';
984
        $mime_type[] = 'application/vnd.ms-excel.addin.macroEnabled.12';
985
        $extension[] = '.xlam';
986
        $mime_type[] = 'application/vnd.ms-excel.sheet.binary.macroEnabled.12';
987
        $extension[] = '.xlsb';
988
        $mime_type[] = 'application/vnd.ms-excel.sheet.macroEnabled.12';
989
        $extension[] = '.xlsm';
990
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
991
        $extension[] = '.xlsx';
992
        $mime_type[] = 'application/vnd.ms-excel.template.macroEnabled.12';
993
        $extension[] = '.xltm';
994
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.template';
995
        $extension[] = '.xltx';
996
997
        // Test on PC (files with no extension get application/octet-stream)
998
        //$mime_type[] = 'application/octet-stream';      $extension[] = '.ext';
999
        // Check whether the MIME type sent by the browser is within the table
1000
        foreach ($mime_type as $key => &$type) {
1001
            if ($type == $file_type) {
1002
                $file_name .= $extension[$key];
1003
                break;
1004
            }
1005
        }
1006
1007
        unset($mime_type, $extension, $type, $key); // Delete to eschew possible collisions
1008
    }
1009
1010
    return $file_name;
1011
}
1012
1013
/**
1014
 * Manages all the unzipping process of an uploaded file.
1015
 *
1016
 * @author Hugues Peeters <[email protected]>
1017
 *
1018
 * @param array  $uploaded_file    - follows the $_FILES Structure
1019
 * @param string $upload_path      - destination of the upload.
1020
 *                                 This path is to append to $base_work_dir
1021
 * @param string $base_work_dir    - base working directory of the module
1022
 * @param int    $max_filled_space - amount of bytes to not exceed in the base
1023
 *                                 working directory
1024
 *
1025
 * @return bool true if it succeeds false otherwise
1026
 */
1027
function unzip_uploaded_file($uploaded_file, $upload_path, $base_work_dir, $max_filled_space)
1028
{
1029
    $zip_file = new PclZip($uploaded_file['tmp_name']);
1030
1031
    // Check the zip content (real size and file extension)
1032
    if (file_exists($uploaded_file['tmp_name'])) {
1033
        $zip_content_array = $zip_file->listContent();
1034
        $ok_scorm = false;
1035
        $realFileSize = 0;
1036
        $ok_plantyn_scorm1 = false;
1037
        $ok_plantyn_scorm2 = false;
1038
        $ok_plantyn_scorm3 = false;
1039
        $ok_aicc_scorm = false;
1040
        foreach ($zip_content_array as $this_content) {
1041
            if (preg_match('~.(php.*|phtml|phar|htaccess)$~i', $this_content['filename'])) {
1042
                Display::addFlash(
1043
                    Display::return_message(get_lang('ZipNoPhp'))
1044
                );
1045
1046
                return false;
1047
            } elseif (stristr($this_content['filename'], 'imsmanifest.xml')) {
1048
                $ok_scorm = true;
1049
            } elseif (stristr($this_content['filename'], 'LMS')) {
1050
                $ok_plantyn_scorm1 = true;
1051
            } elseif (stristr($this_content['filename'], 'REF')) {
1052
                $ok_plantyn_scorm2 = true;
1053
            } elseif (stristr($this_content['filename'], 'SCO')) {
1054
                $ok_plantyn_scorm3 = true;
1055
            } elseif (stristr($this_content['filename'], 'AICC')) {
1056
                $ok_aicc_scorm = true;
1057
            }
1058
            $realFileSize += $this_content['size'];
1059
        }
1060
1061
        if (($ok_plantyn_scorm1 && $ok_plantyn_scorm2 && $ok_plantyn_scorm3) || $ok_aicc_scorm) {
1062
            $ok_scorm = true;
1063
        }
1064
1065
        if (!$ok_scorm && defined('CHECK_FOR_SCORM') && CHECK_FOR_SCORM) {
1066
            Display::addFlash(
1067
                Display::return_message(get_lang('NotScormContent'))
1068
            );
1069
1070
            return false;
1071
        }
1072
1073
        if (!enough_size($realFileSize, $base_work_dir, $max_filled_space)) {
1074
            Display::addFlash(
1075
                Display::return_message(get_lang('NoSpace'))
1076
            );
1077
1078
            return false;
1079
        }
1080
1081
        // It happens on Linux that $upload_path sometimes doesn't start with '/'
1082
        if ($upload_path[0] != '/' && substr($base_work_dir, -1, 1) != '/') {
1083
            $upload_path = '/'.$upload_path;
1084
        }
1085
1086
        if ($upload_path[strlen($upload_path) - 1] == '/') {
1087
            $upload_path = substr($upload_path, 0, -1);
1088
        }
1089
1090
        /*	Uncompressing phase */
1091
1092
        $save_dir = getcwd();
1093
        chdir($base_work_dir.$upload_path);
1094
        $unzippingState = $zip_file->extract();
1095
        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...
1096
            $state = $unzippingState[$j];
1097
1098
            // Fix relative links in html files
1099
            $extension = strrchr($state['stored_filename'], '.');
1100
        }
1101
        if ($dir = @opendir($base_work_dir.$upload_path)) {
1102
            while ($file = readdir($dir)) {
1103
                if ($file != '.' && $file != '..') {
1104
                    $filetype = 'file';
1105
                    if (is_dir($base_work_dir.$upload_path.'/'.$file)) {
1106
                        $filetype = 'folder';
1107
                    }
1108
1109
                    $safe_file = api_replace_dangerous_char($file);
1110
                    $safe_file = disable_dangerous_file($safe_file);
1111
                    @rename($base_work_dir.$upload_path.'/'.$file, $base_work_dir.$upload_path.'/'.$safe_file);
1112
                    set_default_settings($upload_path, $safe_file, $filetype);
1113
                }
1114
            }
1115
1116
            closedir($dir);
1117
        } else {
1118
            error_log('Could not create directory '.$base_work_dir.$upload_path.' to unzip files');
1119
        }
1120
        chdir($save_dir); // Back to previous dir position
1121
    }
1122
1123
    return true;
1124
}
1125
1126
/**
1127
 * Manages all the unzipping process of an uploaded document
1128
 * This uses the item_property table for properties of documents.
1129
 *
1130
 * @author Hugues Peeters <[email protected]>
1131
 * @author Bert Vanderkimpen
1132
 *
1133
 * @param array  $courseInfo
1134
 * @param array  $userInfo
1135
 * @param array  $uploaded_file    - follows the $_FILES Structure
1136
 * @param string $uploadPath       - destination of the upload.
1137
 *                                 This path is to append to $base_work_dir
1138
 * @param string $base_work_dir    - base working directory of the module
1139
 * @param int    $maxFilledSpace   - amount of bytes to not exceed in the base
1140
 *                                 working directory
1141
 * @param int    $sessionId
1142
 * @param int    $groupId          group.id
1143
 * @param bool   $output           Optional. If no output not wanted on success, set to false.
1144
 * @param bool   $onlyUploadFile
1145
 * @param string $whatIfFileExists (only works if $onlyUploadFile is false)
1146
 *
1147
 * @return bool true if it succeeds false otherwise
1148
 */
1149
function unzip_uploaded_document(
1150
    $courseInfo,
1151
    $userInfo,
1152
    $uploaded_file,
1153
    $uploadPath,
1154
    $base_work_dir,
1155
    $maxFilledSpace,
1156
    $sessionId = 0,
1157
    $groupId = 0,
1158
    $output = true,
1159
    $onlyUploadFile = false,
1160
    $whatIfFileExists = 'overwrite'
1161
) {
1162
    if (empty($courseInfo) || empty($userInfo) || empty($uploaded_file) || empty($uploadPath)) {
1163
        return false;
1164
    }
1165
    $zip = new PclZip($uploaded_file['tmp_name']);
1166
1167
    // Check the zip content (real size and file extension)
1168
    $zip_content_array = (array) $zip->listContent();
1169
    $realSize = 0;
1170
    foreach ($zip_content_array as &$this_content) {
1171
        $realSize += $this_content['size'];
1172
    }
1173
1174
    if (!DocumentManager::enough_space($realSize, $maxFilledSpace)) {
1175
        echo Display::return_message(get_lang('UplNotEnoughSpace'), 'error');
1176
1177
        return false;
1178
    }
1179
1180
    $folder = api_get_unique_id();
1181
    $destinationDir = api_get_path(SYS_ARCHIVE_PATH).$folder;
1182
    mkdir($destinationDir, api_get_permissions_for_new_directories(), true);
1183
1184
    // Uncompress zip file
1185
    // We extract using a callback function that "cleans" the path
1186
    $zip->extract(
1187
        PCLZIP_OPT_PATH,
1188
        $destinationDir,
1189
        PCLZIP_CB_PRE_EXTRACT,
1190
        'clean_up_files_in_zip',
1191
        PCLZIP_OPT_REPLACE_NEWER
1192
    );
1193
1194
    if ($onlyUploadFile === false) {
1195
        // Add all documents in the unzipped folder to the database
1196
        add_all_documents_in_folder_to_database(
1197
            $courseInfo,
1198
            $userInfo,
1199
            $base_work_dir,
1200
            $destinationDir,
1201
            $sessionId,
1202
            $groupId,
1203
            $output,
1204
            ['path' => $uploadPath],
1205
            $whatIfFileExists
1206
        );
1207
    } else {
1208
        // Copy result
1209
        $fs = new \Symfony\Component\Filesystem\Filesystem();
1210
        $fs->mirror($destinationDir, $base_work_dir.$uploadPath, null, ['overwrite']);
1211
    }
1212
1213
    if (is_dir($destinationDir)) {
1214
        rmdirr($destinationDir);
1215
    }
1216
1217
    return true;
1218
}
1219
1220
/**
1221
 * This function is a callback function that is used while extracting a zipfile
1222
 * http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_cb_pre_extract.
1223
 *
1224
 * @param array $p_event
1225
 * @param array $p_header
1226
 *
1227
 * @return int (If the function returns 1, then the extraction is resumed, if 0 the path was skipped)
1228
 */
1229
function clean_up_files_in_zip($p_event, &$p_header)
1230
{
1231
    $originalStoredFileName = $p_header['stored_filename'];
1232
    $baseName = basename($originalStoredFileName);
1233
    // Skip files
1234
    $skipFiles = [
1235
        '__MACOSX',
1236
        '.Thumbs.db',
1237
        'Thumbs.db',
1238
    ];
1239
1240
    if (in_array($baseName, $skipFiles)) {
1241
        return 0;
1242
    }
1243
    $modifiedStoredFileName = clean_up_path($originalStoredFileName);
1244
    $p_header['filename'] = str_replace($originalStoredFileName, $modifiedStoredFileName, $p_header['filename']);
1245
1246
    return 1;
1247
}
1248
1249
function cleanZipFilesNoRename($p_event, &$p_header)
1250
{
1251
    $originalStoredFileName = $p_header['stored_filename'];
1252
    $baseName = basename($originalStoredFileName);
1253
    // Skip files
1254
    $skipFiles = [
1255
        '__MACOSX',
1256
        '.Thumbs.db',
1257
        'Thumbs.db',
1258
    ];
1259
1260
    if (in_array($baseName, $skipFiles)) {
1261
        return 0;
1262
    }
1263
    $modifiedStoredFileName = clean_up_path($originalStoredFileName, false);
1264
    $p_header['filename'] = str_replace($originalStoredFileName, $modifiedStoredFileName, $p_header['filename']);
1265
1266
    return 1;
1267
}
1268
1269
/**
1270
 * Allow .htaccess file.
1271
 *
1272
 * @param $p_event
1273
 * @param $p_header
1274
 *
1275
 * @return int
1276
 */
1277
function cleanZipFilesAllowHtaccess($p_event, &$p_header)
1278
{
1279
    $originalStoredFileName = $p_header['stored_filename'];
1280
    $baseName = basename($originalStoredFileName);
1281
1282
    $allowFiles = ['.htaccess'];
1283
    if (in_array($baseName, $allowFiles)) {
1284
        return 1;
1285
    }
1286
1287
    // Skip files
1288
    $skipFiles = [
1289
        '__MACOSX',
1290
        '.Thumbs.db',
1291
        'Thumbs.db',
1292
    ];
1293
1294
    if (in_array($baseName, $skipFiles)) {
1295
        return 0;
1296
    }
1297
    $modifiedStoredFileName = clean_up_path($originalStoredFileName);
1298
    $p_header['filename'] = str_replace($originalStoredFileName, $modifiedStoredFileName, $p_header['filename']);
1299
1300
    return 1;
1301
}
1302
1303
/**
1304
 * This function cleans up a given path
1305
 * by eliminating dangerous file names and cleaning them.
1306
 *
1307
 * @param string $path
1308
 * @param bool   $replaceName
1309
 *
1310
 * @return string
1311
 *
1312
 * @see disable_dangerous_file()
1313
 * @see api_replace_dangerous_char()
1314
 */
1315
function clean_up_path($path, $replaceName = true)
1316
{
1317
    // Split the path in folders and files
1318
    $path_array = explode('/', $path);
1319
    // Clean up every folder and filename in the path
1320
    foreach ($path_array as $key => &$val) {
1321
        // We don't want to lose the dots in ././folder/file (cfr. zipfile)
1322
        if ($val != '.') {
1323
            if ($replaceName) {
1324
                $val = api_replace_dangerous_char($val);
1325
            }
1326
            $val = disable_dangerous_file($val);
1327
        }
1328
    }
1329
    // Join the "cleaned" path (modified in-place as passed by reference)
1330
    $path = implode('/', $path_array);
1331
    filter_extension($path);
1332
1333
    return $path;
1334
}
1335
1336
/**
1337
 * Checks if the file is dangerous, based on extension and/or mimetype.
1338
 * The list of extensions accepted/rejected can be found from
1339
 * api_get_setting('upload_extensions_exclude') and api_get_setting('upload_extensions_include').
1340
 *
1341
 * @param string $filename passed by reference. The filename will be modified
1342
 *                         if filter rules say so! (you can include path but the filename should look like 'abc.html')
1343
 *
1344
 * @return int 0 to skip file, 1 to keep file
1345
 */
1346
function filter_extension(&$filename)
1347
{
1348
    if (substr($filename, -1) == '/') {
1349
        return 1; // Authorize directories
1350
    }
1351
    $blacklist = api_get_setting('upload_extensions_list_type');
1352
    if ($blacklist != 'whitelist') { // if = blacklist
1353
        $extensions = explode(';', strtolower(api_get_setting('upload_extensions_blacklist')));
1354
1355
        $skip = api_get_setting('upload_extensions_skip');
1356
        $ext = strrchr($filename, '.');
1357
        $ext = substr($ext, 1);
1358
        if (empty($ext)) {
1359
            return 1; // We're in blacklist mode, so accept empty extensions
1360
        }
1361
        if (in_array(strtolower($ext), $extensions)) {
1362
            if ($skip == 'true') {
1363
                return 0;
1364
            } else {
1365
                $new_ext = api_get_setting('upload_extensions_replace_by');
1366
                $filename = str_replace('.'.$ext, '.'.$new_ext, $filename);
1367
1368
                return 1;
1369
            }
1370
        } else {
1371
            return 1;
1372
        }
1373
    } else {
1374
        $extensions = explode(';', strtolower(api_get_setting('upload_extensions_whitelist')));
1375
        $skip = api_get_setting('upload_extensions_skip');
1376
        $ext = strrchr($filename, '.');
1377
        $ext = substr($ext, 1);
1378
        if (empty($ext)) {
1379
            return 1; // Accept empty extensions
1380
        }
1381
        if (!in_array(strtolower($ext), $extensions)) {
1382
            if ($skip == 'true') {
1383
                return 0;
1384
            } else {
1385
                $new_ext = api_get_setting('upload_extensions_replace_by');
1386
                $filename = str_replace('.'.$ext, '.'.$new_ext, $filename);
1387
1388
                return 1;
1389
            }
1390
        } else {
1391
            return 1;
1392
        }
1393
    }
1394
}
1395
1396
/**
1397
 * Adds a new document to the database.
1398
 *
1399
 * @param array  $courseInfo
1400
 * @param string $path
1401
 * @param string $fileType
1402
 * @param int    $fileSize
1403
 * @param string $title
1404
 * @param string $comment
1405
 * @param int    $readonly
1406
 * @param bool   $saveVisibility
1407
 * @param int    $group_id         group.id
1408
 * @param int    $sessionId        Session ID, if any
1409
 * @param int    $userId           creator user id
1410
 * @param bool   $sendNotification
1411
 *
1412
 * @return int id if inserted document
1413
 */
1414
function add_document(
1415
    $courseInfo,
1416
    $path,
1417
    $fileType,
1418
    $fileSize,
1419
    $title,
1420
    $comment = null,
1421
    $readonly = 0,
1422
    $saveVisibility = true,
1423
    $group_id = 0,
1424
    $sessionId = 0,
1425
    $userId = 0,
1426
    $sendNotification = true
1427
) {
1428
    $sessionId = empty($sessionId) ? api_get_session_id() : $sessionId;
1429
    $userId = empty($userId) ? api_get_user_id() : $userId;
1430
1431
    $readonly = (int) $readonly;
1432
    $c_id = $courseInfo['real_id'];
1433
    $params = [
1434
        'c_id' => $c_id,
1435
        'path' => $path,
1436
        'filetype' => $fileType,
1437
        'size' => $fileSize,
1438
        'title' => $title,
1439
        'comment' => $comment,
1440
        'readonly' => $readonly,
1441
        'session_id' => $sessionId,
1442
    ];
1443
    $table = Database::get_course_table(TABLE_DOCUMENT);
1444
    $documentId = Database::insert($table, $params);
1445
    if ($documentId) {
1446
        $sql = "UPDATE $table SET id = iid WHERE iid = $documentId";
1447
        Database::query($sql);
1448
1449
        if ($saveVisibility) {
1450
            api_set_default_visibility(
1451
                $documentId,
1452
                TOOL_DOCUMENT,
1453
                $group_id,
1454
                $courseInfo,
1455
                $sessionId,
1456
                $userId
1457
            );
1458
        }
1459
1460
        $allowNotification = api_get_configuration_value('send_notification_when_document_added');
1461
        if ($sendNotification && $allowNotification) {
1462
            $courseTitle = $courseInfo['title'];
1463
            if (!empty($sessionId)) {
1464
                $sessionInfo = api_get_session_info($sessionId);
1465
                $courseTitle .= " ( ".$sessionInfo['name'].") ";
1466
            }
1467
1468
            $url = api_get_path(WEB_CODE_PATH).
1469
                'document/showinframes.php?cidReq='.$courseInfo['code'].'&id_session='.$sessionId.'&id='.$documentId;
1470
            $link = Display::url(basename($title), $url, ['target' => '_blank']);
1471
            $userInfo = api_get_user_info($userId);
1472
1473
            $message = sprintf(
1474
                get_lang('DocumentXHasBeenAddedToDocumentInYourCourseXByUserX'),
1475
                $link,
1476
                $courseTitle,
1477
                $userInfo['complete_name']
1478
            );
1479
            $subject = sprintf(get_lang('NewDocumentAddedToCourseX'), $courseTitle);
1480
            MessageManager::sendMessageToAllUsersInCourse($subject, $message, $courseInfo, $sessionId);
1481
        }
1482
1483
        return $documentId;
1484
    } else {
1485
        return false;
1486
    }
1487
}
1488
1489
/**
1490
 * Updates an existing document in the database
1491
 * as the file exists, we only need to change the size.
1492
 *
1493
 * @param array $_course
1494
 * @param int   $documentId
1495
 * @param int   $filesize
1496
 * @param int   $readonly
1497
 *
1498
 * @return bool true /false
1499
 */
1500
function update_existing_document($_course, $documentId, $filesize, $readonly = 0)
1501
{
1502
    $document_table = Database::get_course_table(TABLE_DOCUMENT);
1503
    $documentId = intval($documentId);
1504
    $filesize = intval($filesize);
1505
    $readonly = intval($readonly);
1506
    $course_id = $_course['real_id'];
1507
1508
    $sql = "UPDATE $document_table SET
1509
            size = '$filesize',
1510
            readonly = '$readonly'
1511
			WHERE c_id = $course_id AND id = $documentId";
1512
    if (Database::query($sql)) {
1513
        return true;
1514
    } else {
1515
        return false;
1516
    }
1517
}
1518
1519
/**
1520
 * This function updates the last_edit_date, last edit user id on all folders in a given path.
1521
 *
1522
 * @param array  $_course
1523
 * @param string $path
1524
 * @param int    $user_id
1525
 */
1526
function item_property_update_on_folder($_course, $path, $user_id)
1527
{
1528
    // If we are in the root, just return... no need to update anything
1529
    if ($path == '/') {
1530
        return;
1531
    }
1532
1533
    $user_id = intval($user_id);
1534
1535
    // If the given path ends with a / we remove it
1536
    $endchar = substr($path, strlen($path) - 1, 1);
1537
    if ($endchar == '/') {
1538
        $path = substr($path, 0, strlen($path) - 1);
1539
    }
1540
1541
    $table = Database::get_course_table(TABLE_ITEM_PROPERTY);
1542
1543
    // Get the time
1544
    $time = api_get_utc_datetime();
1545
1546
    // Det all paths in the given path
1547
    // /folder/subfolder/subsubfolder/file
1548
    // if file is updated, subsubfolder, subfolder and folder are updated
1549
    $exploded_path = explode('/', $path);
1550
    $course_id = api_get_course_int_id();
1551
    $newpath = '';
1552
    foreach ($exploded_path as $key => &$value) {
1553
        // We don't want a slash before our first slash
1554
        if ($key != 0) {
1555
            $newpath .= '/'.$value;
1556
            // Select ID of given folder
1557
            $folder_id = DocumentManager::get_document_id($_course, $newpath);
1558
1559
            if ($folder_id) {
1560
                $sql = "UPDATE $table SET
1561
				        lastedit_date = '$time',
1562
				        lastedit_type = 'DocumentInFolderUpdated', 
1563
				        lastedit_user_id='$user_id'
1564
						WHERE 
1565
						    c_id = $course_id AND 
1566
						    tool='".TOOL_DOCUMENT."' AND 
1567
						    ref = '$folder_id'";
1568
                Database::query($sql);
1569
            }
1570
        }
1571
    }
1572
}
1573
1574
/**
1575
 * Adds file to document table in database
1576
 * deprecated: use file_set_default_settings instead.
1577
 *
1578
 * @author	Olivier Cauberghe <[email protected]>
1579
 *
1580
 * @param	path,filename
1581
 * action:	Adds an entry to the document table with the default settings
1582
 */
1583
function set_default_settings($upload_path, $filename, $filetype = 'file')
1584
{
1585
    $dbTable = Database::get_course_table(TABLE_DOCUMENT);
1586
    global $default_visibility;
1587
1588
    if (!$default_visibility) {
1589
        $default_visibility = 'v';
1590
    }
1591
    $filetype = Database::escape_string($filetype);
1592
1593
    $upload_path = str_replace('\\', '/', $upload_path);
1594
    $upload_path = str_replace('//', '/', $upload_path);
1595
1596
    if ($upload_path == '/') {
1597
        $upload_path = '';
1598
    } elseif (!empty($upload_path) && $upload_path[0] != '/') {
1599
        $upload_path = "/$upload_path";
1600
    }
1601
1602
    $endchar = substr($filename, strlen($filename) - 1, 1);
1603
1604
    if ($endchar == '/') {
1605
        $filename = substr($filename, 0, -1);
1606
    }
1607
    $filename = Database::escape_string($filename);
1608
    $query = "SELECT count(*) as bestaat FROM $dbTable
1609
              WHERE path='$upload_path/$filename'";
1610
    $result = Database::query($query);
1611
    $row = Database::fetch_array($result);
1612
    if ($row['bestaat'] > 0) {
1613
        $query = "UPDATE $dbTable SET
1614
		            path='$upload_path/$filename',
1615
		            visibility='$default_visibility',
1616
		            filetype='$filetype'
1617
		          WHERE path='$upload_path/$filename'";
1618
    } else {
1619
        $query = "INSERT INTO $dbTable (path,visibility,filetype)
1620
		          VALUES('$upload_path/$filename','$default_visibility','$filetype')";
1621
    }
1622
    Database::query($query);
1623
}
1624
1625
/**
1626
 * Retrieves the image path list in a html file.
1627
 *
1628
 * @author Hugues Peeters <[email protected]>
1629
 *
1630
 * @param string $html_file
1631
 *
1632
 * @return array -  images path list
1633
 */
1634
function search_img_from_html($html_file)
1635
{
1636
    $img_path_list = [];
1637
1638
    if (!$fp = fopen($html_file, 'r')) {
1639
        return;
1640
    }
1641
1642
    // Aearch and store occurences of the <img> tag in an array
1643
    $size_file = (filesize($html_file) === 0) ? 1 : filesize($html_file);
1644
    if (isset($fp) && $fp !== false) {
1645
        $buffer = fread($fp, $size_file);
1646
        if (strlen($buffer) >= 0 && $buffer !== false) {
1647
        } else {
1648
            exit('<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...
1649
        }
1650
    } else {
1651
        exit('<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...
1652
    }
1653
    $matches = [];
1654
    if (preg_match_all('~<[[:space:]]*img[^>]*>~i', $buffer, $matches)) {
1655
        $img_tag_list = $matches[0];
1656
    }
1657
1658
    fclose($fp);
1659
    unset($buffer);
1660
1661
    // Search the image file path from all the <IMG> tag detected
1662
1663
    if (sizeof($img_tag_list) > 0) {
1664
        foreach ($img_tag_list as &$this_img_tag) {
1665
            if (preg_match('~src[[:space:]]*=[[:space:]]*[\"]{1}([^\"]+)[\"]{1}~i', $this_img_tag, $matches)) {
1666
                $img_path_list[] = $matches[1];
1667
            }
1668
        }
1669
        $img_path_list = array_unique($img_path_list); // Remove duplicate entries
1670
    }
1671
1672
    return $img_path_list;
1673
}
1674
1675
/**
1676
 * Creates a new directory trying to find a directory name
1677
 * that doesn't already exist.
1678
 *
1679
 * @author  Hugues Peeters <[email protected]>
1680
 * @author  Bert Vanderkimpen
1681
 *
1682
 * @param array  $_course                 current course information
1683
 * @param int    $user_id                 current user id
1684
 * @param int    $session_id
1685
 * @param int    $to_group_id             group.id
1686
 * @param int    $to_user_id
1687
 * @param string $base_work_dir           /var/www/chamilo/courses/ABC/document
1688
 * @param string $desired_dir_name        complete path of the desired name
1689
 *                                        Example: /folder1/folder2
1690
 * @param string $title                   "folder2"
1691
 * @param int    $visibility              (0 for invisible, 1 for visible, 2 for deleted)
1692
 * @param bool   $generateNewNameIfExists
1693
 * @param bool   $sendNotification        depends in conf setting "send_notification_when_document_added"
1694
 *
1695
 * @return string actual directory name if it succeeds,
1696
 *                boolean false otherwise
1697
 */
1698
function create_unexisting_directory(
1699
    $_course,
1700
    $user_id,
1701
    $session_id,
1702
    $to_group_id,
1703
    $to_user_id,
1704
    $base_work_dir,
1705
    $desired_dir_name,
1706
    $title = '',
1707
    $visibility = '',
1708
    $generateNewNameIfExists = false,
1709
    $sendNotification = true
1710
) {
1711
    $course_id = $_course['real_id'];
1712
    $session_id = (int) $session_id;
1713
1714
    $folderExists = DocumentManager::folderExists(
1715
        $desired_dir_name,
1716
        $_course,
1717
        $session_id,
1718
        $to_group_id
1719
    );
1720
1721
    if ($folderExists === true) {
1722
        if ($generateNewNameIfExists) {
1723
            $counter = 1;
1724
            while (1) {
1725
                $folderExists = DocumentManager::folderExists(
1726
                    $desired_dir_name.'_'.$counter,
1727
                    $_course,
1728
                    $session_id,
1729
                    $to_group_id
1730
                );
1731
1732
                if ($folderExists === false) {
1733
                    break;
1734
                }
1735
                $counter++;
1736
            }
1737
            $desired_dir_name = $desired_dir_name.'_'.$counter;
1738
        } else {
1739
            return false;
1740
        }
1741
    }
1742
1743
    $systemFolderName = $desired_dir_name;
1744
1745
    // Adding suffix
1746
    $suffix = DocumentManager::getDocumentSuffix(
1747
        $_course,
1748
        $session_id,
1749
        $to_group_id
1750
    );
1751
1752
    $systemFolderName .= $suffix;
1753
1754
    if ($title == null) {
1755
        $title = basename($desired_dir_name);
1756
    }
1757
1758
    if (!is_dir($base_work_dir.$systemFolderName)) {
1759
        $result = @mkdir(
1760
            $base_work_dir.$systemFolderName,
1761
            api_get_permissions_for_new_directories(),
1762
            true
1763
        );
1764
1765
        if ($result) {
1766
            // Check if pathname already exists inside document table
1767
            $tbl_document = Database::get_course_table(TABLE_DOCUMENT);
1768
            $sql = "SELECT id, path FROM $tbl_document
1769
                    WHERE
1770
                        c_id = $course_id AND
1771
                        (
1772
                            path = '".Database::escape_string($systemFolderName)."'
1773
                        )
1774
            ";
1775
1776
            $groupInfo = [];
1777
            if (!empty($to_group_id)) {
1778
                $groupInfo = GroupManager::get_group_properties($to_group_id);
1779
            }
1780
1781
            $rs = Database::query($sql);
1782
            if (Database::num_rows($rs) == 0) {
1783
                $document_id = add_document(
1784
                    $_course,
1785
                    $systemFolderName,
1786
                    'folder',
1787
                    0,
1788
                    $title,
1789
                    null,
1790
                    0,
1791
                    true,
1792
                    $to_group_id,
1793
                    $session_id,
1794
                    $user_id,
1795
                    $sendNotification
1796
                );
1797
1798
                if ($document_id) {
1799
                    $lastEditType = [
1800
                        0 => 'invisible',
1801
                        1 => 'visible',
1802
                        2 => 'delete',
1803
                    ];
1804
                    // Update document item_property
1805
                    if (isset($lastEditType[$visibility])) {
1806
                        api_item_property_update(
1807
                            $_course,
1808
                            TOOL_DOCUMENT,
1809
                            $document_id,
1810
                            $lastEditType[$visibility],
1811
                            $user_id,
1812
                            $groupInfo,
1813
                            $to_user_id,
1814
                            null,
1815
                            null,
1816
                            $session_id
1817
                        );
1818
                    } else {
1819
                        api_item_property_update(
1820
                            $_course,
1821
                            TOOL_DOCUMENT,
1822
                            $document_id,
1823
                            'FolderCreated',
1824
                            $user_id,
1825
                            $groupInfo,
1826
                            $to_user_id,
1827
                            null,
1828
                            null,
1829
                            $session_id
1830
                        );
1831
                    }
1832
1833
                    $documentData = DocumentManager::get_document_data_by_id(
1834
                        $document_id,
1835
                        $_course['code'],
1836
                        false,
1837
                        $session_id
1838
                    );
1839
1840
                    return $documentData;
1841
                }
1842
            } else {
1843
                $document = Database::fetch_array($rs);
1844
                $documentData = DocumentManager::get_document_data_by_id(
1845
                    $document['id'],
1846
                    $_course['code'],
1847
                    false,
1848
                    $session_id
1849
                );
1850
1851
                /* This means the folder NOT exist in the filesystem
1852
                 (now this was created) but there is a record in the Database*/
1853
1854
                return $documentData;
1855
            }
1856
        }
1857
    }
1858
1859
    return false;
1860
}
1861
1862
/**
1863
 * Handles uploaded missing images.
1864
 *
1865
 * @author Hugues Peeters <[email protected]>
1866
 * @author Bert Vanderkimpen
1867
 *
1868
 * @param array  $_course
1869
 * @param array  $uploaded_file_collection - follows the $_FILES Structure
1870
 * @param string $base_work_dir
1871
 * @param string $missing_files_dir
1872
 * @param int    $user_id
1873
 * @param int    $to_group_id              group.id
1874
 */
1875
function move_uploaded_file_collection_into_directory(
1876
    $_course,
1877
    $uploaded_file_collection,
1878
    $base_work_dir,
1879
    $missing_files_dir,
1880
    $user_id,
1881
    $to_group_id,
1882
    $to_user_id,
1883
    $max_filled_space
1884
) {
1885
    $number_of_uploaded_images = count($uploaded_file_collection['name']);
1886
    $list = [];
1887
    for ($i = 0; $i < $number_of_uploaded_images; $i++) {
1888
        $missing_file['name'] = $uploaded_file_collection['name'][$i];
1889
        $missing_file['type'] = $uploaded_file_collection['type'][$i];
1890
        $missing_file['tmp_name'] = $uploaded_file_collection['tmp_name'][$i];
1891
        $missing_file['error'] = $uploaded_file_collection['error'][$i];
1892
        $missing_file['size'] = $uploaded_file_collection['size'][$i];
1893
1894
        $upload_ok = process_uploaded_file($missing_file);
1895
        if ($upload_ok) {
1896
            $list[] = handle_uploaded_document(
1897
                $_course,
1898
                $missing_file,
1899
                $base_work_dir,
1900
                $missing_files_dir,
1901
                $user_id,
1902
                $to_group_id,
1903
                $to_user_id,
1904
                $max_filled_space,
1905
                0,
1906
                'overwrite'
1907
            );
1908
        }
1909
        unset($missing_file);
1910
    }
1911
1912
    return $list;
1913
}
1914
1915
/**
1916
 * Opens the old html file and replace the src path into the img tag
1917
 * This also works for files in subdirectories.
1918
 *
1919
 * @param $original_img_path is an array
1920
 * @param $new_img_path is an array
1921
 */
1922
function replace_img_path_in_html_file($original_img_path, $new_img_path, $html_file)
1923
{
1924
    // Open the file
1925
    $fp = fopen($html_file, 'r');
1926
    $buffer = fread($fp, filesize($html_file));
1927
    $new_html_content = '';
1928
1929
    // Fix the image tags
1930
    for ($i = 0, $fileNb = count($original_img_path); $i < $fileNb; $i++) {
1931
        $replace_what = $original_img_path[$i];
1932
        // We only need the directory and the filename /path/to/file_html_files/missing_file.gif -> file_html_files/missing_file.gif
1933
        $exploded_file_path = explode('/', $new_img_path[$i]);
1934
        $replace_by = $exploded_file_path[count($exploded_file_path) - 2].'/'.$exploded_file_path[count($exploded_file_path) - 1];
1935
        $buffer = str_replace($replace_what, $replace_by, $buffer);
1936
    }
1937
1938
    $new_html_content .= $buffer;
1939
1940
    @fclose($fp);
1941
1942
    // Write the resulted new file
1943
1944
    if (!$fp = fopen($html_file, 'w')) {
1945
        return;
1946
    }
1947
1948
    if (!fwrite($fp, $new_html_content)) {
1949
        return;
1950
    }
1951
}
1952
1953
/**
1954
 * Checks the extension of a file, if it's .htm or .html
1955
 * we use search_img_from_html to get all image paths in the file.
1956
 *
1957
 * @param string $file
1958
 *
1959
 * @return array paths
1960
 *
1961
 * @see check_for_missing_files() uses search_img_from_html()
1962
 */
1963
function check_for_missing_files($file)
1964
{
1965
    if (strrchr($file, '.') == '.htm' || strrchr($file, '.') == '.html') {
1966
        $img_file_path = search_img_from_html($file);
1967
1968
        return $img_file_path;
1969
    }
1970
1971
    return false;
1972
}
1973
1974
/**
1975
 * This function builds a form that asks for the missing images in a html file
1976
 * maybe we should do this another way?
1977
 *
1978
 * @param array  $missing_files
1979
 * @param string $upload_path
1980
 * @param string $file_name
1981
 *
1982
 * @return string the form
1983
 */
1984
function build_missing_files_form($missing_files, $upload_path, $file_name)
1985
{
1986
    // Do we need a / or not?
1987
    $added_slash = ($upload_path == '/') ? '' : '/';
1988
    $folder_id = DocumentManager::get_document_id(api_get_course_info(), $upload_path);
1989
    // Build the form
1990
    $form = "<p><strong>".get_lang('MissingImagesDetected')."</strong></p>"
1991
        ."<form method=\"post\" action=\"".api_get_self()."\" enctype=\"multipart/form-data\">"
1992
        // Related_file is the path to the file that has missing images
1993
        ."<input type=\"hidden\" name=\"related_file\" value=\"".$upload_path.$added_slash.$file_name."\" />"
1994
        ."<input type=\"hidden\" name=\"upload_path\" value=\"".$upload_path."\" />"
1995
        ."<input type=\"hidden\" name=\"id\" value=\"".$folder_id."\" />"
1996
        ."<table border=\"0\">";
1997
    foreach ($missing_files as &$this_img_file_path) {
1998
        $form .= "<tr>"
1999
            ."<td>".basename($this_img_file_path)." : </td>"
2000
            ."<td>"
2001
            ."<input type=\"file\" name=\"img_file[]\"/>"
2002
            ."<input type=\"hidden\" name=\"img_file_path[]\" value=\"".$this_img_file_path."\" />"
2003
            ."</td>"
2004
            ."</tr>";
2005
    }
2006
    $form .= "</table>"
2007
        ."<button type='submit' name=\"cancel_submit_image\" value=\"".get_lang('Cancel')."\" class=\"cancel\">".get_lang('Cancel')."</button>"
2008
        ."<button type='submit' name=\"submit_image\" value=\"".get_lang('Ok')."\" class=\"save\">".get_lang('Ok')."</button>"
2009
        ."</form>";
2010
2011
    return $form;
2012
}
2013
2014
/**
2015
 * This recursive function can be used during the upgrade process form older
2016
 * versions of Chamilo
2017
 * It crawls the given directory, checks if the file is in the DB and adds
2018
 * it if it's not.
2019
 *
2020
 * @param array  $courseInfo
2021
 * @param array  $userInfo
2022
 * @param string $base_work_dir    course document dir
2023
 * @param string $folderPath       folder to read
2024
 * @param int    $sessionId
2025
 * @param int    $groupId          group.id
2026
 * @param bool   $output
2027
 * @param array  $parent
2028
 * @param string $whatIfFileExists
2029
 *
2030
 * @return bool
2031
 */
2032
function add_all_documents_in_folder_to_database(
2033
    $courseInfo,
2034
    $userInfo,
2035
    $base_work_dir,
2036
    $folderPath,
2037
    $sessionId = 0,
2038
    $groupId = 0,
2039
    $output = false,
2040
    $parent = [],
2041
    $whatIfFileExists = 'overwrite'
2042
) {
2043
    if (empty($userInfo) || empty($courseInfo)) {
2044
        return false;
2045
    }
2046
2047
    $userId = $userInfo['user_id'];
2048
2049
    // Open dir
2050
    $handle = opendir($folderPath);
2051
2052
    if (is_dir($folderPath)) {
2053
        // Run trough
2054
        while ($file = readdir($handle)) {
2055
            if ($file == '.' || $file == '..') {
2056
                continue;
2057
            }
2058
2059
            $parentPath = '';
2060
            if (!empty($parent) && isset($parent['path'])) {
2061
                $parentPath = $parent['path'];
2062
                if ($parentPath == '/') {
2063
                    $parentPath = '';
2064
                }
2065
            }
2066
2067
            $completePath = $parentPath.'/'.$file;
2068
            $sysFolderPath = $folderPath.'/'.$file;
2069
2070
            // Is directory?
2071
            if (is_dir($sysFolderPath)) {
2072
                $folderExists = DocumentManager::folderExists(
2073
                    $completePath,
2074
                    $courseInfo,
2075
                    $sessionId,
2076
                    $groupId
2077
                );
2078
2079
                if ($folderExists === true) {
2080
                    switch ($whatIfFileExists) {
2081
                        case 'overwrite':
2082
                            $documentId = DocumentManager::get_document_id($courseInfo, $completePath, $sessionId);
2083
                            if ($documentId) {
2084
                                $newFolderData = DocumentManager::get_document_data_by_id(
2085
                                    $documentId,
2086
                                    $courseInfo['code'],
2087
                                    false,
2088
                                    $sessionId
2089
                                );
2090
                            }
2091
                            break;
2092
                        case 'rename':
2093
                            $newFolderData = create_unexisting_directory(
2094
                                $courseInfo,
2095
                                $userId,
2096
                                $sessionId,
2097
                                $groupId,
2098
                                null,
2099
                                $base_work_dir,
2100
                                $completePath,
2101
                                null,
2102
                                null,
2103
                                true
2104
                            );
2105
                            break;
2106
                        case 'nothing':
2107
                            if ($output) {
2108
                                $documentId = DocumentManager::get_document_id($courseInfo, $completePath, $sessionId);
2109
                                if ($documentId) {
2110
                                    $folderData = DocumentManager::get_document_data_by_id(
2111
                                        $documentId,
2112
                                        $courseInfo['code'],
2113
                                        false,
2114
                                        $sessionId
2115
                                    );
2116
                                    Display::addFlash(
2117
                                        Display::return_message(
2118
                                            $folderData['path'].' '.get_lang('UplAlreadyExists'),
2119
                                            'warning'
2120
                                        )
2121
                                    );
2122
                                }
2123
                            }
2124
                            continue 2;
2125
                            break;
2126
                    }
2127
                } else {
2128
                    $newFolderData = create_unexisting_directory(
2129
                        $courseInfo,
2130
                        $userId,
2131
                        $sessionId,
2132
                        $groupId,
2133
                        null,
2134
                        $base_work_dir,
2135
                        $completePath,
2136
                        null,
2137
                        null,
2138
                        false
2139
                    );
2140
                }
2141
2142
                // Recursive
2143
                add_all_documents_in_folder_to_database(
2144
                    $courseInfo,
2145
                    $userInfo,
2146
                    $base_work_dir,
2147
                    $sysFolderPath,
2148
                    $sessionId,
2149
                    $groupId,
2150
                    $output,
2151
                    $newFolderData,
2152
                    $whatIfFileExists
2153
                );
2154
            } else {
2155
                // Rename
2156
                $uploadedFile = [
2157
                    'name' => $file,
2158
                    'tmp_name' => $sysFolderPath,
2159
                    'size' => filesize($sysFolderPath),
2160
                    'type' => null,
2161
                    'from_file' => true,
2162
                    'move_file' => true,
2163
                ];
2164
2165
                handle_uploaded_document(
2166
                    $courseInfo,
2167
                    $uploadedFile,
2168
                    $base_work_dir,
2169
                    $parentPath,
2170
                    $userId,
2171
                    $groupId,
2172
                    null,
2173
                    0,
2174
                    $whatIfFileExists,
2175
                    $output,
2176
                    false,
2177
                    null,
2178
                    $sessionId
2179
                );
2180
            }
2181
        }
2182
    }
2183
}
2184