dolibarr 24.0.0-beta
api_documents.class.php
1<?php
2
3/* Copyright (C) 2016 Xebax Christy <xebax@wanadoo.fr>
4 * Copyright (C) 2016 Laurent Destailleur <eldy@users.sourceforge.net>
5 * Copyright (C) 2016 Jean-François Ferry <jfefe@aternatik.fr>
6 * Copyright (C) 2023 Romain Neil <contact@romain-neil.fr>
7 * Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
8 * Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
9 * Copyright (C) 2025 William Mead <william@m34d.com>
10 * Copyright (C) 2025-2026 Charlene Benke <charlene@patas-monkey.com>
11 *
12 * This program is free software you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <https://www.gnu.org/licenses/>.
24 */
25
26use Luracast\Restler\RestException;
27
28require_once DOL_DOCUMENT_ROOT.'/main.inc.php';
29require_once DOL_DOCUMENT_ROOT.'/api/class/api.class.php';
30require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
31
41{
45 public function __construct()
46 {
47 global $db;
48 $this->db = $db;
49 }
50
51
72 public function index($modulepart, $original_file = '')
73 {
74 global $conf;
75
76 if (empty($modulepart)) {
77 throw new RestException(400, 'bad value for parameter modulepart');
78 }
79 if (empty($original_file)) {
80 throw new RestException(400, 'bad value for parameter original_file');
81 }
82
83 // Normalize modulepart for project_task
84 if ($modulepart == 'task' || $modulepart == 'project_task') {
85 $modulepart = 'project_task';
86 }
87
88 //--- Finds and returns the document
89 $entity = $conf->entity;
90
91 // Special cases that need to use get_exdir to get real dir of object
92 // If future, all object should use this to define path of documents.
93 /*
94 $tmpreldir = '';
95 if ($modulepart == 'supplier_invoice') {
96 $tmpreldir = get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier');
97 }
98
99 $relativefile = $tmpreldir.dol_sanitizeFileName($object->ref); */
100 $relativefile = $original_file;
101
102 $check_access = dol_check_secure_access_document($modulepart, $relativefile, $entity, DolibarrApiAccess::$user, '', 'read');
103 $accessallowed = $check_access['accessallowed'];
104 $sqlprotectagainstexternals = $check_access['sqlprotectagainstexternals'];
105 $original_file = $check_access['original_file'];
106
107 if (preg_match('/\.\./', $original_file) || preg_match('/[<>|]/', $original_file)) {
108 throw new RestException(403);
109 }
110 if (!$accessallowed) {
111 throw new RestException(403);
112 }
113
114 if (DolibarrApiAccess::$user->socid > 0) {
115 if ($sqlprotectagainstexternals) {
116 $resql = $this->db->query($sqlprotectagainstexternals);
117 if ($resql) {
118 $num = $this->db->num_rows($resql);
119 $i = 0;
120 while ($i < $num) {
121 $obj = $this->db->fetch_object($resql);
122 if (DolibarrApiAccess::$user->socid != $obj->fk_soc) {
123 throw new RestException(403, 'Not allowed to download documents with such a ref');
124 }
125 $i++;
126 }
127 }
128 }
129 }
130
131 $filename = basename($original_file);
132 $original_file_osencoded = dol_osencode($original_file); // New file name encoded in OS encoding charset
133
134 if (!file_exists($original_file_osencoded)) {
135 dol_syslog("Try to download not found file ".$original_file_osencoded, LOG_WARNING);
136 throw new RestException(404, 'File not found');
137 }
138
139 $file_content = file_get_contents($original_file_osencoded);
140 return array('filename' => $filename, 'content-type' => dol_mimetype($filename), 'filesize' => filesize($original_file), 'content' => base64_encode($file_content), 'encoding' => 'base64');
141 }
142
143
174 public function builddoc($modulepart, $original_file = '', $doctemplate = '', $langcode = '')
175 {
176 global $conf, $langs;
177
178 if (empty($modulepart)) {
179 throw new RestException(400, 'bad value for parameter modulepart');
180 }
181 if (empty($original_file)) {
182 throw new RestException(400, 'bad value for parameter original_file');
183 }
184
185 $outputlangs = $langs;
186 if ($langcode && $langs->defaultlang != $langcode) {
187 $outputlangs = new Translate('', $conf);
188 $outputlangs->setDefaultLang($langcode);
189 }
190
191 //--- Finds and returns the document
192 $entity = $conf->entity;
193
194 // Special cases that need to use get_exdir to get real dir of object
195 // If future, all object should use this to define path of documents.
196 /*
197 $tmpreldir = '';
198 if ($modulepart == 'supplier_invoice') {
199 $tmpreldir = get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier');
200 }
201
202 $relativefile = $tmpreldir.dol_sanitizeFileName($object->ref); */
203 $relativefile = $original_file;
204
205 $check_access = dol_check_secure_access_document($modulepart, $relativefile, $entity, DolibarrApiAccess::$user, '', 'write');
206 $accessallowed = $check_access['accessallowed'];
207 $sqlprotectagainstexternals = $check_access['sqlprotectagainstexternals'];
208 $original_file = $check_access['original_file'];
209
210 if (preg_match('/\.\./', $original_file) || preg_match('/[<>|]/', $original_file)) {
211 throw new RestException(403);
212 }
213 if (!$accessallowed) {
214 throw new RestException(403);
215 }
216
217 if (DolibarrApiAccess::$user->socid > 0) {
218 if ($sqlprotectagainstexternals) {
219 $resql = $this->db->query($sqlprotectagainstexternals);
220 if ($resql) {
221 $num = $this->db->num_rows($resql);
222 $i = 0;
223 while ($i < $num) {
224 $obj = $this->db->fetch_object($resql);
225 if (DolibarrApiAccess::$user->socid != $obj->fk_soc) {
226 throw new RestException(403, 'Not allowed to download documents with such a ref');
227 }
228 $i++;
229 }
230 }
231 }
232 }
233
234 // --- Generates the document
235 $hidedetails = !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS') ? 0 : 1;
236 $hidedesc = !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DESC') ? 0 : 1;
237 $hideref = !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_REF') ? 0 : 1;
238
239 $templateused = '';
240
241 if ($modulepart == 'facture' || $modulepart == 'invoice') {
242 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
243 $tmpobject = new Facture($this->db);
244 $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
245 if (!$result) {
246 throw new RestException(404, 'Invoice not found');
247 }
248
249 $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
250 $result = $tmpobject->generateDocument($templateused, $outputlangs, $hidedetails, $hidedesc, $hideref);
251 if ($result <= 0) {
252 throw new RestException(500, 'Error generating document');
253 }
254 } elseif ($modulepart == 'facture_fournisseur' || $modulepart == 'invoice_supplier') {
255 require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.facture.class.php';
256 $tmpobject = new FactureFournisseur($this->db);
257 $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
258 if (!$result) {
259 throw new RestException(404, 'Supplier invoice not found');
260 }
261
262 $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
263 $result = $tmpobject->generateDocument($templateused, $outputlangs, $hidedetails, $hidedesc, $hideref);
264 if ($result < 0) {
265 throw new RestException(500, 'Error generating document');
266 }
267 } elseif ($modulepart == 'commande' || $modulepart == 'order') {
268 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
269 $tmpobject = new Commande($this->db);
270 $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
271 if (!$result) {
272 throw new RestException(404, 'Order not found');
273 }
274 $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
275 $result = $tmpobject->generateDocument($templateused, $outputlangs, $hidedetails, $hidedesc, $hideref);
276 if ($result <= 0) {
277 throw new RestException(500, 'Error generating document');
278 }
279 } elseif ($modulepart == 'propal' || $modulepart == 'proposal') {
280 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
281 $tmpobject = new Propal($this->db);
282 $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
283 if (!$result) {
284 throw new RestException(404, 'Proposal not found');
285 }
286 $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
287 $result = $tmpobject->generateDocument($templateused, $outputlangs, $hidedetails, $hidedesc, $hideref);
288 if ($result <= 0) {
289 throw new RestException(500, 'Error generating document');
290 }
291 } elseif ($modulepart == 'contrat' || $modulepart == 'contract') {
292 require_once DOL_DOCUMENT_ROOT . '/contrat/class/contrat.class.php';
293
294 $tmpobject = new Contrat($this->db);
295 $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
296
297 if (!$result) {
298 throw new RestException(404, 'Contract not found');
299 }
300
301 $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
302 $result = $tmpobject->generateDocument($templateused, $outputlangs, $hidedetails, $hidedesc, $hideref);
303
304 if ($result <= 0) {
305 throw new RestException(500, 'Error generating document');
306 }
307 } elseif ($modulepart == 'expedition' || $modulepart == 'shipment') {
308 require_once DOL_DOCUMENT_ROOT . '/expedition/class/expedition.class.php';
309
310 $tmpobject = new Expedition($this->db);
311 $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
312
313 if (!$result) {
314 throw new RestException(404, 'Shipment not found');
315 }
316
317 $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
318 $result = $tmpobject->generateDocument($templateused, $outputlangs, $hidedetails, $hidedesc, $hideref);
319
320 if ($result <= 0) {
321 throw new RestException(500, 'Error generating document');
322 }
323 } elseif ($modulepart == 'mrp') {
324 require_once DOL_DOCUMENT_ROOT . '/mrp/class/mo.class.php';
325
326 $tmpobject = new Mo($this->db);
327 $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
328
329 if (!$result) {
330 throw new RestException(404, 'MO not found');
331 }
332
333 $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
334 $result = $tmpobject->generateDocument($templateused, $outputlangs, $hidedetails, $hidedesc, $hideref);
335
336 if ($result <= 0) {
337 throw new RestException(500, 'Error generating document');
338 }
339 } elseif ($modulepart == 'expensereport') {
340 require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
341
342 $tmpobject = new ExpenseReport($this->db);
343 $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
344
345 if (!$result) {
346 throw new RestException(404, 'Expense report not found');
347 }
348
349 $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
350 $result = $tmpobject->generateDocument($templateused, $outputlangs, $hidedetails, $hidedesc, $hideref);
351
352 if ($result <= 0) {
353 throw new RestException(500, 'Error generating document');
354 }
355 } elseif ($modulepart == 'holiday') {
356 require_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php';
357
358 $tmpobject = new Holiday($this->db);
359 $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
360
361 if (!$result) {
362 throw new RestException(404, 'Holiday not found');
363 }
364
365 $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
366 $result = $tmpobject->generateDocument($templateused, $outputlangs, $hidedetails, $hidedesc, $hideref);
367
368 if ($result <= 0) {
369 throw new RestException(500, 'Error generating document');
370 }
371 } elseif ($modulepart == 'product') {
372 require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
373
374 $tmpobject = new Product($this->db);
375 $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
376
377 if (!$result) {
378 throw new RestException(404, 'Product not found');
379 }
380
381 $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
382 $result = $tmpobject->generateDocument($templateused, $outputlangs, $hidedetails, $hidedesc, $hideref);
383
384 if ($result <= 0) {
385 throw new RestException(500, 'Error generating document');
386 }
387 } elseif ($modulepart == 'stock' || $modulepart == 'entrepot') {
388 require_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php';
389
390 $tmpobject = new Entrepot($this->db);
391 $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
392
393 if (!$result) {
394 throw new RestException(404, 'Warehouse not found');
395 }
396
397 $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
398 $result = $tmpobject->generateDocument($templateused, $outputlangs, $hidedetails, $hidedesc, $hideref);
399
400 if ($result <= 0) {
401 throw new RestException(500, 'Error generating document');
402 }
403 } elseif ($modulepart == 'fichinter' || $modulepart == 'intervention') {
404 require_once DOL_DOCUMENT_ROOT . '/fichinter/class/fichinter.class.php';
405
406 $tmpobject = new Fichinter($this->db);
407 $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
408
409 if (!$result) {
410 throw new RestException(404, 'Intervention not found');
411 }
412
413 $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
414 $result = $tmpobject->generateDocument($templateused, $outputlangs, $hidedetails, $hidedesc, $hideref);
415
416 if ($result <= 0) {
417 throw new RestException(500, 'Error generating document');
418 }
419 } else {
420 throw new RestException(403, 'Generation not available for this modulepart');
421 }
422
423 $filename = basename($original_file);
424 $original_file_osencoded = dol_osencode($original_file); // New file name encoded in OS encoding charset
425
426 if (!file_exists($original_file_osencoded)) {
427 throw new RestException(404, 'File not found');
428 }
429
430 $file_content = file_get_contents($original_file_osencoded);
431 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');
432 }
433
463 public function getDocumentsListByElement($modulepart, $id = 0, $ref = '', $sortfield = '', $sortorder = '', $limit = 100, $page = 0, $content_type = '', $pagination_data = false)
464 {
465 global $conf;
468 if (empty($modulepart)) {
469 throw new RestException(400, 'bad value for parameter modulepart');
470 }
471
472 if (empty($id) && empty($ref)) {
473 throw new RestException(400, 'bad value for parameter id or ref');
474 }
475
476 $id = (empty($id) ? 0 : $id);
477 $recursive = 0;
478 $type = 'files';
479
480 if ($modulepart == 'societe' || $modulepart == 'thirdparty') {
481 require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
482
483 if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
484 throw new RestException(403);
485 }
486
487 $object = new Societe($this->db);
488 $result = $object->fetch($id, $ref);
489 if (!$result) {
490 throw new RestException(404, 'Thirdparty not found');
491 }
492
493 $upload_dir = $conf->societe->multidir_output[$object->entity ?? $conf->entity]."/".$object->id;
494 } elseif ($modulepart == 'user') {
495 require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
496
497 // Can get doc if has permission to read all user or if it is user itself
498 if (!DolibarrApiAccess::$user->hasRight('user', 'user', 'lire') && DolibarrApiAccess::$user->id != $id) {
499 throw new RestException(403);
500 }
501
502 $object = new User($this->db);
503 $result = $object->fetch($id, $ref);
504 if (!$result) {
505 throw new RestException(404, 'User not found');
506 }
507
508 $upload_dir = getMultidirOutput($object) . '/'.get_exdir(0, 0, 0, 0, $object, 'user').'/'.$object->id;
509 } elseif ($modulepart == 'adherent' || $modulepart == 'member') {
510 require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
511
512 if (!DolibarrApiAccess::$user->hasRight('adherent', 'lire')) {
513 throw new RestException(403);
514 }
515
516 $object = new Adherent($this->db);
517 $result = $object->fetch($id, $ref);
518 if (!$result) {
519 throw new RestException(404, 'Member not found');
520 }
521
522 $upload_dir = getMultidirOutput($object) . "/".get_exdir(0, 0, 0, 1, $object, 'member');
523 } elseif ($modulepart == 'propal' || $modulepart == 'proposal') {
524 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
525
526 if (!DolibarrApiAccess::$user->hasRight('propal', 'lire')) {
527 throw new RestException(403);
528 }
529
530 $object = new Propal($this->db);
531 $result = $object->fetch($id, $ref);
532 if (!$result) {
533 throw new RestException(404, 'Proposal not found');
534 }
535
536 $upload_dir = $conf->propal->multidir_output[$object->entity ?? $conf->entity]."/".get_exdir(0, 0, 0, 1, $object, 'propal');
537 } elseif ($modulepart == 'supplier_proposal') {
538 require_once DOL_DOCUMENT_ROOT.'/supplier_proposal/class/supplier_proposal.class.php';
539
540 if (!DolibarrApiAccess::$user->hasRight('supplier_proposal', 'read')) {
541 throw new RestException(403);
542 }
543
544 $object = new Propal($this->db);
545 $result = $object->fetch($id, $ref);
546 if (!$result) {
547 throw new RestException(404, 'Supplier proposal not found');
548 }
549
550 $upload_dir = $conf->propal->multidir_output[$object->entity ?? $conf->entity]."/".get_exdir(0, 0, 0, 1, $object, 'propal');
551 } elseif ($modulepart == 'commande' || $modulepart == 'order') {
552 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
553
554 if (!DolibarrApiAccess::$user->hasRight('commande', 'lire')) {
555 throw new RestException(403);
556 }
557
558 $object = new Commande($this->db);
559 $result = $object->fetch($id, $ref);
560 if (!$result) {
561 throw new RestException(404, 'Order not found');
562 }
563
564 $upload_dir = getMultidirOutput($object). "/".get_exdir(0, 0, 0, 1, $object, 'commande');
565 } elseif ($modulepart == 'commande_fournisseur' || $modulepart == 'supplier_order') {
566 $modulepart = 'supplier_order';
567
568 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
569
570 if (!DolibarrApiAccess::$user->hasRight('fournisseur', 'commande', 'lire') && !DolibarrApiAccess::$user->hasRight('supplier_order', 'lire')) {
571 throw new RestException(403);
572 }
573
574 $object = new CommandeFournisseur($this->db);
575 $result = $object->fetch($id, $ref);
576 if (!$result) {
577 throw new RestException(404, 'Purchase order not found');
578 }
579
580 $upload_dir = getMultidirOutput($object) . "/commande/".dol_sanitizeFileName((string) $object->ref);
581 } elseif ($modulepart == 'shipment' || $modulepart == 'expedition') {
582 require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
583
584 if (!DolibarrApiAccess::$user->hasRight('expedition', 'lire')) {
585 throw new RestException(403);
586 }
587
588 $object = new Expedition($this->db);
589 $result = $object->fetch($id, $ref);
590 if (!$result) {
591 throw new RestException(404, 'Shipment not found');
592 }
593
594 $upload_dir = getMultidirOutput($object) . "/sending/".get_exdir(0, 0, 0, 1, $object, 'shipment');
595 } elseif ($modulepart == 'facture' || $modulepart == 'invoice') {
596 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
597
598 if (!DolibarrApiAccess::$user->hasRight('facture', 'lire')) {
599 throw new RestException(403);
600 }
601
602 $object = new Facture($this->db);
603 $result = $object->fetch($id, $ref);
604 if (!$result) {
605 throw new RestException(404, 'Invoice not found');
606 }
607
608 $upload_dir = getMultidirOutput($object) . "/".get_exdir(0, 0, 0, 1, $object, 'invoice');
609 } elseif ($modulepart == 'facture_fournisseur' || $modulepart == 'supplier_invoice') {
610 $modulepart = 'supplier_invoice';
611
612 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
613
614 if (!DolibarrApiAccess::$user->hasRight('fournisseur', 'facture', 'lire') && !DolibarrApiAccess::$user->hasRight('supplier_invoice', 'lire')) {
615 throw new RestException(403);
616 }
617
618 $object = new FactureFournisseur($this->db);
619 $result = $object->fetch($id, $ref);
620 if (!$result) {
621 throw new RestException(404, 'Invoice not found');
622 }
623
624 $upload_dir = getMultidirOutput($object) . "/".get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier').dol_sanitizeFileName($object->ref);
625 } elseif ($modulepart == 'produit' || $modulepart == 'product' || $modulepart == 'service') {
626 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
627
628 if (!DolibarrApiAccess::$user->hasRight('produit', 'lire')) {
629 throw new RestException(403);
630 }
631
632 $object = new Product($this->db);
633 $result = $object->fetch($id, $ref);
634 if ($result == 0) {
635 throw new RestException(404, 'Product not found');
636 } elseif ($result < 0) {
637 throw new RestException(500, 'Error while fetching object: '.$object->error);
638 }
639
640 $upload_dir = getMultidirOutput($object) . '/'.dol_sanitizeFileName((string) $object->ref);
641 } elseif ($modulepart == 'agenda' || $modulepart == 'action' || $modulepart == 'event' || $modulepart == 'actioncomm') {
642 require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
643
644 if (!DolibarrApiAccess::$user->hasRight('agenda', 'myactions', 'read') && !DolibarrApiAccess::$user->hasRight('agenda', 'allactions', 'read')) {
645 throw new RestException(403);
646 }
647
648 $object = new ActionComm($this->db);
649 $result = $object->fetch($id, $ref);
650 if (!$result) {
651 throw new RestException(404, 'Event not found');
652 }
653
654 $upload_dir = getMultidirOutput($object) . '/'.dol_sanitizeFileName((string) $object->ref);
655 } elseif ($modulepart == 'expensereport') {
656 require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
657
658 if (!DolibarrApiAccess::$user->hasRight('expensereport', 'read')) {
659 throw new RestException(403);
660 }
661
662 $object = new ExpenseReport($this->db);
663 $result = $object->fetch($id, $ref);
664 if (!$result) {
665 throw new RestException(404, 'Expense report not found');
666 }
667
668 $upload_dir = getMultidirOutput($object) . '/'.dol_sanitizeFileName((string) $object->ref);
669 } elseif ($modulepart == 'holiday') {
670 require_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php';
671
672 if (!DolibarrApiAccess::$user->hasRight('holiday', 'read')) {
673 throw new RestException(403);
674 }
675
676 $object = new Holiday($this->db);
677 $result = $object->fetch($id, $ref);
678 if (!$result) {
679 throw new RestException(404, 'Holiday not found');
680 }
681
682 $upload_dir = getMultidirOutput($object) . '/'.dol_sanitizeFileName((string) $object->ref);
683 } elseif ($modulepart == 'ticket') {
684 require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php';
685
686 if (!DolibarrApiAccess::$user->hasRight('ticket', 'read')) {
687 throw new RestException(403);
688 }
689
690 $object = new Ticket($this->db);
691 $result = $object->fetch($id, $ref);
692 if (!$result) {
693 throw new RestException(404, 'Ticket not found');
694 }
695
696 $upload_dir = $conf->ticket->dir_output.'/'.dol_sanitizeFileName((string) $object->ref);
697 } elseif ($modulepart == 'knowledgemanagement') {
698 require_once DOL_DOCUMENT_ROOT.'/knowledgemanagement/class/knowledgerecord.class.php';
699
700 if (!DolibarrApiAccess::$user->hasRight('knowledgemanagement', 'knowledgerecord', 'read')) {
701 throw new RestException(403);
702 }
703
704 $object = new KnowledgeRecord($this->db);
705 $result = $object->fetch($id, $ref);
706 if (!$result) {
707 throw new RestException(404, 'KM article not found');
708 }
709
710 $upload_dir = getMultidirOutput($object) . '/knowledgerecord/'.dol_sanitizeFileName((string) $object->ref);
711 } elseif ($modulepart == 'categorie' || $modulepart == 'category') {
712 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
713
714 if (!DolibarrApiAccess::$user->hasRight('categorie', 'lire')) {
715 throw new RestException(403);
716 }
717
718 $object = new Categorie($this->db);
719 $result = $object->fetch($id, $ref);
720 if (!$result) {
721 throw new RestException(404, 'Category not found');
722 }
723
724 $upload_dir = $conf->categorie->multidir_output[$object->entity ?? $conf->entity].'/'.get_exdir($object->id, 2, 0, 0, $object, 'category').$object->id."/photos/".dol_sanitizeFileName((string) $object->ref);
725 } elseif ($modulepart == 'ecm') {
726 throw new RestException(500, 'Modulepart Ecm not implemented yet.');
727 // require_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmdirectory.class.php';
728
729 // if (!DolibarrApiAccess::$user->hasRight('ecm', 'read')) {
730 // throw new RestException(403);
731 // }
732
733 // // $object = new EcmDirectory($this->db);
734 // // $result = $object->fetch($ref);
735 // // if (!$result) {
736 // // throw new RestException(404, 'EcmDirectory not found');
737 // // }
738 // $upload_dir = $conf->ecm->dir_output;
739 // $type = 'all';
740 // $recursive = 0;
741 } elseif ($modulepart == 'contrat' || $modulepart == 'contract') {
742 $modulepart = 'contrat';
743 require_once DOL_DOCUMENT_ROOT . '/contrat/class/contrat.class.php';
744
745 $object = new Contrat($this->db);
746 $result = $object->fetch($id, $ref);
747 if (!$result) {
748 throw new RestException(404, 'Contract not found');
749 }
750
751 $upload_dir = getMultidirOutput($object) . "/" . get_exdir(0, 0, 0, 1, $object, 'contract');
752 } elseif ($modulepart == 'intervention' || $modulepart == 'ficheinter') {
753 $modulepart = 'ficheinter';
754 require_once DOL_DOCUMENT_ROOT . '/fichinter/class/fichinter.class.php';
755
756 $object = new Fichinter($this->db);
757 $result = $object->fetch($id, $ref);
758 if (!$result) {
759 throw new RestException(404, 'Interventional not found');
760 }
761
762 $upload_dir = $conf->ficheinter->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'ficheinter');
763 } elseif ($modulepart == 'projet' || $modulepart == 'project') {
764 $modulepart = 'project';
765 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
766
767 $object = new Project($this->db);
768 $result = $object->fetch($id, $ref);
769 if (!$result) {
770 throw new RestException(404, 'Project not found');
771 }
772 $upload_dir = $conf->project->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'project');
773 } elseif ($modulepart == 'task' || $modulepart == 'project_task') {
774 $modulepart = 'project_task';
775 require_once DOL_DOCUMENT_ROOT . '/projet/class/task.class.php';
776
777 if (!DolibarrApiAccess::$user->hasRight('projet', 'lire')) {
778 throw new RestException(403);
779 }
780
781 $object = new Task($this->db);
782 $result = $object->fetch($id, $ref);
783 if (!$result) {
784 throw new RestException(404, 'Task not found');
785 }
786
787 // Fetch the project to build the correct path
788 $project_result = $object->fetchProject();
789 if ($project_result < 0) {
790 throw new RestException(500, 'Error while fetching project for task');
791 }
792
793 $upload_dir = $conf->project->dir_output . "/" . dol_sanitizeFileName((string) $object->project->ref) . "/" . dol_sanitizeFileName((string) $object->ref);
794 } elseif ($modulepart == 'mrp') {
795 $modulepart = 'mrp';
796 require_once DOL_DOCUMENT_ROOT . '/mrp/class/mo.class.php';
797
798 $object = new Mo($this->db);
799 $result = $object->fetch($id, $ref);
800 if (!$result) {
801 throw new RestException(404, 'MO not found');
802 }
803
804 $upload_dir = getMultidirOutput($object) . "/" . get_exdir(0, 0, 0, 1, $object, 'mrp');
805 } elseif ($modulepart == 'contact' || $modulepart == 'socpeople') {
806 $modulepart = 'contact';
807 require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
808
809 $object = new Contact($this->db);
810 $result = $object->fetch($id?$id:$ref);
811 if (!$result) {
812 throw new RestException(404, 'Contact not found');
813 }
814 $upload_dir = $conf->societe->multidir_output[$object->entity ?? $conf->entity] . "/contact/" . get_exdir(0, 0, 0, 1, $object, 'contact');
815 } elseif ($modulepart == 'stock') {
816 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
817
818 if (!DolibarrApiAccess::$user->hasRight('stock', 'lire')) {
819 throw new RestException(403);
820 }
821
822 $object = new Entrepot($this->db);
823 $result = $object->fetch($id, $ref);
824 if (!$result) {
825 throw new RestException(404, 'Warehouse not found');
826 }
827 $upload_dir = $conf->stock->multidir_output[$object->entity ?? $conf->entity].'/'.get_exdir(0, 0, 0, 1, $object, 'stock');
828 } else {
829 throw new RestException(500, 'Modulepart '.$modulepart.' not implemented yet.');
830 }
831
832 $objectType = $modulepart;
833 if (! empty($object->id) && ! empty($object->table_element)) {
834 $objectType = $object->table_element;
835 }
836
837 $filearray = dol_dir_list($upload_dir, $type, $recursive, '', '(\.meta|_preview.*\.png)$', $sortfield, (strtolower($sortorder) == 'desc' ? SORT_DESC : SORT_ASC), 1);
838 $countarray = count($filearray);
839 $filearray = array_slice($filearray, $limit * $page, $limit);
840 if (empty($filearray)) {
841 throw new RestException(404, 'Search for modulepart '.$modulepart.' with Id '.$object->id.(!empty($object->ref) ? ' or Ref '.$object->ref : '').' does not return any document.');
842 } else {
843 if (($object->id) > 0 && !empty($modulepart)) {
844 require_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
845 $ecmfile = new EcmFiles($this->db);
846 $result = $ecmfile->fetchAll('', '', 0, 0, array('t.src_object_type' => $objectType, 't.src_object_id' => $object->id));
847 if ($result < 0) {
848 throw new RestException(503, 'Error when retrieve ecm list : '.$this->db->lasterror());
849 } elseif (is_array($ecmfile->lines) && count($ecmfile->lines) > 0) {
850 $count = count($filearray);
851 for ($i = 0 ; $i < $count ; $i++) {
852 foreach ($ecmfile->lines as $line) {
853 unset($line->db);
854 if ($filearray[$i]['name'] == $line->filename) {
855 // Next line converts EcmFilesLine properties to array
856 $filearray[$i] = array_merge($filearray[$i], (array) $line);
857 }
858 }
859 if (isset($filearray[$i]['relativename'])) $filearray[$i]['content-type'] = dol_mimetype($filearray[$i]['relativename']);
860 $arraycontenttype = explode(",", $content_type);
861 if (!empty($content_type) && isset($filearray[$i]['relativename']) && !in_array(dol_mimetype($filearray[$i]['relativename']), $arraycontenttype)) {
862 unset($filearray[$i]);
863 $countarray -= 1;
864 }
865 }
866 }
867 }
868 }
869
870 //if $pagination_data is true the response will contain element data with all values and element pagination with pagination data(total,page,limit)
871 if ($pagination_data) {
872 $tmp = $filearray;
873 $filearray = [];
874 $filearray['data'] = $tmp;
875 $filearray['pagination'] = [
876 'total' => (int) $countarray,
877 'page' => $page, //count starts from 0
878 'page_count' => ceil((int) $countarray / $limit),
879 'limit' => $limit
880 ];
881 }
882
883 return $filearray;
884 }
885
886
895 /*
896 public function get($id) {
897 return array('note'=>'xxx');
898 }*/
899
900
936 public function post($filename, $modulepart, $ref = '', $subdir = '', $filecontent = '', $fileencoding = '', $overwriteifexists = 0, $createdirifnotexists = 1, $position = 0, $cover = '', $array_options = [], $generateThumbs = 0)
937 {
938 global $conf;
939
940 $modulepartorig = $modulepart;
941
942 if (empty($modulepart)) {
943 throw new RestException(400, 'Modulepart not provided.');
944 }
945
946 $newfilecontent = '';
947 if (empty($fileencoding)) {
948 $newfilecontent = $filecontent;
949 }
950 if ($fileencoding == 'base64') {
951 $newfilecontent = base64_decode($filecontent);
952 }
953
954 $original_file = dol_sanitizeFileName($filename);
955 $relativefile = 'UNSET';
956
957 // Define $uploadir
958 $object = null;
959 $entity = DolibarrApiAccess::$user->entity;
960 if (empty($entity)) {
961 $entity = 1;
962 }
963
964 if ($ref) {
965 $tmpreldir = '';
966 $fetchbyid = false;
967
968 if ($modulepart == 'facture' || $modulepart == 'invoice') {
969 $modulepart = 'facture';
970
971 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
972 $object = new Facture($this->db);
973 } elseif ($modulepart == 'facture_fournisseur' || $modulepart == 'supplier_invoice') {
974 $modulepart = 'supplier_invoice';
975
976 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
977 $object = new FactureFournisseur($this->db);
978 } elseif ($modulepart == 'commande' || $modulepart == 'order') {
979 $modulepart = 'commande';
980
981 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
982 $object = new Commande($this->db);
983 } elseif ($modulepart == 'commande_fournisseur' || $modulepart == 'supplier_order') {
984 $modulepart = 'supplier_order';
985
986 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
987 $object = new CommandeFournisseur($this->db);
988 } elseif ($modulepart == 'projet' || $modulepart == 'project') {
989 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
990 $object = new Project($this->db);
991 } elseif ($modulepart == 'task' || $modulepart == 'project_task') {
992 $modulepart = 'project_task';
993
994 require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
995 $object = new Task($this->db);
996
997 $task_result = $object->fetch(0, $ref);
998
999 // Fetching the tasks project is required because its out_dir might be a sub-directory of the project
1000 if ($task_result > 0) {
1001 $project_result = $object->fetchProject();
1002
1003 if ($project_result >= 0) {
1004 $tmpreldir = dol_sanitizeFileName((string) $object->project->ref).'/';
1005 }
1006 } else {
1007 throw new RestException(500, 'Error while fetching Task '.$ref);
1008 }
1009 } elseif ($modulepart == 'product' || $modulepart == 'produit' || $modulepart == 'service' || $modulepart == 'produit|service') {
1010 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
1011 $object = new Product($this->db);
1012 } elseif ($modulepart == 'expensereport') {
1013 require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
1014 $object = new ExpenseReport($this->db);
1015 } elseif ($modulepart == 'holiday') {
1016 require_once DOL_DOCUMENT_ROOT.'/holiday/class/holiday.class.php';
1017 $object = new Holiday($this->db);
1018 } elseif ($modulepart == 'ficheinter' || $modulepart == 'intervention') {
1019 require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
1020 $object = new Fichinter($this->db);
1021 } elseif ($modulepart == 'shipment' || $modulepart == 'expedition') {
1022 require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
1023 $object = new Expedition($this->db);
1024 } elseif ($modulepart == 'adherent' || $modulepart == 'member') {
1025 $modulepart = 'adherent';
1026 require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
1027 $object = new Adherent($this->db);
1028 } elseif ($modulepart == 'proposal' || $modulepart == 'propal' || $modulepart == 'propale') {
1029 $modulepart = 'propale';
1030 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
1031 $object = new Propal($this->db);
1032 } elseif ($modulepart == 'agenda' || $modulepart == 'action' || $modulepart == 'event') {
1033 $modulepart = 'agenda';
1034 require_once DOL_DOCUMENT_ROOT . '/comm/action/class/actioncomm.class.php';
1035 $object = new ActionComm($this->db);
1036 } elseif ($modulepart == 'contact' || $modulepart == 'socpeople') {
1037 $modulepart = 'contact';
1038 require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
1039 $object = new Contact($this->db);
1040 $fetchbyid = true;
1041 } elseif ($modulepart == 'societe' || $modulepart == 'company') {
1042 $modulepart = 'societe';
1043 require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
1044 $object = new Societe($this->db);
1045 $fetchbyid = true;
1046 } elseif ($modulepart == 'knowledgemanagement' ) {
1047 $modulepart = 'knowledgemanagement';
1048 require_once DOL_DOCUMENT_ROOT.'/knowledgemanagement/class/knowledgerecord.class.php';
1049 $object = new KnowledgeRecord($this->db);
1050 $fetchbyid = true;
1051 } elseif ($modulepart == 'ticket' ) {
1052 $modulepart = 'ticket';
1053 require_once DOL_DOCUMENT_ROOT.'/ticket/class/ticket.class.php';
1054 $object = new Ticket($this->db);
1055 $fetchbyid = true;
1056 } elseif ($modulepart == 'contrat' || $modulepart == 'contract') {
1057 $modulepart = 'contrat';
1058 require_once DOL_DOCUMENT_ROOT . '/contrat/class/contrat.class.php';
1059 $object = new Contrat($this->db);
1060 } elseif ($modulepart == 'mrp') {
1061 $modulepart = 'mrp';
1062 require_once DOL_DOCUMENT_ROOT . '/mrp/class/mo.class.php';
1063 $object = new Mo($this->db);
1064 } elseif ($modulepart == 'stock') {
1065 $modulepart = 'stock';
1066 require_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php';
1067 $object = new Entrepot($this->db);
1068 } elseif ($modulepart == 'ecm') {
1069 throw new RestException(500, 'Using a non empty "ref" is not compatible with using modulepart = '.$modulepart);
1070 } else {
1071 // TODO Implement additional moduleparts
1072 throw new RestException(500, 'Modulepart '.$modulepart.' not implemented yet.');
1073 }
1074
1075 // at this step $object is always an object
1076 if ($fetchbyid) {
1077 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1078 $result = $object->fetch((int) $ref);
1079 } else {
1080 $result = $object->fetch(0, $ref);
1081 }
1082
1083 if ($result == 0) {
1084 throw new RestException(404, "Object with ref '".$ref."' was not found.");
1085 } elseif ($result < 0) {
1086 throw new RestException(500, 'Error while fetching object: '.$object->error);
1087 }
1088
1089 if (!($object->id > 0)) {
1090 throw new RestException(404, 'The object '.$modulepart." with ref '".$ref."' was not found.");
1091 }
1092
1093 // Special cases that need to use get_exdir to get real dir of object
1094 // In future, all object should use this to define path of documents.
1095 if ($modulepart == 'supplier_invoice') {
1096 $tmpreldir = get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier');
1097 }
1098
1099 // Test on permissions
1100 //if ($modulepart != 'ecm') { // Here $modulepart is always != 'ecm'
1101 if ($modulepart == 'societe') {
1102 $relativefile = $tmpreldir.dol_sanitizeFileName((string) $object->id);
1103 } else {
1104 $relativefile = $tmpreldir.dol_sanitizeFileName((string) $object->ref);
1105 }
1106 $tmp = dol_check_secure_access_document($modulepart, $relativefile, $entity, DolibarrApiAccess::$user, $ref, 'write');
1107 $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
1108 /*} else {
1109 if (!DolibarrApiAccess::$user->hasRight('ecm', 'upload')) {
1110 throw new RestException(403, 'Missing permission to upload files in ECM module');
1111 }
1112 $upload_dir = $conf->medias->multidir_output[$conf->entity];
1113 }*/
1114
1115 if (empty($upload_dir) || $upload_dir == '/') {
1116 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.');
1117 }
1118 } else {
1119 if ($modulepart == 'invoice') {
1120 $modulepart = 'facture';
1121 }
1122 if ($modulepart == 'member') {
1123 $modulepart = 'adherent';
1124 }
1125
1126 // Test on permissions
1127 if ($modulepart != 'ecm') {
1128 $relativefile = $subdir;
1129 $tmp = dol_check_secure_access_document($modulepart, $relativefile, $entity, DolibarrApiAccess::$user, '', 'write');
1130 $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
1131 } else {
1132 if (!DolibarrApiAccess::$user->hasRight('ecm', 'upload')) {
1133 throw new RestException(403, 'Missing permission to upload files in ECM module');
1134 }
1135 $upload_dir = $conf->medias->multidir_output[$conf->entity];
1136 }
1137
1138 if (empty($upload_dir) || $upload_dir == '/') {
1139 if (!empty($tmp['error'])) {
1140 throw new RestException(403, 'Error returned by dol_check_secure_access_document: '.$tmp['error']);
1141 } else {
1142 throw new RestException(400, 'This value of modulepart ('.$modulepart.') is not allowed with this value of subdir ('.$relativefile.')');
1143 }
1144 }
1145 }
1146 // $original_file here is still value of filename without any dir.
1147
1148 $upload_dir = dol_sanitizePathName($upload_dir);
1149
1150 if (!empty($createdirifnotexists)) {
1151 if (dol_mkdir($upload_dir) < 0) { // needed by products
1152 throw new RestException(500, 'Error while trying to create directory '.$upload_dir);
1153 }
1154 }
1155
1156 $destfile = $upload_dir.'/'.$original_file;
1157 $destfiletmp = DOL_DATA_ROOT.'/admin/temp/'.$original_file;
1158 dol_delete_file($destfiletmp);
1159 //var_dump($original_file);exit;
1160
1161 if (!dol_is_dir(dirname($destfile))) {
1162 throw new RestException(400, 'Directory does not exists : '.dirname($destfile));
1163 }
1164
1165 if (!$overwriteifexists && dol_is_file($destfile)) {
1166 throw new RestException(400, "File with name '".$original_file."' already exists.");
1167 }
1168
1169 // in case temporary directory admin/temp doesn't exist
1170 if (!dol_is_dir(dirname($destfiletmp))) {
1171 dol_mkdir(dirname($destfiletmp));
1172 }
1173
1174 $fhandle = @fopen($destfiletmp, 'w');
1175 if ($fhandle) {
1176 $nbofbyteswrote = fwrite($fhandle, $newfilecontent);
1177 fclose($fhandle);
1178 dolChmod($destfiletmp);
1179 } else {
1180 throw new RestException(500, "Failed to open file '".$destfiletmp."' for write");
1181 }
1182
1183 $disablevirusscan = 0;
1184 $src_file = $destfiletmp;
1185 $dest_file = $destfile;
1186
1187 // Security:
1188 // If we need to make a virus scan
1189 if (empty($disablevirusscan) && file_exists($src_file)) {
1190 $checkvirusarray = dolCheckVirus($src_file, $dest_file);
1191 if (count($checkvirusarray)) {
1192 dol_syslog('Files.lib::dol_move_uploaded_file File "'.$src_file.'" (target name "'.$dest_file.'") KO with antivirus: errors='.implode(',', $checkvirusarray), LOG_WARNING);
1193 throw new RestException(500, 'ErrorFileIsInfectedWithAVirus: '.implode(',', $checkvirusarray));
1194 }
1195 }
1196
1197 // Security:
1198 // Disallow file with some extensions. We rename them.
1199 // Because if we put the documents directory into a directory inside web root (very bad), this allows to execute on demand arbitrary code.
1200 if (isAFileWithExecutableContent($dest_file) && !getDolGlobalString('MAIN_DOCUMENT_IS_OUTSIDE_WEBROOT_SO_NOEXE_NOT_REQUIRED')) {
1201 // $upload_dir ends with a slash, so be must be sure the medias dir to compare to ends with slash too.
1202 $publicmediasdirwithslash = $conf->medias->multidir_output[$conf->entity];
1203 if (!preg_match('/\/$/', $publicmediasdirwithslash)) {
1204 $publicmediasdirwithslash .= '/';
1205 }
1206
1207 if (strpos($upload_dir, $publicmediasdirwithslash) !== 0 || !getDolGlobalInt("MAIN_DOCUMENT_DISABLE_NOEXE_IN_MEDIAS_DIR")) { // We never add .noexe on files into media directory
1208 $dest_file .= '.noexe';
1209 }
1210 }
1211
1212 // Security:
1213 // We refuse cache files/dirs, upload using .. and pipes into filenames.
1214 if (preg_match('/^\./', basename($src_file)) || preg_match('/\.\./', $src_file) || preg_match('/[<>|]/', $src_file)) {
1215 dol_syslog("Refused to deliver file ".$src_file, LOG_WARNING);
1216 throw new RestException(500, "Refused to deliver file ".$src_file);
1217 }
1218
1219 // Security:
1220 // We refuse cache files/dirs, upload using .. and pipes into filenames.
1221 if (preg_match('/^\./', basename($dest_file)) || preg_match('/\.\./', $dest_file) || preg_match('/[<>|]/', $dest_file)) {
1222 dol_syslog("Refused to deliver file ".$dest_file, LOG_WARNING);
1223 throw new RestException(500, "Refused to deliver file ".$dest_file);
1224 }
1225
1226 $moreinfo = array('note_private' => 'File uploaded using API /documents from IP '.getUserRemoteIP());
1227 // $object may be null
1228 if (is_object($object) && $object->id > 0) {
1229 $moreinfo['src_object_type'] = $object->table_element;
1230 $moreinfo['src_object_id'] = $object->id;
1231 }
1232 if (!empty($array_options)) {
1233 $moreinfo = array_merge($moreinfo, ["array_options" => $array_options]);
1234 }
1235 if (!empty($position)) {
1236 $moreinfo = array_merge($moreinfo, ["position" => $position]);
1237 }
1238 if (!empty($cover)) {
1239 $moreinfo = array_merge($moreinfo, ["cover" => $cover]);
1240 }
1241 $moreinfo['gen_or_uploaded'] = 'api';
1242
1243 // Move the temporary file at its final emplacement
1244 $result = dol_move($destfiletmp, $dest_file, '0', $overwriteifexists, 1, 1, $moreinfo);
1245 if (!$result) {
1246 throw new RestException(500, "Failed to move file into '".$dest_file."'");
1247 }
1248
1249 if (is_object($object) && $generateThumbs) {
1250 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1251 if (image_format_supported($dest_file)) {
1252 $object->addThumbs($dest_file);
1253 }
1254 }
1255
1256 return dol_basename($destfile);
1257 }
1258
1278 public function delete($modulepart, $original_file)
1279 {
1280 global $conf;
1281
1282 if (empty($modulepart)) {
1283 throw new RestException(400, 'bad value for parameter modulepart');
1284 }
1285 if (empty($original_file)) {
1286 throw new RestException(400, 'bad value for parameter original_file');
1287 }
1288
1289 // Normalize modulepart for project_task
1290 if ($modulepart == 'task') {
1291 $modulepart = 'project_task';
1292 }
1293
1294 //--- Finds and returns the document
1295 $entity = $conf->entity;
1296
1297 // Special cases that need to use get_exdir to get real dir of object
1298 // If future, all object should use this to define path of documents.
1299 /*
1300 $tmpreldir = '';
1301 if ($modulepart == 'supplier_invoice') {
1302 $tmpreldir = get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier');
1303 }
1304
1305 $relativefile = $tmpreldir.dol_sanitizeFileName($object->ref); */
1306 $relativefile = $original_file;
1307
1308 $check_access = dol_check_secure_access_document($modulepart, $relativefile, $entity, DolibarrApiAccess::$user, '', 'read');
1309 $accessallowed = $check_access['accessallowed'];
1310 $sqlprotectagainstexternals = $check_access['sqlprotectagainstexternals'];
1311 $original_file = $check_access['original_file'];
1312
1313 if (preg_match('/\.\./', $original_file) || preg_match('/[<>|]/', $original_file)) {
1314 throw new RestException(403);
1315 }
1316 if (!$accessallowed) {
1317 throw new RestException(403);
1318 }
1319
1320 if (DolibarrApiAccess::$user->socid > 0) {
1321 if ($sqlprotectagainstexternals) {
1322 $resql = $this->db->query($sqlprotectagainstexternals);
1323 if ($resql) {
1324 $num = $this->db->num_rows($resql);
1325 $i = 0;
1326 while ($i < $num) {
1327 $obj = $this->db->fetch_object($resql);
1328 if (DolibarrApiAccess::$user->socid != $obj->fk_soc) {
1329 throw new RestException(403, 'Not allowed to download documents with such a ref');
1330 }
1331 $i++;
1332 }
1333 }
1334 }
1335 }
1336
1337 $filename = basename($original_file);
1338 $original_file_osencoded = dol_osencode($original_file); // New file name encoded in OS encoding charset
1339
1340 if (!file_exists($original_file_osencoded)) {
1341 dol_syslog("Try to download not found file ".$original_file_osencoded, LOG_WARNING);
1342 throw new RestException(404, 'File not found');
1343 }
1344
1345 if (@unlink($original_file_osencoded)) {
1346 return array(
1347 'success' => array(
1348 'code' => 200,
1349 'message' => 'Document deleted'
1350 )
1351 );
1352 }
1353
1354 throw new RestException(403);
1355 }
1356}
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
Class to manage agenda events (actions)
Class to manage members of a foundation.
Class to manage categories.
Class to manage predefined suppliers products.
Class to manage customers orders.
Class to manage contact/addresses.
API class for receive files.
__construct()
Constructor.
index($modulepart, $original_file='')
Download a document.
builddoc($modulepart, $original_file='', $doctemplate='', $langcode='')
Build a document.
post($filename, $modulepart, $ref='', $subdir='', $filecontent='', $fileencoding='', $overwriteifexists=0, $createdirifnotexists=1, $position=0, $cover='', $array_options=[], $generateThumbs=0)
Return a document.
Class for API REST v1.
Definition api.class.php:35
Class to manage ECM files.
Class to manage warehouses.
Class to manage Trips and Expenses.
Class to manage suppliers invoices.
Class to manage invoices.
Class of the module paid holiday.
Class for KnowledgeRecord.
Class for Mo.
Definition mo.class.php:35
Class to manage products or services.
Class to manage projects.
Class to manage proposals.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage tasks.
Class to manage translations.
Class to manage Dolibarr users.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_move($srcfile, $destfile, $newmask='0', $overwriteifexists=1, $testvirus=0, $indexdatabase=1, $moreinfo=array(), $entity=null)
Move a file into another name.
dol_basename($pathfile)
Make a basename working with all page code (default PHP basenamed fails with cyrillic).
Definition files.lib.php:39
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
dol_check_secure_access_document($modulepart, $original_file, $entity, $fuser=null, $refname='', $mode='read')
Security check when accessing to a document (used by document.php, viewimage.php and webservices to g...
dol_is_file($pathoffile)
Return if path is a file.
dolCheckVirus($src_file, $dest_file='')
Check virus into a file.
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition files.lib.php:64
dol_is_dir($folder)
Test if filename is a directory.
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
dol_sanitizePathName($str, $newstr='_', $unaccent=0, $allowdash=0)
Clean a string to use it as a path name.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
dolChmod($filepath, $newmask='')
Change mod of a file.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
getMultidirOutput($object, $module='', $forobject=0, $mode='output')
Return the full path of the directory where a module (or an object of a module) stores its files.
getUserRemoteIP($trusted=0)
Return the real IP of remote user.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart='')
Return a path to have a the directory according to object where files are stored.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
image_format_supported($file, $acceptsvg=0)
Return if a filename is file name of a supported image format.
Class to generate the form for creating a new ticket.