Passed
Push — 1.11.x ( 977fbd...c674ba )
by Julito
72:46
created

cleanZipFilesNoRename()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

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