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