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