Passed
Push — EXTRACT_CLASSES ( 231cec...0382f2 )
by Rafael
65:54 queued 05:18
created

Documents::post()   F

Complexity

Conditions 80
Paths > 20000

Size

Total Lines 272
Code Lines 168

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 80
eloc 168
nc 383689
nop 8
dl 0
loc 272
rs 0
c 0
b 0
f 0

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
3
/* Copyright (C) 2016       Xebax Christy               <[email protected]>
4
 * Copyright (C) 2016	    Laurent Destailleur		    <[email protected]>
5
 * Copyright (C) 2016       Jean-François Ferry         <[email protected]>
6
 * Copyright (C) 2023       Romain Neil                 <[email protected]>
7
 * Copyright (C) 2024       Rafael San José             <[email protected]>
8
 *
9
 * This program is free software you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 3 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21
 */
22
23
namespace Dolibarr\Code\Api\Api;
24
25
use Luracast\Restler\RestException;
26
27
require_once constant('DOL_DOCUMENT_ROOT') . '/main.inc.php';
28
require_once constant('DOL_DOCUMENT_ROOT') . '/api/class/api.class.php';
29
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
30
31
/**
32
 * API class for receive files
33
 *
34
 * @access protected
35
 * @class Documents {@requires user,external}
36
 */
37
class Documents extends DolibarrApi
38
{
39
    /**
40
     * Constructor
41
     */
42
    public function __construct()
43
    {
44
        global $db;
45
        $this->db = $db;
46
    }
47
48
49
    /**
50
     * Download a document.
51
     *
52
     * Note that, this API is similar to using the wrapper link "documents.php" to download a file (used for
53
     * internal HTML links of documents into application), but with no need to have a session cookie (the token is used instead).
54
     *
55
     * @param   string  $modulepart     Name of module or area concerned by file download ('facture', ...)
56
     * @param   string  $original_file  Relative path with filename, relative to modulepart (for example: IN201701-999/IN201701-999.pdf)
57
     * @return  array                   List of documents
58
     *
59
     * @url GET /download
60
     *
61
     * @throws  RestException   400     Bad value for parameter modulepart or original_file
62
     * @throws  RestException   403     Access denied
63
     * @throws  RestException   404     File not found
64
     */
65
    public function index($modulepart, $original_file = '')
66
    {
67
        global $conf;
68
69
        if (empty($modulepart)) {
70
            throw new RestException(400, 'bad value for parameter modulepart');
71
        }
72
        if (empty($original_file)) {
73
            throw new RestException(400, 'bad value for parameter original_file');
74
        }
75
76
        //--- Finds and returns the document
77
        $entity = $conf->entity;
78
79
        // Special cases that need to use get_exdir to get real dir of object
80
        // If future, all object should use this to define path of documents.
81
        /*
82
        $tmpreldir = '';
83
        if ($modulepart == 'supplier_invoice') {
84
            $tmpreldir = get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier');
85
        }
86
87
        $relativefile = $tmpreldir.dol_sanitizeFileName($object->ref); */
88
        $relativefile = $original_file;
89
90
        $check_access = dol_check_secure_access_document($modulepart, $relativefile, $entity, DolibarrApiAccess::$user, '', 'read');
91
        $accessallowed = $check_access['accessallowed'];
92
        $sqlprotectagainstexternals = $check_access['sqlprotectagainstexternals'];
93
        $original_file = $check_access['original_file'];
94
95
        if (preg_match('/\.\./', $original_file) || preg_match('/[<>|]/', $original_file)) {
96
            throw new RestException(403);
97
        }
98
        if (!$accessallowed) {
99
            throw new RestException(403);
100
        }
101
102
        $filename = basename($original_file);
103
        $original_file_osencoded = dol_osencode($original_file); // New file name encoded in OS encoding charset
104
105
        if (!file_exists($original_file_osencoded)) {
106
            dol_syslog("Try to download not found file " . $original_file_osencoded, LOG_WARNING);
107
            throw new RestException(404, 'File not found');
108
        }
109
110
        $file_content = file_get_contents($original_file_osencoded);
111
        return array('filename' => $filename, 'content-type' => dol_mimetype($filename), 'filesize' => filesize($original_file), 'content' => base64_encode($file_content), 'encoding' => 'base64');
112
    }
113
114
115
    /**
116
     * Build a document.
117
     *
118
     * Test sample 1: { "modulepart": "invoice", "original_file": "FA1701-001/FA1701-001.pdf", "doctemplate": "crabe", "langcode": "fr_FR" }.
119
     *
120
     * Supported modules: invoice, order, proposal, contract, shipment
121
     *
122
     * @param   string  $modulepart     Name of module or area concerned by file download ('thirdparty', 'member', 'proposal', 'supplier_proposal', 'order', 'supplier_order', 'invoice', 'supplier_invoice', 'shipment', 'project',  ...)
123
     * @param   string  $original_file  Relative path with filename, relative to modulepart (for example: IN201701-999/IN201701-999.pdf).
124
     * @param   string  $doctemplate    Set here the doc template to use for document generation (If not set, use the default template).
125
     * @param   string  $langcode       Language code like 'en_US', 'fr_FR', 'es_ES', ... (If not set, use the default language).
126
     * @return  array                   List of documents
127
     *
128
     * @url PUT /builddoc
129
     *
130
     * @throws  RestException   400     Bad value for parameter modulepart or original_file
131
     * @throws  RestException   403     Access denied
132
     * @throws  RestException   404     Invoice, Order, Proposal, Contract or Shipment not found
133
     * @throws  RestException   500     Error generating document
134
     * @throws  RestException   501     File not found
135
     */
136
    public function builddoc($modulepart, $original_file = '', $doctemplate = '', $langcode = '')
137
    {
138
        global $conf, $langs;
139
140
        if (empty($modulepart)) {
141
            throw new RestException(400, 'bad value for parameter modulepart');
142
        }
143
        if (empty($original_file)) {
144
            throw new RestException(400, 'bad value for parameter original_file');
145
        }
146
147
        $outputlangs = $langs;
148
        if ($langcode && $langs->defaultlang != $langcode) {
149
            $outputlangs = new Translate('', $conf);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\Translate was not found. Did you mean Translate? If so, make sure to prefix the type with \.
Loading history...
150
            $outputlangs->setDefaultLang($langcode);
151
        }
152
153
        //--- Finds and returns the document
154
        $entity = $conf->entity;
155
156
        // Special cases that need to use get_exdir to get real dir of object
157
        // If future, all object should use this to define path of documents.
158
        /*
159
        $tmpreldir = '';
160
        if ($modulepart == 'supplier_invoice') {
161
            $tmpreldir = get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier');
162
        }
163
164
        $relativefile = $tmpreldir.dol_sanitizeFileName($object->ref); */
165
        $relativefile = $original_file;
166
167
        $check_access = dol_check_secure_access_document($modulepart, $relativefile, $entity, DolibarrApiAccess::$user, '', 'write');
168
        $accessallowed              = $check_access['accessallowed'];
169
        $sqlprotectagainstexternals = $check_access['sqlprotectagainstexternals'];
170
        $original_file              = $check_access['original_file'];
171
172
        if (preg_match('/\.\./', $original_file) || preg_match('/[<>|]/', $original_file)) {
173
            throw new RestException(403);
174
        }
175
        if (!$accessallowed) {
176
            throw new RestException(403);
177
        }
178
179
        // --- Generates the document
180
        $hidedetails = !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS') ? 0 : 1;
181
        $hidedesc = !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DESC') ? 0 : 1;
182
        $hideref = !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_REF') ? 0 : 1;
183
184
        $templateused = '';
185
186
        if ($modulepart == 'facture' || $modulepart == 'invoice') {
187
            require_once constant('DOL_DOCUMENT_ROOT') . '/compta/facture/class/facture.class.php';
188
            $tmpobject = new Facture($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\Facture was not found. Did you mean Facture? If so, make sure to prefix the type with \.
Loading history...
189
            $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
190
            if (!$result) {
191
                throw new RestException(404, 'Invoice not found');
192
            }
193
194
            $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
195
            $result = $tmpobject->generateDocument($templateused, $outputlangs, $hidedetails, $hidedesc, $hideref);
196
            if ($result <= 0) {
197
                throw new RestException(500, 'Error generating document');
198
            }
199
        } elseif ($modulepart == 'facture_fournisseur' || $modulepart == 'invoice_supplier') {
200
            require_once constant('DOL_DOCUMENT_ROOT') . '/fourn/class/fournisseur.facture.class.php';
201
            $tmpobject = new FactureFournisseur($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\FactureFournisseur was not found. Did you mean FactureFournisseur? If so, make sure to prefix the type with \.
Loading history...
202
            $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
203
            if (!$result) {
204
                throw new RestException(404, 'Supplier invoice not found');
205
            }
206
207
            $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
208
            $result = $tmpobject->generateDocument($templateused, $outputlangs, $hidedetails, $hidedesc, $hideref);
209
            if ($result < 0) {
210
                throw new RestException(500, 'Error generating document');
211
            }
212
        } elseif ($modulepart == 'commande' || $modulepart == 'order') {
213
            require_once constant('DOL_DOCUMENT_ROOT') . '/commande/class/commande.class.php';
214
            $tmpobject = new Commande($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\Commande was not found. Did you mean Commande? If so, make sure to prefix the type with \.
Loading history...
215
            $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
216
            if (!$result) {
217
                throw new RestException(404, 'Order not found');
218
            }
219
            $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
220
            $result = $tmpobject->generateDocument($templateused, $outputlangs, $hidedetails, $hidedesc, $hideref);
221
            if ($result <= 0) {
222
                throw new RestException(500, 'Error generating document');
223
            }
224
        } elseif ($modulepart == 'propal' || $modulepart == 'proposal') {
225
            require_once constant('DOL_DOCUMENT_ROOT') . '/comm/propal/class/propal.class.php';
226
            $tmpobject = new Propal($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\Propal was not found. Did you mean Propal? If so, make sure to prefix the type with \.
Loading history...
227
            $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
228
            if (!$result) {
229
                throw new RestException(404, 'Proposal not found');
230
            }
231
            $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
232
            $result = $tmpobject->generateDocument($templateused, $outputlangs, $hidedetails, $hidedesc, $hideref);
233
            if ($result <= 0) {
234
                throw new RestException(500, 'Error generating document');
235
            }
236
        } elseif ($modulepart == 'contrat' || $modulepart == 'contract') {
237
            require_once constant('DOL_DOCUMENT_ROOT') . '/contrat/class/contrat.class.php';
238
239
            $tmpobject = new Contrat($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\Contrat was not found. Did you mean Contrat? If so, make sure to prefix the type with \.
Loading history...
240
            $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
241
242
            if (!$result) {
243
                throw new RestException(404, 'Contract not found');
244
            }
245
246
            $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
247
            $result = $tmpobject->generateDocument($templateused, $outputlangs, $hidedetails, $hidedesc, $hideref);
248
249
            if ($result <= 0) {
250
                throw new RestException(500, 'Error generating document missing doctemplate parameter');
251
            }
252
        } elseif ($modulepart == 'expedition' || $modulepart == 'shipment') {
253
            require_once constant('DOL_DOCUMENT_ROOT') . '/expedition/class/expedition.class.php';
254
255
            $tmpobject = new Expedition($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\Expedition was not found. Did you mean Expedition? If so, make sure to prefix the type with \.
Loading history...
256
            $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
257
258
            if (!$result) {
259
                throw new RestException(404, 'Shipment not found');
260
            }
261
262
            $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
263
            $result = $tmpobject->generateDocument($templateused, $outputlangs, $hidedetails, $hidedesc, $hideref);
264
265
            if ($result <= 0) {
266
                throw new RestException(500, 'Error generating document missing doctemplate parameter');
267
            }
268
        } else {
269
            throw new RestException(403, 'Generation not available for this modulepart');
270
        }
271
272
        $filename = basename($original_file);
273
        $original_file_osencoded = dol_osencode($original_file); // New file name encoded in OS encoding charset
274
275
        if (!file_exists($original_file_osencoded)) {
276
            throw new RestException(404, 'File not found');
277
        }
278
279
        $file_content = file_get_contents($original_file_osencoded);
280
        return array('filename' => $filename, 'content-type' => dol_mimetype($filename), 'filesize' => filesize($original_file), 'content' => base64_encode($file_content), 'langcode' => $outputlangs->defaultlang, 'template' => $templateused, 'encoding' => 'base64');
281
    }
282
283
    /**
284
     * Return the list of documents of a dedicated element (from its ID or Ref)
285
     *
286
     * Supported modules: thirdparty, user, member, proposal, order, supplier_order, shipment, invoice, supplier_invoice, product, event, expensereport, knowledgemanagement, category, contract
287
     *
288
     * @param   string  $modulepart     Name of module or area concerned ('thirdparty', 'member', 'proposal', 'order', 'invoice', 'supplier_invoice', 'shipment', 'project',  ...)
289
     * @param   int     $id             ID of element
290
     * @param   string  $ref            Ref of element
291
     * @param   string  $sortfield      Sort criteria ('','fullname','relativename','name','date','size')
292
     * @param   string  $sortorder      Sort order ('asc' or 'desc')
293
     * @return  array                   Array of documents with path
294
     *
295
     * @url GET /
296
     *
297
     * @throws  RestException   400     Bad value for parameter modulepart, id or ref
298
     * @throws  RestException   403     Access denied
299
     * @throws  RestException   404     Thirdparty, User, Member, Order, Invoice or Proposal not found
300
     * @throws  RestException   500     Error while fetching object
301
     * @throws  RestException   503     Error when retrieve ecm list
302
     */
303
    public function getDocumentsListByElement($modulepart, $id = 0, $ref = '', $sortfield = '', $sortorder = '')
304
    {
305
        global $conf;
306
307
        if (empty($modulepart)) {
308
            throw new RestException(400, 'bad value for parameter modulepart');
309
        }
310
311
        if (empty($id) && empty($ref)) {
312
            throw new RestException(400, 'bad value for parameter id or ref');
313
        }
314
315
        $id = (empty($id) ? 0 : $id);
316
        $recursive = 0;
317
        $type = 'files';
318
319
        if ($modulepart == 'societe' || $modulepart == 'thirdparty') {
320
            require_once constant('DOL_DOCUMENT_ROOT') . '/societe/class/societe.class.php';
321
322
            if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
323
                throw new RestException(403);
324
            }
325
326
            $object = new Societe($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\Societe was not found. Did you mean Societe? If so, make sure to prefix the type with \.
Loading history...
327
            $result = $object->fetch($id, $ref);
328
            if (!$result) {
329
                throw new RestException(404, 'Thirdparty not found');
330
            }
331
332
            $upload_dir = $conf->societe->multidir_output[$object->entity] . "/" . $object->id;
333
        } elseif ($modulepart == 'user') {
334
            require_once constant('DOL_DOCUMENT_ROOT') . '/user/class/user.class.php';
335
336
            // Can get doc if has permission to read all user or if it is user itself
337
            if (!DolibarrApiAccess::$user->hasRight('user', 'user', 'lire') && DolibarrApiAccess::$user->id != $id) {
338
                throw new RestException(403);
339
            }
340
341
            $object = new User($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\User was not found. Did you mean User? If so, make sure to prefix the type with \.
Loading history...
342
            $result = $object->fetch($id, $ref);
343
            if (!$result) {
344
                throw new RestException(404, 'User not found');
345
            }
346
347
            $upload_dir = $conf->user->dir_output . '/' . get_exdir(0, 0, 0, 0, $object, 'user') . '/' . $object->id;
348
        } elseif ($modulepart == 'adherent' || $modulepart == 'member') {
349
            require_once constant('DOL_DOCUMENT_ROOT') . '/adherents/class/adherent.class.php';
350
351
            if (!DolibarrApiAccess::$user->hasRight('adherent', 'lire')) {
352
                throw new RestException(403);
353
            }
354
355
            $object = new Adherent($this->db);
356
            $result = $object->fetch($id, $ref);
357
            if (!$result) {
358
                throw new RestException(404, 'Member not found');
359
            }
360
361
            $upload_dir = $conf->adherent->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'member');
362
        } elseif ($modulepart == 'propal' || $modulepart == 'proposal') {
363
            require_once constant('DOL_DOCUMENT_ROOT') . '/comm/propal/class/propal.class.php';
364
365
            if (!DolibarrApiAccess::$user->hasRight('propal', 'lire')) {
366
                throw new RestException(403);
367
            }
368
369
            $object = new Propal($this->db);
370
            $result = $object->fetch($id, $ref);
371
            if (!$result) {
372
                throw new RestException(404, 'Proposal not found');
373
            }
374
375
            $upload_dir = $conf->propal->multidir_output[$object->entity] . "/" . get_exdir(0, 0, 0, 1, $object, 'propal');
376
        } elseif ($modulepart == 'supplier_proposal') {
377
            require_once constant('DOL_DOCUMENT_ROOT') . '/supplier_proposal/class/supplier_proposal.class.php';
378
379
            if (!DolibarrApiAccess::$user->hasRight('supplier_proposal', 'read')) {
380
                throw new RestException(403);
381
            }
382
383
            $object = new Propal($this->db);
384
            $result = $object->fetch($id, $ref);
385
            if (!$result) {
386
                throw new RestException(404, 'Supplier proposal not found');
387
            }
388
389
            $upload_dir = $conf->propal->multidir_output[$object->entity] . "/" . get_exdir(0, 0, 0, 1, $object, 'propal');
390
        } elseif ($modulepart == 'commande' || $modulepart == 'order') {
391
            require_once constant('DOL_DOCUMENT_ROOT') . '/commande/class/commande.class.php';
392
393
            if (!DolibarrApiAccess::$user->hasRight('commande', 'lire')) {
394
                throw new RestException(403);
395
            }
396
397
            $object = new Commande($this->db);
398
            $result = $object->fetch($id, $ref);
399
            if (!$result) {
400
                throw new RestException(404, 'Order not found');
401
            }
402
403
            $upload_dir = $conf->commande->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'commande');
404
        } elseif ($modulepart == 'commande_fournisseur' || $modulepart == 'supplier_order') {
405
            $modulepart = 'supplier_order';
406
407
            require_once constant('DOL_DOCUMENT_ROOT') . '/fourn/class/fournisseur.commande.class.php';
408
409
            if (!DolibarrApiAccess::$user->hasRight('fournisseur', 'commande', 'lire') && !DolibarrApiAccess::$user->hasRight('supplier_order', 'lire')) {
410
                throw new RestException(403);
411
            }
412
413
            $object = new CommandeFournisseur($this->db);
414
            $result = $object->fetch($id, $ref);
415
            if (!$result) {
416
                throw new RestException(404, 'Purchase order not found');
417
            }
418
419
            $upload_dir = $conf->fournisseur->dir_output . "/commande/" . dol_sanitizeFileName($object->ref);
420
        } elseif ($modulepart == 'shipment' || $modulepart == 'expedition') {
421
            require_once constant('DOL_DOCUMENT_ROOT') . '/expedition/class/expedition.class.php';
422
423
            if (!DolibarrApiAccess::$user->hasRight('expedition', 'lire')) {
424
                throw new RestException(403);
425
            }
426
427
            $object = new Expedition($this->db);
428
            $result = $object->fetch($id, $ref);
429
            if (!$result) {
430
                throw new RestException(404, 'Shipment not found');
431
            }
432
433
            $upload_dir = $conf->expedition->dir_output . "/sending/" . get_exdir(0, 0, 0, 1, $object, 'shipment');
434
        } elseif ($modulepart == 'facture' || $modulepart == 'invoice') {
435
            require_once constant('DOL_DOCUMENT_ROOT') . '/compta/facture/class/facture.class.php';
436
437
            if (!DolibarrApiAccess::$user->hasRight('facture', 'lire')) {
438
                throw new RestException(403);
439
            }
440
441
            $object = new Facture($this->db);
442
            $result = $object->fetch($id, $ref);
443
            if (!$result) {
444
                throw new RestException(404, 'Invoice not found');
445
            }
446
447
            $upload_dir = $conf->facture->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'invoice');
448
        } elseif ($modulepart == 'facture_fournisseur' || $modulepart == 'supplier_invoice') {
449
            $modulepart = 'supplier_invoice';
450
451
            require_once constant('DOL_DOCUMENT_ROOT') . '/fourn/class/fournisseur.facture.class.php';
452
453
            if (!DolibarrApiAccess::$user->hasRight('fournisseur', 'facture', 'lire') && !DolibarrApiAccess::$user->hasRight('supplier_invoice', 'lire')) {
454
                throw new RestException(403);
455
            }
456
457
            $object = new FactureFournisseur($this->db);
458
            $result = $object->fetch($id, $ref);
459
            if (!$result) {
460
                throw new RestException(404, 'Invoice not found');
461
            }
462
463
            $upload_dir = $conf->fournisseur->dir_output . "/facture/" . get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier') . dol_sanitizeFileName($object->ref);
464
        } elseif ($modulepart == 'produit' || $modulepart == 'product') {
465
            require_once constant('DOL_DOCUMENT_ROOT') . '/product/class/product.class.php';
466
467
            if (!DolibarrApiAccess::$user->hasRight('produit', 'lire')) {
468
                throw new RestException(403);
469
            }
470
471
            $object = new Product($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\Product was not found. Did you mean Product? If so, make sure to prefix the type with \.
Loading history...
472
            $result = $object->fetch($id, $ref);
473
            if ($result == 0) {
474
                throw new RestException(404, 'Product not found');
475
            } elseif ($result < 0) {
476
                throw new RestException(500, 'Error while fetching object: ' . $object->error);
477
            }
478
479
            $upload_dir = $conf->product->multidir_output[$object->entity] . '/' . get_exdir(0, 0, 0, 1, $object, 'product');
480
        } elseif ($modulepart == 'agenda' || $modulepart == 'action' || $modulepart == 'event') {
481
            require_once constant('DOL_DOCUMENT_ROOT') . '/comm/action/class/actioncomm.class.php';
482
483
            if (!DolibarrApiAccess::$user->hasRight('agenda', 'myactions', 'read') && !DolibarrApiAccess::$user->hasRight('agenda', 'allactions', 'read')) {
484
                throw new RestException(403);
485
            }
486
487
            $object = new ActionComm($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\ActionComm was not found. Did you mean ActionComm? If so, make sure to prefix the type with \.
Loading history...
488
            $result = $object->fetch($id, $ref);
489
            if (!$result) {
490
                throw new RestException(404, 'Event not found');
491
            }
492
493
            $upload_dir = $conf->agenda->dir_output . '/' . dol_sanitizeFileName($object->ref);
494
        } elseif ($modulepart == 'expensereport') {
495
            require_once constant('DOL_DOCUMENT_ROOT') . '/expensereport/class/expensereport.class.php';
496
497
            if (!DolibarrApiAccess::$user->hasRight('expensereport', 'read') && !DolibarrApiAccess::$user->hasRight('expensereport', 'read')) {
498
                throw new RestException(403);
499
            }
500
501
            $object = new ExpenseReport($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\ExpenseReport was not found. Did you mean ExpenseReport? If so, make sure to prefix the type with \.
Loading history...
502
            $result = $object->fetch($id, $ref);
503
            if (!$result) {
504
                throw new RestException(404, 'Expense report not found');
505
            }
506
507
            $upload_dir = $conf->expensereport->dir_output . '/' . dol_sanitizeFileName($object->ref);
508
        } elseif ($modulepart == 'knowledgemanagement') {
509
            require_once constant('DOL_DOCUMENT_ROOT') . '/knowledgemanagement/class/knowledgerecord.class.php';
510
511
            if (!DolibarrApiAccess::$user->hasRight('knowledgemanagement', 'knowledgerecord', 'read') && !DolibarrApiAccess::$user->hasRight('knowledgemanagement', 'knowledgerecord', 'read')) {
512
                throw new RestException(403);
513
            }
514
515
            $object = new KnowledgeRecord($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\KnowledgeRecord was not found. Did you mean KnowledgeRecord? If so, make sure to prefix the type with \.
Loading history...
516
            $result = $object->fetch($id, $ref);
517
            if (!$result) {
518
                throw new RestException(404, 'KM article not found');
519
            }
520
521
            $upload_dir = $conf->knowledgemanagement->dir_output . '/knowledgerecord/' . dol_sanitizeFileName($object->ref);
522
        } elseif ($modulepart == 'categorie' || $modulepart == 'category') {
523
            require_once constant('DOL_DOCUMENT_ROOT') . '/categories/class/categorie.class.php';
524
525
            if (!DolibarrApiAccess::$user->hasRight('categorie', 'lire')) {
526
                throw new RestException(403);
527
            }
528
529
            $object = new Categorie($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\Categorie was not found. Did you mean Categorie? If so, make sure to prefix the type with \.
Loading history...
530
            $result = $object->fetch($id, $ref);
531
            if (!$result) {
532
                throw new RestException(404, 'Category not found');
533
            }
534
535
            $upload_dir = $conf->categorie->multidir_output[$object->entity] . '/' . get_exdir($object->id, 2, 0, 0, $object, 'category') . $object->id . "/photos/" . dol_sanitizeFileName($object->ref);
536
        } elseif ($modulepart == 'ecm') {
537
            throw new RestException(500, 'Modulepart Ecm not implemented yet.');
538
            // require_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmdirectory.class.php';
539
540
            // if (!DolibarrApiAccess::$user->hasRight('ecm', 'read')) {
541
            //  throw new RestException(403);
542
            // }
543
544
            // // $object = new EcmDirectory($this->db);
545
            // // $result = $object->fetch($ref);
546
            // // if (!$result) {
547
            // //   throw new RestException(404, 'EcmDirectory not found');
548
            // // }
549
            // $upload_dir = $conf->ecm->dir_output;
550
            // $type = 'all';
551
            // $recursive = 0;
552
        } elseif ($modulepart == 'contrat' || $modulepart == 'contract') {
553
            $modulepart = 'contrat';
554
            require_once constant('DOL_DOCUMENT_ROOT') . '/contrat/class/contrat.class.php';
555
556
            $object = new Contrat($this->db);
557
            $result = $object->fetch($id, $ref);
558
            if (!$result) {
559
                throw new RestException(404, 'Contract not found');
560
            }
561
562
            $upload_dir = $conf->contrat->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'contract');
563
        } elseif ($modulepart == 'projet' || $modulepart == 'project') {
564
            $modulepart = 'project';
565
            require_once constant('DOL_DOCUMENT_ROOT') . '/projet/class/project.class.php';
566
567
            $object = new Project($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\Project was not found. Did you mean Project? If so, make sure to prefix the type with \.
Loading history...
568
            $result = $object->fetch($id, $ref);
569
            if (!$result) {
570
                throw new RestException(404, 'Project not found');
571
            }
572
573
            $upload_dir = $conf->projet->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'project');
574
        } else {
575
            throw new RestException(500, 'Modulepart ' . $modulepart . ' not implemented yet.');
576
        }
577
578
        $objectType = $modulepart;
579
        if (! empty($object->id) && ! empty($object->table_element)) {
580
            $objectType = $object->table_element;
581
        }
582
583
        $filearray = dol_dir_list($upload_dir, $type, $recursive, '', '(\.meta|_preview.*\.png)$', $sortfield, (strtolower($sortorder) == 'desc' ? SORT_DESC : SORT_ASC), 1);
584
        if (empty($filearray)) {
585
            throw new RestException(404, 'Search for modulepart ' . $modulepart . ' with Id ' . $object->id . (!empty($object->ref) ? ' or Ref ' . $object->ref : '') . ' does not return any document.');
586
        } else {
587
            if (($object->id) > 0 && !empty($modulepart)) {
588
                require_once constant('DOL_DOCUMENT_ROOT') . '/ecm/class/ecmfiles.class.php';
589
                $ecmfile = new EcmFiles($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\EcmFiles was not found. Did you mean EcmFiles? If so, make sure to prefix the type with \.
Loading history...
590
                $result = $ecmfile->fetchAll('', '', 0, 0, array('t.src_object_type' => $objectType, 't.src_object_id' => $object->id));
591
                if ($result < 0) {
592
                    throw new RestException(503, 'Error when retrieve ecm list : ' . $this->db->lasterror());
593
                } elseif (is_array($ecmfile->lines) && count($ecmfile->lines) > 0) {
594
                    $count = count($filearray);
595
                    for ($i = 0 ; $i < $count ; $i++) {
596
                        foreach ($ecmfile->lines as $line) {
597
                            if ($filearray[$i]['name'] == $line->filename) {
598
                                $filearray[$i] = array_merge($filearray[$i], (array) $line);
599
                            }
600
                        }
601
                    }
602
                }
603
            }
604
        }
605
606
        return $filearray;
607
    }
608
609
610
    /**
611
     * Return a document.
612
     *
613
     * @param   int         $id          ID of document
614
     * @return  array                    Array with data of file
615
     *
616
     * @throws RestException
617
     */
618
    /*
619
    public function get($id) {
620
        return array('note'=>'xxx');
621
    }*/
622
623
624
    /**
625
     * Upload a document.
626
     *
627
     * Test sample for invoice: { "filename": "mynewfile.txt", "modulepart": "invoice", "ref": "FA1701-001", "subdir": "", "filecontent": "content text", "fileencoding": "", "overwriteifexists": "0" }.
628
     * Test sample for supplier invoice: { "filename": "mynewfile.txt", "modulepart": "supplier_invoice", "ref": "FA1701-001", "subdir": "", "filecontent": "content text", "fileencoding": "", "overwriteifexists": "0" }.
629
     * Test sample for medias file: { "filename": "mynewfile.txt", "modulepart": "medias", "ref": "", "subdir": "image/mywebsite", "filecontent": "Y29udGVudCB0ZXh0Cg==", "fileencoding": "base64", "overwriteifexists": "0" }.
630
     *
631
     * Supported modules: invoice, order, supplier_order, task/project_task, product/service, expensereport, fichinter, member, propale, agenda, contact
632
     *
633
     * @param   string  $filename               Name of file to create ('FA1705-0123.txt')
634
     * @param   string  $modulepart             Name of module or area concerned by file upload ('product', 'service', 'invoice', 'proposal', 'project', 'project_task', 'supplier_invoice', 'expensereport', 'member', ...)
635
     * @param   string  $ref                    Reference of object (This will define subdir automatically and store submitted file into it)
636
     * @param   string  $subdir                 Subdirectory (Only if ref not provided)
637
     * @param   string  $filecontent            File content (string with file content. An empty file will be created if this parameter is not provided)
638
     * @param   string  $fileencoding           File encoding (''=no encoding, 'base64'=Base 64)
639
     * @param   int     $overwriteifexists      Overwrite file if exists (1 by default)
640
     * @param   int     $createdirifnotexists   Create subdirectories if the doesn't exists (1 by default)
641
     * @return  string
642
     *
643
     * @url POST /upload
644
     *
645
     * @throws  RestException   400     Bad Request
646
     * @throws  RestException   403     Access denied
647
     * @throws  RestException   404     Object not found
648
     * @throws  RestException   500     Error on file operationw
649
     */
650
    public function post($filename, $modulepart, $ref = '', $subdir = '', $filecontent = '', $fileencoding = '', $overwriteifexists = 0, $createdirifnotexists = 1)
651
    {
652
        global $conf;
653
654
        //var_dump($modulepart);
655
        //var_dump($filename);
656
        //var_dump($filecontent);exit;
657
658
        $modulepartorig = $modulepart;
659
660
        if (empty($modulepart)) {
661
            throw new RestException(400, 'Modulepart not provided.');
662
        }
663
664
        $newfilecontent = '';
665
        if (empty($fileencoding)) {
666
            $newfilecontent = $filecontent;
667
        }
668
        if ($fileencoding == 'base64') {
669
            $newfilecontent = base64_decode($filecontent);
670
        }
671
672
        $original_file = dol_sanitizeFileName($filename);
673
674
        // Define $uploadir
675
        $object = null;
676
        $entity = DolibarrApiAccess::$user->entity;
677
        if (empty($entity)) {
678
            $entity = 1;
679
        }
680
681
        if ($ref) {
682
            $tmpreldir = '';
683
            $fetchbyid = false;
684
685
            if ($modulepart == 'facture' || $modulepart == 'invoice') {
686
                $modulepart = 'facture';
687
688
                require_once constant('DOL_DOCUMENT_ROOT') . '/compta/facture/class/facture.class.php';
689
                $object = new Facture($this->db);
690
            } elseif ($modulepart == 'facture_fournisseur' || $modulepart == 'supplier_invoice') {
691
                $modulepart = 'supplier_invoice';
692
693
                require_once constant('DOL_DOCUMENT_ROOT') . '/fourn/class/fournisseur.facture.class.php';
694
                $object = new FactureFournisseur($this->db);
695
            } elseif ($modulepart == 'commande' || $modulepart == 'order') {
696
                $modulepart = 'commande';
697
698
                require_once constant('DOL_DOCUMENT_ROOT') . '/commande/class/commande.class.php';
699
                $object = new Commande($this->db);
700
            } elseif ($modulepart == 'commande_fournisseur' || $modulepart == 'supplier_order') {
701
                $modulepart = 'supplier_order';
702
703
                require_once constant('DOL_DOCUMENT_ROOT') . '/fourn/class/fournisseur.commande.class.php';
704
                $object = new CommandeFournisseur($this->db);
705
            } elseif ($modulepart == 'projet' || $modulepart == 'project') {
706
                require_once constant('DOL_DOCUMENT_ROOT') . '/projet/class/project.class.php';
707
                $object = new Project($this->db);
708
            } elseif ($modulepart == 'task' || $modulepart == 'project_task') {
709
                $modulepart = 'project_task';
710
711
                require_once constant('DOL_DOCUMENT_ROOT') . '/projet/class/task.class.php';
712
                $object = new Task($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\Task was not found. Did you mean Task? If so, make sure to prefix the type with \.
Loading history...
713
714
                $task_result = $object->fetch('', $ref);
715
716
                // Fetching the tasks project is required because its out_dir might be a sub-directory of the project
717
                if ($task_result > 0) {
718
                    $project_result = $object->fetch_projet();
719
720
                    if ($project_result >= 0) {
721
                        $tmpreldir = dol_sanitizeFileName($object->project->ref) . '/';
722
                    }
723
                } else {
724
                    throw new RestException(500, 'Error while fetching Task ' . $ref);
725
                }
726
            } elseif ($modulepart == 'product' || $modulepart == 'produit' || $modulepart == 'service' || $modulepart == 'produit|service') {
727
                require_once constant('DOL_DOCUMENT_ROOT') . '/product/class/product.class.php';
728
                $object = new Product($this->db);
729
            } elseif ($modulepart == 'expensereport') {
730
                require_once constant('DOL_DOCUMENT_ROOT') . '/expensereport/class/expensereport.class.php';
731
                $object = new ExpenseReport($this->db);
732
            } elseif ($modulepart == 'fichinter') {
733
                require_once constant('DOL_DOCUMENT_ROOT') . '/fichinter/class/fichinter.class.php';
734
                $object = new Fichinter($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\Fichinter was not found. Did you mean Fichinter? If so, make sure to prefix the type with \.
Loading history...
735
            } elseif ($modulepart == 'adherent' || $modulepart == 'member') {
736
                $modulepart = 'adherent';
737
                require_once constant('DOL_DOCUMENT_ROOT') . '/adherents/class/adherent.class.php';
738
                $object = new Adherent($this->db);
739
            } elseif ($modulepart == 'proposal' || $modulepart == 'propal' || $modulepart == 'propale') {
740
                $modulepart = 'propale';
741
                require_once constant('DOL_DOCUMENT_ROOT') . '/comm/propal/class/propal.class.php';
742
                $object = new Propal($this->db);
743
            } elseif ($modulepart == 'agenda' || $modulepart == 'action' || $modulepart == 'event') {
744
                $modulepart = 'agenda';
745
                require_once constant('DOL_DOCUMENT_ROOT') . '/comm/action/class/actioncomm.class.php';
746
                $object = new ActionComm($this->db);
747
            } elseif ($modulepart == 'contact' || $modulepart == 'socpeople') {
748
                $modulepart = 'contact';
749
                require_once constant('DOL_DOCUMENT_ROOT') . '/contact/class/contact.class.php';
750
                $object = new Contact($this->db);
0 ignored issues
show
Bug introduced by
The type Dolibarr\Code\Api\Api\Contact was not found. Did you mean Contact? If so, make sure to prefix the type with \.
Loading history...
751
                $fetchbyid = true;
752
            } elseif ($modulepart == 'contrat' || $modulepart == 'contract') {
753
                $modulepart = 'contrat';
754
                require_once constant('DOL_DOCUMENT_ROOT') . '/contrat/class/contrat.class.php';
755
                $object = new Contrat($this->db);
756
            } else {
757
                // TODO Implement additional moduleparts
758
                throw new RestException(500, 'Modulepart ' . $modulepart . ' not implemented yet.');
759
            }
760
761
            if (is_object($object)) {
762
                if ($fetchbyid) {
763
                    // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
764
                    $result = $object->fetch($ref);
765
                } else {
766
                    $result = $object->fetch('', $ref);
767
                }
768
769
                if ($result == 0) {
770
                    throw new RestException(404, "Object with ref '" . $ref . "' was not found.");
771
                } elseif ($result < 0) {
772
                    throw new RestException(500, 'Error while fetching object: ' . $object->error);
773
                }
774
            }
775
776
            if (!($object->id > 0)) {
777
                throw new RestException(404, 'The object ' . $modulepart . " with ref '" . $ref . "' was not found.");
778
            }
779
780
            // Special cases that need to use get_exdir to get real dir of object
781
            // In future, all object should use this to define path of documents.
782
            if ($modulepart == 'supplier_invoice') {
783
                $tmpreldir = get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier');
784
            }
785
786
            // Test on permissions
787
            if ($modulepart != 'ecm') {
788
                $relativefile = $tmpreldir . dol_sanitizeFileName($object->ref);
789
                $tmp = dol_check_secure_access_document($modulepart, $relativefile, $entity, DolibarrApiAccess::$user, $ref, 'write');
790
                $upload_dir = $tmp['original_file']; // No dirname here, tmp['original_file'] is already the dir because dol_check_secure_access_document was called with param original_file that is only the dir
791
            } else {
792
                if (!DolibarrApiAccess::$user->hasRight('ecm', 'upload')) {
793
                    throw new RestException(403, 'Missing permission to upload files in ECM module');
794
                }
795
                $upload_dir = $conf->medias->multidir_output[$conf->entity];
796
            }
797
798
            if (empty($upload_dir) || $upload_dir == '/') {
799
                throw new RestException(500, 'This value of modulepart (' . $modulepart . ') does not support yet usage of ref. Check modulepart parameter or try to use subdir parameter instead of ref.');
800
            }
801
        } else {
802
            if ($modulepart == 'invoice') {
803
                $modulepart = 'facture';
804
            }
805
            if ($modulepart == 'member') {
806
                $modulepart = 'adherent';
807
            }
808
809
            // Test on permissions
810
            if ($modulepart != 'ecm') {
811
                $relativefile = $subdir;
812
                $tmp = dol_check_secure_access_document($modulepart, $relativefile, $entity, DolibarrApiAccess::$user, '', 'write');
813
                $upload_dir = $tmp['original_file']; // No dirname here, tmp['original_file'] is already the dir because dol_check_secure_access_document was called with param original_file that is only the dir
814
            } else {
815
                if (!DolibarrApiAccess::$user->hasRight('ecm', 'upload')) {
816
                    throw new RestException(403, 'Missing permission to upload files in ECM module');
817
                }
818
                $upload_dir = $conf->medias->multidir_output[$conf->entity];
819
            }
820
821
            if (empty($upload_dir) || $upload_dir == '/') {
822
                if (!empty($tmp['error'])) {
823
                    throw new RestException(403, 'Error returned by dol_check_secure_access_document: ' . $tmp['error']);
824
                } else {
825
                    throw new RestException(400, 'This value of modulepart (' . $modulepart . ') is not allowed with this value of subdir (' . $relativefile . ')');
826
                }
827
            }
828
        }
829
        // $original_file here is still value of filename without any dir.
830
831
        $upload_dir = dol_sanitizePathName($upload_dir);
832
833
        if (!empty($createdirifnotexists)) {
834
            if (dol_mkdir($upload_dir) < 0) { // needed by products
835
                throw new RestException(500, 'Error while trying to create directory ' . $upload_dir);
836
            }
837
        }
838
839
        $destfile = $upload_dir . '/' . $original_file;
840
        $destfiletmp = DOL_DATA_ROOT . '/admin/temp/' . $original_file;
841
        dol_delete_file($destfiletmp);
842
        //var_dump($original_file);exit;
843
844
        if (!dol_is_dir(dirname($destfile))) {
845
            throw new RestException(400, 'Directory does not exists : ' . dirname($destfile));
846
        }
847
848
        if (!$overwriteifexists && dol_is_file($destfile)) {
849
            throw new RestException(400, "File with name '" . $original_file . "' already exists.");
850
        }
851
852
        // in case temporary directory admin/temp doesn't exist
853
        if (!dol_is_dir(dirname($destfiletmp))) {
854
            dol_mkdir(dirname($destfiletmp));
855
        }
856
857
        $fhandle = @fopen($destfiletmp, 'w');
858
        if ($fhandle) {
859
            $nbofbyteswrote = fwrite($fhandle, $newfilecontent);
860
            fclose($fhandle);
861
            dolChmod($destfiletmp);
862
        } else {
863
            throw new RestException(500, "Failed to open file '" . $destfiletmp . "' for write");
864
        }
865
866
        $disablevirusscan = 0;
867
        $src_file = $destfiletmp;
868
        $dest_file = $destfile;
869
870
        // Security:
871
        // If we need to make a virus scan
872
        if (empty($disablevirusscan) && file_exists($src_file)) {
873
            $checkvirusarray = dolCheckVirus($src_file, $dest_file);
874
            if (count($checkvirusarray)) {
875
                dol_syslog('Files.lib::dol_move_uploaded_file File "' . $src_file . '" (target name "' . $dest_file . '") KO with antivirus: errors=' . implode(',', $checkvirusarray), LOG_WARNING);
876
                throw new RestException(500, 'ErrorFileIsInfectedWithAVirus: ' . implode(',', $checkvirusarray));
877
            }
878
        }
879
880
        // Security:
881
        // Disallow file with some extensions. We rename them.
882
        // Because if we put the documents directory into a directory inside web root (very bad), this allows to execute on demand arbitrary code.
883
        if (isAFileWithExecutableContent($dest_file) && !getDolGlobalString('MAIN_DOCUMENT_IS_OUTSIDE_WEBROOT_SO_NOEXE_NOT_REQUIRED')) {
884
            // $upload_dir ends with a slash, so be must be sure the medias dir to compare to ends with slash too.
885
            $publicmediasdirwithslash = $conf->medias->multidir_output[$conf->entity];
886
            if (!preg_match('/\/$/', $publicmediasdirwithslash)) {
887
                $publicmediasdirwithslash .= '/';
888
            }
889
890
            if (strpos($upload_dir, $publicmediasdirwithslash) !== 0 || !getDolGlobalInt("MAIN_DOCUMENT_DISABLE_NOEXE_IN_MEDIAS_DIR")) {    // We never add .noexe on files into media directory
891
                $dest_file .= '.noexe';
892
            }
893
        }
894
895
        // Security:
896
        // We refuse cache files/dirs, upload using .. and pipes into filenames.
897
        if (preg_match('/^\./', basename($src_file)) || preg_match('/\.\./', $src_file) || preg_match('/[<>|]/', $src_file)) {
898
            dol_syslog("Refused to deliver file " . $src_file, LOG_WARNING);
899
            throw new RestException(500, "Refused to deliver file " . $src_file);
900
        }
901
902
        // Security:
903
        // We refuse cache files/dirs, upload using .. and pipes into filenames.
904
        if (preg_match('/^\./', basename($dest_file)) || preg_match('/\.\./', $dest_file) || preg_match('/[<>|]/', $dest_file)) {
905
            dol_syslog("Refused to deliver file " . $dest_file, LOG_WARNING);
906
            throw new RestException(500, "Refused to deliver file " . $dest_file);
907
        }
908
909
        $moreinfo = array('note_private' => 'File uploaded using API /documents from IP ' . getUserRemoteIP());
910
        if (!empty($object) && is_object($object) && $object->id > 0) {
911
            $moreinfo['src_object_type'] = $object->table_element;
912
            $moreinfo['src_object_id'] = $object->id;
913
        }
914
915
        // Move the temporary file at its final emplacement
916
        $result = dol_move($destfiletmp, $dest_file, 0, $overwriteifexists, 1, 1, $moreinfo);
917
        if (!$result) {
918
            throw new RestException(500, "Failed to move file into '" . $destfile . "'");
919
        }
920
921
        return dol_basename($destfile);
922
    }
923
924
    /**
925
     * Delete a document.
926
     *
927
     * @param   string  $modulepart     Name of module or area concerned by file download ('product', ...)
928
     * @param   string  $original_file  Relative path with filename, relative to modulepart (for example: PRODUCT-REF-999/IMAGE-999.jpg)
929
     * @return  array                   List of documents
930
     *
931
     * @url DELETE /
932
     *
933
     * @throws  RestException   400  Bad value for parameter modulepart
934
     * @throws  RestException   400  Bad value for parameter original_file
935
     * @throws  RestException   403  Access denied
936
     * @throws  RestException   404  File not found
937
     * @throws  RestException   500  Error on file operation
938
     */
939
    public function delete($modulepart, $original_file)
940
    {
941
        global $conf, $langs;
942
943
        if (empty($modulepart)) {
944
            throw new RestException(400, 'bad value for parameter modulepart');
945
        }
946
        if (empty($original_file)) {
947
            throw new RestException(400, 'bad value for parameter original_file');
948
        }
949
950
        //--- Finds and returns the document
951
        $entity = $conf->entity;
952
953
        // Special cases that need to use get_exdir to get real dir of object
954
        // If future, all object should use this to define path of documents.
955
        /*
956
        $tmpreldir = '';
957
        if ($modulepart == 'supplier_invoice') {
958
            $tmpreldir = get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier');
959
        }
960
961
        $relativefile = $tmpreldir.dol_sanitizeFileName($object->ref); */
962
        $relativefile = $original_file;
963
964
        $check_access = dol_check_secure_access_document($modulepart, $relativefile, $entity, DolibarrApiAccess::$user, '', 'read');
965
        $accessallowed = $check_access['accessallowed'];
966
        $sqlprotectagainstexternals = $check_access['sqlprotectagainstexternals'];
967
        $original_file = $check_access['original_file'];
968
969
        if (preg_match('/\.\./', $original_file) || preg_match('/[<>|]/', $original_file)) {
970
            throw new RestException(403);
971
        }
972
        if (!$accessallowed) {
973
            throw new RestException(403);
974
        }
975
976
        $filename = basename($original_file);
977
        $original_file_osencoded = dol_osencode($original_file); // New file name encoded in OS encoding charset
978
979
        if (!file_exists($original_file_osencoded)) {
980
            dol_syslog("Try to download not found file " . $original_file_osencoded, LOG_WARNING);
981
            throw new RestException(404, 'File not found');
982
        }
983
984
        if (@unlink($original_file_osencoded)) {
985
            return array(
986
                'success' => array(
987
                    'code' => 200,
988
                    'message' => 'Document deleted'
989
                )
990
            );
991
        }
992
993
        throw new RestException(403);
994
    }
995
}
996