Passed
Push — master ( 08314e...a4ad40 )
by Julito
10:14
created

handle_uploaded_document()   F

Complexity

Conditions 40
Paths 2913

Size

Total Lines 367
Code Lines 190

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 40
eloc 190
nc 2913
nop 17
dl 0
loc 367
rs 0
c 1
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A cleanZipFilesAllowHtaccess() 0 24 3
A clean_up_path() 0 19 4
A cleanZipFilesNoRename() 0 18 2
A clean_up_files_in_zip() 0 18 2
B filter_extension() 0 46 9

How to fix   Long Method    Complexity    Many Parameters   

Long Method

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

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

Commonly applied refactorings include:

Many Parameters

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

There are several approaches to avoid long parameter lists:

1
<?php
2
/* For licensing terms, see /license.txt */
3
4
use Chamilo\CoreBundle\Entity\ResourceLink;
5
use Chamilo\CoreBundle\Framework\Container;
6
use Chamilo\CourseBundle\Entity\CDocument;
7
use Symfony\Component\HttpFoundation\File\UploadedFile;
8
9
/**
10
 * Changes the file name extension from .php to .phps
11
 * Useful for securing a site.
12
 *
13
 * @author Hugues Peeters <[email protected]>
14
 *
15
 * @param string $file_name Name of a file
16
 *
17
 * @return string the filename phps'ized
18
 */
19
function php2phps($file_name)
20
{
21
    return preg_replace('/\.(phar.?|php.?|phtml.?)(\.){0,1}.*$/i', '.phps', $file_name);
22
}
23
24
/**
25
 * Renames .htaccess & .HTACCESS to htaccess.txt.
26
 *
27
 * @param string $filename
28
 *
29
 * @return string
30
 */
31
function htaccess2txt($filename)
32
{
33
    return str_replace(['.htaccess', '.HTACCESS'], ['htaccess.txt', 'htaccess.txt'], $filename);
34
}
35
36
/**
37
 * This function executes our safety precautions
38
 * more functions can be added.
39
 *
40
 * @param string $filename
41
 *
42
 * @return string
43
 *
44
 * @see php2phps()
45
 * @see htaccess2txt()
46
 */
47
function disable_dangerous_file($filename)
48
{
49
    return htaccess2txt(php2phps($filename));
50
}
51
52
/**
53
 * Returns the name without extension, used for the title.
54
 *
55
 * @param string $name
56
 *
57
 * @return name without the extension
58
 */
59
function get_document_title($name)
60
{
61
    // If they upload .htaccess...
62
    $name = disable_dangerous_file($name);
63
    $ext = substr(strrchr($name, '.'), 0);
64
65
    if (empty($ext)) {
66
        return substr($name, 0, strlen($name));
67
    }
68
69
    return substr($name, 0, strlen($name) - strlen(strstr($name, $ext)));
70
}
71
72
/**
73
 * This function checks if the upload succeeded.
74
 *
75
 * @return true if upload succeeded
76
 */
77
function process_uploaded_file($uploadedFileData, $show_output = true)
78
{
79
    $uploadedFile = [];
80
    if ($uploadedFileData instanceof UploadedFile) {
81
        $uploadedFile['error'] = $uploadedFileData->getError();
82
        $uploadedFile['tmp_name'] = $uploadedFileData->getPathname();
83
        $uploadedFile['size'] = $uploadedFileData->getSize();
84
    } else {
85
        $uploadedFile = $uploadedFileData;
86
    }
87
88
    // Checking the error code sent with the file upload.
89
    if (isset($uploadedFile['error'])) {
90
        switch ($uploadedFile['error']) {
91
            case 1:
92
                // The uploaded file exceeds the upload_max_filesize directive in php.ini.
93
                if ($show_output) {
94
                    Display::addFlash(
95
                        Display::return_message(
96
                            get_lang('The uploaded file exceeds the maximum filesize allowed by the server:').ini_get('upload_max_filesize'),
97
                            'error'
98
                        )
99
                    );
100
                }
101
102
                return false;
103
            case 2:
104
                // The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.
105
                // Not used at the moment, but could be handy if we want to limit the size of an upload
106
                // (e.g. image upload in html editor).
107
                $max_file_size = (int) $_POST['MAX_FILE_SIZE'];
108
                if ($show_output) {
109
                    Display::addFlash(
110
                        Display::return_message(
111
                            get_lang('The file size exceeds the maximum allowed setting:').format_file_size($max_file_size),
112
                            'error'
113
                        )
114
                    );
115
                }
116
117
                return false;
118
            case 3:
119
                // The uploaded file was only partially uploaded.
120
                if ($show_output) {
121
                    Display::addFlash(
122
                        Display::return_message(
123
                            get_lang('The uploaded file was only partially uploaded.').' '.get_lang('Please Try Again!'),
124
                            'error'
125
                        )
126
                    );
127
                }
128
129
                return false;
130
            case 4:
131
                // No file was uploaded.
132
                if ($show_output) {
133
                    Display::addFlash(
134
                        Display::return_message(
135
                            get_lang('No file was uploaded.').' '.get_lang('Please select a file before pressing the upload button.'),
136
                            'error'
137
                        )
138
                    );
139
                }
140
141
                return false;
142
        }
143
    }
144
145
    if (!file_exists($uploadedFile['tmp_name'])) {
146
        // No file was uploaded.
147
        if ($show_output) {
148
            Display::addFlash(Display::return_message(get_lang('The file upload has failed.'), 'error'));
149
        }
150
151
        return false;
152
    }
153
154
    if (file_exists($uploadedFile['tmp_name'])) {
155
        $filesize = filesize($uploadedFile['tmp_name']);
156
        if (empty($filesize)) {
157
            // No file was uploaded.
158
            if ($show_output) {
159
                Display::addFlash(
160
                    Display::return_message(
161
                        get_lang('The file upload has failed.SizeIsZero'),
162
                        'error'
163
                    )
164
                );
165
            }
166
167
            return false;
168
        }
169
    }
170
171
    $course_id = api_get_course_id();
172
173
    //Checking course quota if we are in a course
174
    if (!empty($course_id)) {
175
        $max_filled_space = DocumentManager::get_course_quota();
176
        // Check if there is enough space to save the file
177
        if (!DocumentManager::enough_space($uploadedFile['size'], $max_filled_space)) {
178
            if ($show_output) {
179
                Display::addFlash(
180
                    Display::return_message(
181
                        get_lang('There is not enough space to upload this file.'),
182
                        'error'
183
                    )
184
                );
185
            }
186
187
            return false;
188
        }
189
    }
190
191
    // case 0: default: We assume there is no error, the file uploaded with success.
192
    return true;
193
}
194
195
/**
196
 * Tries to add an extension to files without extension
197
 * Some applications on Macintosh computers don't add an extension to the files.
198
 * This subroutine try to fix this on the basis of the MIME type sent
199
 * by the browser.
200
 *
201
 * Note : some browsers don't send the MIME Type (e.g. Netscape 4).
202
 *        We don't have solution for this kind of situation
203
 *
204
 * @author Hugues Peeters <[email protected]>
205
 * @author Bert Vanderkimpen
206
 *
207
 * @param string $file_name Name of the file
208
 * @param string $file_type Type of the file
209
 *
210
 * @return string File name
211
 */
212
function add_ext_on_mime($file_name, $file_type)
213
{
214
    // Check whether the file has an extension AND whether the browser has sent a MIME Type
215
216
    if (!preg_match('/^.*\.[a-zA-Z_0-9]+$/', $file_name) && $file_type) {
217
        // Build a "MIME-types / extensions" connection table
218
        static $mime_type = [];
219
220
        $mime_type[] = 'application/msword';
221
        $extension[] = '.doc';
222
        $mime_type[] = 'application/rtf';
223
        $extension[] = '.rtf';
224
        $mime_type[] = 'application/vnd.ms-powerpoint';
225
        $extension[] = '.ppt';
226
        $mime_type[] = 'application/vnd.ms-excel';
227
        $extension[] = '.xls';
228
        $mime_type[] = 'application/pdf';
229
        $extension[] = '.pdf';
230
        $mime_type[] = 'application/postscript';
231
        $extension[] = '.ps';
232
        $mime_type[] = 'application/mac-binhex40';
233
        $extension[] = '.hqx';
234
        $mime_type[] = 'application/x-gzip';
235
        $extension[] = 'tar.gz';
236
        $mime_type[] = 'application/x-shockwave-flash';
237
        $extension[] = '.swf';
238
        $mime_type[] = 'application/x-stuffit';
239
        $extension[] = '.sit';
240
        $mime_type[] = 'application/x-tar';
241
        $extension[] = '.tar';
242
        $mime_type[] = 'application/zip';
243
        $extension[] = '.zip';
244
        $mime_type[] = 'application/x-tar';
245
        $extension[] = '.tar';
246
        $mime_type[] = 'text/html';
247
        $extension[] = '.html';
248
        $mime_type[] = 'text/plain';
249
        $extension[] = '.txt';
250
        $mime_type[] = 'text/rtf';
251
        $extension[] = '.rtf';
252
        $mime_type[] = 'img/gif';
253
        $extension[] = '.gif';
254
        $mime_type[] = 'img/jpeg';
255
        $extension[] = '.jpg';
256
        $mime_type[] = 'img/png';
257
        $extension[] = '.png';
258
        $mime_type[] = 'audio/midi';
259
        $extension[] = '.mid';
260
        $mime_type[] = 'audio/mpeg';
261
        $extension[] = '.mp3';
262
        $mime_type[] = 'audio/x-aiff';
263
        $extension[] = '.aif';
264
        $mime_type[] = 'audio/x-pn-realaudio';
265
        $extension[] = '.rm';
266
        $mime_type[] = 'audio/x-pn-realaudio-plugin';
267
        $extension[] = '.rpm';
268
        $mime_type[] = 'audio/x-wav';
269
        $extension[] = '.wav';
270
        $mime_type[] = 'video/mpeg';
271
        $extension[] = '.mpg';
272
        $mime_type[] = 'video/mpeg4-generic';
273
        $extension[] = '.mp4';
274
        $mime_type[] = 'video/quicktime';
275
        $extension[] = '.mov';
276
        $mime_type[] = 'video/x-msvideo';
277
        $extension[] = '.avi';
278
279
        $mime_type[] = 'video/x-ms-wmv';
280
        $extension[] = '.wmv';
281
        $mime_type[] = 'video/x-flv';
282
        $extension[] = '.flv';
283
        $mime_type[] = 'image/svg+xml';
284
        $extension[] = '.svg';
285
        $mime_type[] = 'image/svg+xml';
286
        $extension[] = '.svgz';
287
        $mime_type[] = 'video/ogg';
288
        $extension[] = '.ogv';
289
        $mime_type[] = 'audio/ogg';
290
        $extension[] = '.oga';
291
        $mime_type[] = 'application/ogg';
292
        $extension[] = '.ogg';
293
        $mime_type[] = 'application/ogg';
294
        $extension[] = '.ogx';
295
        $mime_type[] = 'application/x-freemind';
296
        $extension[] = '.mm';
297
298
        $mime_type[] = 'application/vnd.ms-word.document.macroEnabled.12';
299
        $extension[] = '.docm';
300
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
301
        $extension[] = '.docx';
302
        $mime_type[] = 'application/vnd.ms-word.template.macroEnabled.12';
303
        $extension[] = '.dotm';
304
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.wordprocessingml.template';
305
        $extension[] = '.dotx';
306
        $mime_type[] = 'application/vnd.ms-powerpoint.template.macroEnabled.12';
307
        $extension[] = '.potm';
308
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.presentationml.template';
309
        $extension[] = '.potx';
310
        $mime_type[] = 'application/vnd.ms-powerpoint.addin.macroEnabled.12';
311
        $extension[] = '.ppam';
312
        $mime_type[] = 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12';
313
        $extension[] = '.ppsm';
314
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.presentationml.slideshow';
315
        $extension[] = '.ppsx';
316
        $mime_type[] = 'application/vnd.ms-powerpoint.presentation.macroEnabled.12';
317
        $extension[] = '.pptm';
318
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.presentationml.presentation';
319
        $extension[] = '.pptx';
320
        $mime_type[] = 'application/vnd.ms-excel.addin.macroEnabled.12';
321
        $extension[] = '.xlam';
322
        $mime_type[] = 'application/vnd.ms-excel.sheet.binary.macroEnabled.12';
323
        $extension[] = '.xlsb';
324
        $mime_type[] = 'application/vnd.ms-excel.sheet.macroEnabled.12';
325
        $extension[] = '.xlsm';
326
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
327
        $extension[] = '.xlsx';
328
        $mime_type[] = 'application/vnd.ms-excel.template.macroEnabled.12';
329
        $extension[] = '.xltm';
330
        $mime_type[] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.template';
331
        $extension[] = '.xltx';
332
333
        // Test on PC (files with no extension get application/octet-stream)
334
        //$mime_type[] = 'application/octet-stream';      $extension[] = '.ext';
335
        // Check whether the MIME type sent by the browser is within the table
336
        foreach ($mime_type as $key => &$type) {
337
            if ($type == $file_type) {
338
                $file_name .= $extension[$key];
339
                break;
340
            }
341
        }
342
343
        unset($mime_type, $extension, $type, $key); // Delete to eschew possible collisions
344
    }
345
346
    return $file_name;
347
}
348
349
/**
350
 * This function is a callback function that is used while extracting a zipfile
351
 * http://www.phpconcept.net/pclzip/man/en/index.php?options-pclzip_cb_pre_extract.
352
 *
353
 * @param array $p_event
354
 * @param array $p_header
355
 *
356
 * @return int (If the function returns 1, then the extraction is resumed, if 0 the path was skipped)
357
 */
358
function clean_up_files_in_zip($p_event, &$p_header)
359
{
360
    $originalStoredFileName = $p_header['stored_filename'];
361
    $baseName = basename($originalStoredFileName);
362
    // Skip files
363
    $skipFiles = [
364
        '__MACOSX',
365
        '.Thumbs.db',
366
        'Thumbs.db',
367
    ];
368
369
    if (in_array($baseName, $skipFiles)) {
370
        return 0;
371
    }
372
    $modifiedStoredFileName = clean_up_path($originalStoredFileName);
373
    $p_header['filename'] = str_replace($originalStoredFileName, $modifiedStoredFileName, $p_header['filename']);
374
375
    return 1;
376
}
377
378
function cleanZipFilesNoRename($p_event, &$p_header)
379
{
380
    $originalStoredFileName = $p_header['stored_filename'];
381
    $baseName = basename($originalStoredFileName);
382
    // Skip files
383
    $skipFiles = [
384
        '__MACOSX',
385
        '.Thumbs.db',
386
        'Thumbs.db',
387
    ];
388
389
    if (in_array($baseName, $skipFiles)) {
390
        return 0;
391
    }
392
    $modifiedStoredFileName = clean_up_path($originalStoredFileName, false);
393
    $p_header['filename'] = str_replace($originalStoredFileName, $modifiedStoredFileName, $p_header['filename']);
394
395
    return 1;
396
}
397
398
/**
399
 * Allow .htaccess file.
400
 *
401
 * @param $p_event
402
 * @param $p_header
403
 *
404
 * @return int
405
 */
406
function cleanZipFilesAllowHtaccess($p_event, &$p_header)
407
{
408
    $originalStoredFileName = $p_header['stored_filename'];
409
    $baseName = basename($originalStoredFileName);
410
411
    $allowFiles = ['.htaccess'];
412
    if (in_array($baseName, $allowFiles)) {
413
        return 1;
414
    }
415
416
    // Skip files
417
    $skipFiles = [
418
        '__MACOSX',
419
        '.Thumbs.db',
420
        'Thumbs.db',
421
    ];
422
423
    if (in_array($baseName, $skipFiles)) {
424
        return 0;
425
    }
426
    $modifiedStoredFileName = clean_up_path($originalStoredFileName);
427
    $p_header['filename'] = str_replace($originalStoredFileName, $modifiedStoredFileName, $p_header['filename']);
428
429
    return 1;
430
}
431
432
/**
433
 * This function cleans up a given path
434
 * by eliminating dangerous file names and cleaning them.
435
 *
436
 * @param string $path
437
 * @param bool   $replaceName
438
 *
439
 * @return string
440
 *
441
 * @see disable_dangerous_file()
442
 * @see api_replace_dangerous_char()
443
 */
444
function clean_up_path($path, $replaceName = true)
445
{
446
    // Split the path in folders and files
447
    $path_array = explode('/', $path);
448
    // Clean up every folder and filename in the path
449
    foreach ($path_array as $key => &$val) {
450
        // We don't want to lose the dots in ././folder/file (cfr. zipfile)
451
        if ('.' != $val) {
452
            if ($replaceName) {
453
                $val = api_replace_dangerous_char($val);
454
            }
455
            $val = disable_dangerous_file($val);
456
        }
457
    }
458
    // Join the "cleaned" path (modified in-place as passed by reference)
459
    $path = implode('/', $path_array);
460
    filter_extension($path);
461
462
    return $path;
463
}
464
465
/**
466
 * Checks if the file is dangerous, based on extension and/or mimetype.
467
 * The list of extensions accepted/rejected can be found from
468
 * api_get_setting('upload_extensions_exclude') and api_get_setting('upload_extensions_include').
469
 *
470
 * @param string $filename passed by reference. The filename will be modified
471
 *                         if filter rules say so! (you can include path but the filename should look like 'abc.html')
472
 *
473
 * @return int 0 to skip file, 1 to keep file
474
 */
475
function filter_extension(&$filename)
476
{
477
    if ('/' == substr($filename, -1)) {
478
        return 1; // Authorize directories
479
    }
480
    $blacklist = api_get_setting('upload_extensions_list_type');
481
    if ('whitelist' != $blacklist) { // if = blacklist
482
        $extensions = explode(';', strtolower(api_get_setting('upload_extensions_blacklist')));
483
484
        $skip = api_get_setting('upload_extensions_skip');
485
        $ext = strrchr($filename, '.');
486
        $ext = substr($ext, 1);
487
        if (empty($ext)) {
488
            return 1; // We're in blacklist mode, so accept empty extensions
489
        }
490
        if (in_array(strtolower($ext), $extensions)) {
491
            if ('true' == $skip) {
492
                return 0;
493
            } else {
494
                $new_ext = api_get_setting('upload_extensions_replace_by');
495
                $filename = str_replace('.'.$ext, '.'.$new_ext, $filename);
496
497
                return 1;
498
            }
499
        } else {
500
            return 1;
501
        }
502
    } else {
503
        $extensions = explode(';', strtolower(api_get_setting('upload_extensions_whitelist')));
504
        $skip = api_get_setting('upload_extensions_skip');
505
        $ext = strrchr($filename, '.');
506
        $ext = substr($ext, 1);
507
        if (empty($ext)) {
508
            return 1; // Accept empty extensions
509
        }
510
        if (!in_array(strtolower($ext), $extensions)) {
511
            if ('true' == $skip) {
512
                return 0;
513
            } else {
514
                $new_ext = api_get_setting('upload_extensions_replace_by');
515
                $filename = str_replace('.'.$ext, '.'.$new_ext, $filename);
516
517
                return 1;
518
            }
519
        } else {
520
            return 1;
521
        }
522
    }
523
}
524
525
/**
526
 * Creates a new directory trying to find a directory name
527
 * that doesn't already exist.
528
 *
529
 * @author  Hugues Peeters <[email protected]>
530
 * @author  Bert Vanderkimpen
531
 *
532
 * @param array  $_course                 current course information
533
 * @param int    $user_id                 current user id
534
 * @param int    $session_id
535
 * @param int    $to_group_id             group.id
536
 * @param int    $to_user_id
537
 * @param string $base_work_dir           /var/www/chamilo/courses/ABC/document
538
 * @param string $desired_dir_name        complete path of the desired name
539
 *                                        Example: /folder1/folder2
540
 * @param string $title                   "folder2"
541
 * @param int    $visibility              (0 for invisible, 1 for visible, 2 for deleted)
542
 * @param bool   $generateNewNameIfExists
543
 * @param bool   $sendNotification        depends in conf setting "send_notification_when_document_added"
544
 * @param array  $parentInfo
545
 *
546
 * @return CDocument|false
547
 */
548
function create_unexisting_directory(
549
    $_course,
550
    $user_id,
551
    $session_id,
552
    $to_group_id,
553
    $to_user_id,
554
    $base_work_dir,
555
    $desired_dir_name,
556
    $title = '',
557
    $visibility = '',
558
    $generateNewNameIfExists = false,
559
    $sendNotification = true,
560
    $parentInfo = null
561
) {
562
    $course_id = $_course['real_id'];
563
    $session_id = (int) $session_id;
564
565
    $parentId = 0;
566
    if (!empty($parentInfo)) {
567
        if (is_array($parentInfo) && isset($parentInfo['iid'])) {
568
            $parentId = $parentInfo['iid'];
569
        }
570
        if ($parentInfo instanceof CDocument) {
571
            $parentId = $parentInfo->getIid();
572
        }
573
    }
574
575
    $document = DocumentManager::addDocument(
576
        $_course,
577
        $desired_dir_name,
578
        'folder',
579
        0,
580
        $title,
581
        null,
582
        0,
583
        true,
584
        $to_group_id,
585
        $session_id,
586
        $user_id,
587
        $sendNotification,
588
        '',
589
        $parentId
590
    );
591
592
    if ($document) {
593
        return $document;
594
    }
595
596
    $folderExists = DocumentManager::folderExists(
597
        $desired_dir_name,
598
        $_course,
599
        $session_id,
600
        $to_group_id
601
    );
602
603
    if (true === $folderExists) {
604
        if ($generateNewNameIfExists) {
605
            $counter = 1;
606
            while (1) {
607
                $folderExists = DocumentManager::folderExists(
608
                    $desired_dir_name.'_'.$counter,
609
                    $_course,
610
                    $session_id,
611
                    $to_group_id
612
                );
613
614
                if (false === $folderExists) {
615
                    break;
616
                }
617
                $counter++;
618
            }
619
            $desired_dir_name = $desired_dir_name.'_'.$counter;
620
        }
621
    }
622
623
    $systemFolderName = $desired_dir_name;
624
625
    // Adding suffix
626
    $suffix = DocumentManager::getDocumentSuffix(
627
        $_course,
628
        $session_id,
629
        $to_group_id
630
    );
631
632
    $systemFolderName .= $suffix;
633
634
    if (null == $title) {
635
        $title = basename($desired_dir_name);
636
    }
637
638
    // Check if pathname already exists inside document table
639
    $table = Database::get_course_table(TABLE_DOCUMENT);
640
    $sql = "SELECT iid, path FROM $table
641
            WHERE
642
                c_id = $course_id AND
643
                path = '".Database::escape_string($systemFolderName)."'";
644
    $rs = Database::query($sql);
645
646
    $parentId = 0;
647
    if (!empty($parentInfo) && isset($parentInfo['iid'])) {
648
        $parentId = $parentInfo['iid'];
649
    }
650
651
    if (0 == Database::num_rows($rs)) {
652
        $document = DocumentManager::addDocument(
653
            $_course,
654
            $systemFolderName,
655
            'folder',
656
            0,
657
            $title,
658
            null,
659
            0,
660
            true,
661
            $to_group_id,
662
            $session_id,
663
            $user_id,
664
            $sendNotification,
665
            '',
666
            $parentId
667
        );
668
669
        if ($document) {
670
            return $document;
671
        }
672
    } else {
673
        $document = Database::fetch_array($rs);
674
        $documentData = DocumentManager::get_document_data_by_id(
675
            $document['iid'],
676
            $_course['code'],
677
            false,
678
            $session_id
679
        );
680
681
        if ($documentData) {
682
            $document = Container::getDocumentRepository()->find($documentData['iid']);
683
684
            return $document;
685
        }
686
    }
687
688
    return false;
689
}
690