Passed
Push — 1.11.x ( 5ed552...bb3e4b )
by Julito
10:19
created

getReplacedByExtension()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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