dolibarr 21.0.0-alpha
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) 2024 Frédéric France <frederic.france@free.fr>
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') && !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
677 public function post($filename, $modulepart, $ref = '', $subdir = '', $filecontent = '', $fileencoding = '', $overwriteifexists = 0, $createdirifnotexists = 1, $position = 0, $cover = '', $array_options = [])
678 {
679 global $conf;
680
681 $modulepartorig = $modulepart;
682
683 if (empty($modulepart)) {
684 throw new RestException(400, 'Modulepart not provided.');
685 }
686
687 $newfilecontent = '';
688 if (empty($fileencoding)) {
689 $newfilecontent = $filecontent;
690 }
691 if ($fileencoding == 'base64') {
692 $newfilecontent = base64_decode($filecontent);
693 }
694
695 $original_file = dol_sanitizeFileName($filename);
696
697 // Define $uploadir
698 $object = null;
699 $entity = DolibarrApiAccess::$user->entity;
700 if (empty($entity)) {
701 $entity = 1;
702 }
703
704 if ($ref) {
705 $tmpreldir = '';
706 $fetchbyid = false;
707
708 if ($modulepart == 'facture' || $modulepart == 'invoice') {
709 $modulepart = 'facture';
710
711 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
712 $object = new Facture($this->db);
713 } elseif ($modulepart == 'facture_fournisseur' || $modulepart == 'supplier_invoice') {
714 $modulepart = 'supplier_invoice';
715
716 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
717 $object = new FactureFournisseur($this->db);
718 } elseif ($modulepart == 'commande' || $modulepart == 'order') {
719 $modulepart = 'commande';
720
721 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
722 $object = new Commande($this->db);
723 } elseif ($modulepart == 'commande_fournisseur' || $modulepart == 'supplier_order') {
724 $modulepart = 'supplier_order';
725
726 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
727 $object = new CommandeFournisseur($this->db);
728 } elseif ($modulepart == 'projet' || $modulepart == 'project') {
729 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
730 $object = new Project($this->db);
731 } elseif ($modulepart == 'task' || $modulepart == 'project_task') {
732 $modulepart = 'project_task';
733
734 require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
735 $object = new Task($this->db);
736
737 $task_result = $object->fetch(0, $ref);
738
739 // Fetching the tasks project is required because its out_dir might be a sub-directory of the project
740 if ($task_result > 0) {
741 $project_result = $object->fetchProject();
742
743 if ($project_result >= 0) {
744 $tmpreldir = dol_sanitizeFileName($object->project->ref).'/';
745 }
746 } else {
747 throw new RestException(500, 'Error while fetching Task '.$ref);
748 }
749 } elseif ($modulepart == 'product' || $modulepart == 'produit' || $modulepart == 'service' || $modulepart == 'produit|service') {
750 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
751 $object = new Product($this->db);
752 } elseif ($modulepart == 'expensereport') {
753 require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
754 $object = new ExpenseReport($this->db);
755 } elseif ($modulepart == 'fichinter') {
756 require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
757 $object = new Fichinter($this->db);
758 } elseif ($modulepart == 'adherent' || $modulepart == 'member') {
759 $modulepart = 'adherent';
760 require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
761 $object = new Adherent($this->db);
762 } elseif ($modulepart == 'proposal' || $modulepart == 'propal' || $modulepart == 'propale') {
763 $modulepart = 'propale';
764 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
765 $object = new Propal($this->db);
766 } elseif ($modulepart == 'agenda' || $modulepart == 'action' || $modulepart == 'event') {
767 $modulepart = 'agenda';
768 require_once DOL_DOCUMENT_ROOT . '/comm/action/class/actioncomm.class.php';
769 $object = new ActionComm($this->db);
770 } elseif ($modulepart == 'contact' || $modulepart == 'socpeople') {
771 $modulepart = 'contact';
772 require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
773 $object = new Contact($this->db);
774 $fetchbyid = true;
775 } elseif ($modulepart == 'contrat' || $modulepart == 'contract') {
776 $modulepart = 'contrat';
777 require_once DOL_DOCUMENT_ROOT . '/contrat/class/contrat.class.php';
778 $object = new Contrat($this->db);
779 } elseif ($modulepart == 'mrp') {
780 $modulepart = 'mrp';
781 require_once DOL_DOCUMENT_ROOT . '/mrp/class/mo.class.php';
782 $object = new Mo($this->db);
783 } else {
784 // TODO Implement additional moduleparts
785 throw new RestException(500, 'Modulepart '.$modulepart.' not implemented yet.');
786 }
787
788 if (is_object($object)) {
789 if ($fetchbyid) {
790 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
791 $result = $object->fetch($ref);
792 } else {
793 $result = $object->fetch(0, $ref);
794 }
795
796 if ($result == 0) {
797 throw new RestException(404, "Object with ref '".$ref."' was not found.");
798 } elseif ($result < 0) {
799 throw new RestException(500, 'Error while fetching object: '.$object->error);
800 }
801 }
802
803 if (!($object->id > 0)) {
804 throw new RestException(404, 'The object '.$modulepart." with ref '".$ref."' was not found.");
805 }
806
807 // Special cases that need to use get_exdir to get real dir of object
808 // In future, all object should use this to define path of documents.
809 if ($modulepart == 'supplier_invoice') {
810 $tmpreldir = get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier');
811 }
812
813 // Test on permissions
814 if ($modulepart != 'ecm') {
815 $relativefile = $tmpreldir.dol_sanitizeFileName($object->ref);
816 $tmp = dol_check_secure_access_document($modulepart, $relativefile, $entity, DolibarrApiAccess::$user, $ref, 'write');
817 $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
818 } else {
819 if (!DolibarrApiAccess::$user->hasRight('ecm', 'upload')) {
820 throw new RestException(403, 'Missing permission to upload files in ECM module');
821 }
822 $upload_dir = $conf->medias->multidir_output[$conf->entity];
823 }
824
825 if (empty($upload_dir) || $upload_dir == '/') {
826 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.');
827 }
828 } else {
829 if ($modulepart == 'invoice') {
830 $modulepart = 'facture';
831 }
832 if ($modulepart == 'member') {
833 $modulepart = 'adherent';
834 }
835
836 // Test on permissions
837 if ($modulepart != 'ecm') {
838 $relativefile = $subdir;
839 $tmp = dol_check_secure_access_document($modulepart, $relativefile, $entity, DolibarrApiAccess::$user, '', 'write');
840 $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
841 } else {
842 if (!DolibarrApiAccess::$user->hasRight('ecm', 'upload')) {
843 throw new RestException(403, 'Missing permission to upload files in ECM module');
844 }
845 $upload_dir = $conf->medias->multidir_output[$conf->entity];
846 }
847
848 if (empty($upload_dir) || $upload_dir == '/') {
849 if (!empty($tmp['error'])) {
850 throw new RestException(403, 'Error returned by dol_check_secure_access_document: '.$tmp['error']);
851 } else {
852 throw new RestException(400, 'This value of modulepart ('.$modulepart.') is not allowed with this value of subdir ('.$relativefile.')');
853 }
854 }
855 }
856 // $original_file here is still value of filename without any dir.
857
858 $upload_dir = dol_sanitizePathName($upload_dir);
859
860 if (!empty($createdirifnotexists)) {
861 if (dol_mkdir($upload_dir) < 0) { // needed by products
862 throw new RestException(500, 'Error while trying to create directory '.$upload_dir);
863 }
864 }
865
866 $destfile = $upload_dir.'/'.$original_file;
867 $destfiletmp = DOL_DATA_ROOT.'/admin/temp/'.$original_file;
868 dol_delete_file($destfiletmp);
869 //var_dump($original_file);exit;
870
871 if (!dol_is_dir(dirname($destfile))) {
872 throw new RestException(400, 'Directory does not exists : '.dirname($destfile));
873 }
874
875 if (!$overwriteifexists && dol_is_file($destfile)) {
876 throw new RestException(400, "File with name '".$original_file."' already exists.");
877 }
878
879 // in case temporary directory admin/temp doesn't exist
880 if (!dol_is_dir(dirname($destfiletmp))) {
881 dol_mkdir(dirname($destfiletmp));
882 }
883
884 $fhandle = @fopen($destfiletmp, 'w');
885 if ($fhandle) {
886 $nbofbyteswrote = fwrite($fhandle, $newfilecontent);
887 fclose($fhandle);
888 dolChmod($destfiletmp);
889 } else {
890 throw new RestException(500, "Failed to open file '".$destfiletmp."' for write");
891 }
892
893 $disablevirusscan = 0;
894 $src_file = $destfiletmp;
895 $dest_file = $destfile;
896
897 // Security:
898 // If we need to make a virus scan
899 if (empty($disablevirusscan) && file_exists($src_file)) {
900 $checkvirusarray = dolCheckVirus($src_file, $dest_file);
901 if (count($checkvirusarray)) {
902 dol_syslog('Files.lib::dol_move_uploaded_file File "'.$src_file.'" (target name "'.$dest_file.'") KO with antivirus: errors='.implode(',', $checkvirusarray), LOG_WARNING);
903 throw new RestException(500, 'ErrorFileIsInfectedWithAVirus: '.implode(',', $checkvirusarray));
904 }
905 }
906
907 // Security:
908 // Disallow file with some extensions. We rename them.
909 // Because if we put the documents directory into a directory inside web root (very bad), this allows to execute on demand arbitrary code.
910 if (isAFileWithExecutableContent($dest_file) && !getDolGlobalString('MAIN_DOCUMENT_IS_OUTSIDE_WEBROOT_SO_NOEXE_NOT_REQUIRED')) {
911 // $upload_dir ends with a slash, so be must be sure the medias dir to compare to ends with slash too.
912 $publicmediasdirwithslash = $conf->medias->multidir_output[$conf->entity];
913 if (!preg_match('/\/$/', $publicmediasdirwithslash)) {
914 $publicmediasdirwithslash .= '/';
915 }
916
917 if (strpos($upload_dir, $publicmediasdirwithslash) !== 0 || !getDolGlobalInt("MAIN_DOCUMENT_DISABLE_NOEXE_IN_MEDIAS_DIR")) { // We never add .noexe on files into media directory
918 $dest_file .= '.noexe';
919 }
920 }
921
922 // Security:
923 // We refuse cache files/dirs, upload using .. and pipes into filenames.
924 if (preg_match('/^\./', basename($src_file)) || preg_match('/\.\./', $src_file) || preg_match('/[<>|]/', $src_file)) {
925 dol_syslog("Refused to deliver file ".$src_file, LOG_WARNING);
926 throw new RestException(500, "Refused to deliver file ".$src_file);
927 }
928
929 // Security:
930 // We refuse cache files/dirs, upload using .. and pipes into filenames.
931 if (preg_match('/^\./', basename($dest_file)) || preg_match('/\.\./', $dest_file) || preg_match('/[<>|]/', $dest_file)) {
932 dol_syslog("Refused to deliver file ".$dest_file, LOG_WARNING);
933 throw new RestException(500, "Refused to deliver file ".$dest_file);
934 }
935
936 $moreinfo = array('note_private' => 'File uploaded using API /documents from IP '.getUserRemoteIP());
937 if (!empty($object) && is_object($object) && $object->id > 0) {
938 $moreinfo['src_object_type'] = $object->table_element;
939 $moreinfo['src_object_id'] = $object->id;
940 }
941 if (!empty($array_options)) {
942 $moreinfo = array_merge($moreinfo, ["array_options" => $array_options]);
943 }
944 if (!empty($position)) {
945 $moreinfo = array_merge($moreinfo, ["position" => $position]);
946 }
947 if (!empty($cover)) {
948 $moreinfo = array_merge($moreinfo, ["cover" => $cover]);
949 }
950
951 // Move the temporary file at its final emplacement
952 $result = dol_move($destfiletmp, $dest_file, '0', $overwriteifexists, 1, 1, $moreinfo);
953 if (!$result) {
954 throw new RestException(500, "Failed to move file into '".$dest_file."'");
955 }
956
957 return dol_basename($destfile);
958 }
959
975 public function delete($modulepart, $original_file)
976 {
977 global $conf, $langs;
978
979 if (empty($modulepart)) {
980 throw new RestException(400, 'bad value for parameter modulepart');
981 }
982 if (empty($original_file)) {
983 throw new RestException(400, 'bad value for parameter original_file');
984 }
985
986 //--- Finds and returns the document
987 $entity = $conf->entity;
988
989 // Special cases that need to use get_exdir to get real dir of object
990 // If future, all object should use this to define path of documents.
991 /*
992 $tmpreldir = '';
993 if ($modulepart == 'supplier_invoice') {
994 $tmpreldir = get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier');
995 }
996
997 $relativefile = $tmpreldir.dol_sanitizeFileName($object->ref); */
998 $relativefile = $original_file;
999
1000 $check_access = dol_check_secure_access_document($modulepart, $relativefile, $entity, DolibarrApiAccess::$user, '', 'read');
1001 $accessallowed = $check_access['accessallowed'];
1002 $sqlprotectagainstexternals = $check_access['sqlprotectagainstexternals'];
1003 $original_file = $check_access['original_file'];
1004
1005 if (preg_match('/\.\./', $original_file) || preg_match('/[<>|]/', $original_file)) {
1006 throw new RestException(403);
1007 }
1008 if (!$accessallowed) {
1009 throw new RestException(403);
1010 }
1011
1012 $filename = basename($original_file);
1013 $original_file_osencoded = dol_osencode($original_file); // New file name encoded in OS encoding charset
1014
1015 if (!file_exists($original_file_osencoded)) {
1016 dol_syslog("Try to download not found file ".$original_file_osencoded, LOG_WARNING);
1017 throw new RestException(404, 'File not found');
1018 }
1019
1020 if (@unlink($original_file_osencoded)) {
1021 return array(
1022 'success' => array(
1023 'code' => 200,
1024 'message' => 'Document deleted'
1025 )
1026 );
1027 }
1028
1029 throw new RestException(403);
1030 }
1031}
$id
Definition account.php:39
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.
API class for receive files.
post($filename, $modulepart, $ref='', $subdir='', $filecontent='', $fileencoding='', $overwriteifexists=0, $createdirifnotexists=1, $position=0, $cover='', $array_options=[])
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:30
Class to manage ECM files.
Class to manage Trips and Expenses.
Class to manage suppliers invoices.
Class to manage invoices.
Class for KnowledgeRecord.
Class for Mo.
Definition mo.class.php:34
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 a 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)