dolibarr 19.0.4
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.'/api/class/api.class.php';
26require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
27
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;
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 = !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS') ? 0 : 1;
185 $hidedesc = !getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DESC') ? 0 : 1;
186 $hideref = !getDolGlobalString('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 $tmpobject = new Facture($this->db);
193 $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
194 if (!$result) {
195 throw new RestException(404, 'Invoice not found');
196 }
197
198 $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
199 $result = $tmpobject->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 $tmpobject = new FactureFournisseur($this->db);
206 $result = $tmpobject->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 : $tmpobject->model_pdf;
212 $result = $tmpobject->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 $tmpobject = new Commande($this->db);
219 $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
220 if (!$result) {
221 throw new RestException(404, 'Order not found');
222 }
223 $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
224 $result = $tmpobject->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 $tmpobject = new Propal($this->db);
231 $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
232 if (!$result) {
233 throw new RestException(404, 'Proposal not found');
234 }
235 $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
236 $result = $tmpobject->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 $tmpobject = new Contrat($this->db);
244 $result = $tmpobject->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 : $tmpobject->model_pdf;
251 $result = $tmpobject->generateDocument($templateused, $outputlangs, $hidedetails, $hidedesc, $hideref);
252
253 if ($result <= 0) {
254 throw new RestException(500, 'Error generating document missing doctemplate parameter');
255 }
256 } elseif ($modulepart == 'expedition' || $modulepart == 'shipment') {
257 require_once DOL_DOCUMENT_ROOT . '/expedition/class/expedition.class.php';
258
259 $tmpobject = new Expedition($this->db);
260 $result = $tmpobject->fetch(0, preg_replace('/\.[^\.]+$/', '', basename($original_file)));
261
262 if (!$result) {
263 throw new RestException(404, 'Shipment not found');
264 }
265
266 $templateused = $doctemplate ? $doctemplate : $tmpobject->model_pdf;
267 $result = $tmpobject->generateDocument($templateused, $outputlangs, $hidedetails, $hidedesc, $hideref);
268
269 if ($result <= 0) {
270 throw new RestException(500, 'Error generating document missing doctemplate parameter');
271 }
272 } else {
273 throw new RestException(403, 'Generation not available for this modulepart');
274 }
275
276 $filename = basename($original_file);
277 $original_file_osencoded = dol_osencode($original_file); // New file name encoded in OS encoding charset
278
279 if (!file_exists($original_file_osencoded)) {
280 throw new RestException(404, 'File not found');
281 }
282
283 $file_content = file_get_contents($original_file_osencoded);
284 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');
285 }
286
306 public function getDocumentsListByElement($modulepart, $id = 0, $ref = '', $sortfield = '', $sortorder = '')
307 {
308 global $conf;
309
310 if (empty($modulepart)) {
311 throw new RestException(400, 'bad value for parameter modulepart');
312 }
313
314 if (empty($id) && empty($ref)) {
315 throw new RestException(400, 'bad value for parameter id or ref');
316 }
317
318 $id = (empty($id) ? 0 : $id);
319 $recursive = 0;
320 $type = 'files';
321
322 if ($modulepart == 'societe' || $modulepart == 'thirdparty') {
323 require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
324
325 if (!DolibarrApiAccess::$user->hasRight('societe', 'lire')) {
326 throw new RestException(401);
327 }
328
329 $object = new Societe($this->db);
330 $result = $object->fetch($id, $ref);
331 if (!$result) {
332 throw new RestException(404, 'Thirdparty not found');
333 }
334
335 $upload_dir = $conf->societe->multidir_output[$object->entity]."/".$object->id;
336 } elseif ($modulepart == 'user') {
337 require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
338
339 // Can get doc if has permission to read all user or if it is user itself
340 if (!DolibarrApiAccess::$user->rights->user->user->lire && DolibarrApiAccess::$user->id != $id) {
341 throw new RestException(401);
342 }
343
344 $object = new User($this->db);
345 $result = $object->fetch($id, $ref);
346 if (!$result) {
347 throw new RestException(404, 'User not found');
348 }
349
350 $upload_dir = $conf->user->dir_output.'/'.get_exdir(0, 0, 0, 0, $object, 'user').'/'.$object->id;
351 } elseif ($modulepart == 'adherent' || $modulepart == 'member') {
352 require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
353
354 if (!DolibarrApiAccess::$user->rights->adherent->lire) {
355 throw new RestException(401);
356 }
357
358 $object = new Adherent($this->db);
359 $result = $object->fetch($id, $ref);
360 if (!$result) {
361 throw new RestException(404, 'Member not found');
362 }
363
364 $upload_dir = $conf->adherent->dir_output."/".get_exdir(0, 0, 0, 1, $object, 'member');
365 } elseif ($modulepart == 'propal' || $modulepart == 'proposal') {
366 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
367
368 if (!DolibarrApiAccess::$user->hasRight('propal', 'lire')) {
369 throw new RestException(401);
370 }
371
372 $object = new Propal($this->db);
373 $result = $object->fetch($id, $ref);
374 if (!$result) {
375 throw new RestException(404, 'Proposal not found');
376 }
377
378 $upload_dir = $conf->propal->multidir_output[$object->entity]."/".get_exdir(0, 0, 0, 1, $object, 'propal');
379 } elseif ($modulepart == 'supplier_proposal') {
380 require_once DOL_DOCUMENT_ROOT.'/supplier_proposal/class/supplier_proposal.class.php';
381
382 if (!DolibarrApiAccess::$user->rights->supplier_proposal->read) {
383 throw new RestException(401);
384 }
385
386 $object = new Propal($this->db);
387 $result = $object->fetch($id, $ref);
388 if (!$result) {
389 throw new RestException(404, 'Supplier proposal not found');
390 }
391
392 $upload_dir = $conf->propal->multidir_output[$object->entity]."/".get_exdir(0, 0, 0, 1, $object, 'propal');
393 } elseif ($modulepart == 'commande' || $modulepart == 'order') {
394 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
395
396 if (!DolibarrApiAccess::$user->hasRight('commande', 'lire')) {
397 throw new RestException(401);
398 }
399
400 $object = new Commande($this->db);
401 $result = $object->fetch($id, $ref);
402 if (!$result) {
403 throw new RestException(404, 'Order not found');
404 }
405
406 $upload_dir = $conf->commande->dir_output."/".get_exdir(0, 0, 0, 1, $object, 'commande');
407 } elseif ($modulepart == 'commande_fournisseur' || $modulepart == 'supplier_order') {
408 $modulepart = 'supplier_order';
409
410 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
411
412 if (empty(DolibarrApiAccess::$user->rights->fournisseur->commande->lire) && empty(DolibarrApiAccess::$user->rights->supplier_order->lire)) {
413 throw new RestException(401);
414 }
415
416 $object = new CommandeFournisseur($this->db);
417 $result = $object->fetch($id, $ref);
418 if (!$result) {
419 throw new RestException(404, 'Purchase order not found');
420 }
421
422 $upload_dir = $conf->fournisseur->dir_output."/commande/".dol_sanitizeFileName($object->ref);
423 } elseif ($modulepart == 'shipment' || $modulepart == 'expedition') {
424 require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
425
426 if (!DolibarrApiAccess::$user->rights->expedition->lire) {
427 throw new RestException(401);
428 }
429
430 $object = new Expedition($this->db);
431 $result = $object->fetch($id, $ref);
432 if (!$result) {
433 throw new RestException(404, 'Shipment not found');
434 }
435
436 $upload_dir = $conf->expedition->dir_output."/sending/".get_exdir(0, 0, 0, 1, $object, 'shipment');
437 } elseif ($modulepart == 'facture' || $modulepart == 'invoice') {
438 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
439
440 if (!DolibarrApiAccess::$user->hasRight('facture', 'lire')) {
441 throw new RestException(401);
442 }
443
444 $object = new Facture($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->facture->dir_output."/".get_exdir(0, 0, 0, 1, $object, 'invoice');
451 } elseif ($modulepart == 'facture_fournisseur' || $modulepart == 'supplier_invoice') {
452 $modulepart = 'supplier_invoice';
453
454 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
455
456 if (empty(DolibarrApiAccess::$user->rights->fournisseur->facture->lire) && empty(DolibarrApiAccess::$user->rights->supplier_invoice->lire)) {
457 throw new RestException(401);
458 }
459
460 $object = new FactureFournisseur($this->db);
461 $result = $object->fetch($id, $ref);
462 if (!$result) {
463 throw new RestException(404, 'Invoice not found');
464 }
465
466 $upload_dir = $conf->fournisseur->dir_output."/facture/".get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier').dol_sanitizeFileName($object->ref);
467 } elseif ($modulepart == 'produit' || $modulepart == 'product') {
468 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
469
470 if (!DolibarrApiAccess::$user->rights->produit->lire) {
471 throw new RestException(401);
472 }
473
474 $object = new Product($this->db);
475 $result = $object->fetch($id, $ref);
476 if ($result == 0) {
477 throw new RestException(404, 'Product not found');
478 } elseif ($result < 0) {
479 throw new RestException(500, 'Error while fetching object: '.$object->error);
480 }
481
482 $upload_dir = $conf->product->multidir_output[$object->entity].'/'.get_exdir(0, 0, 0, 1, $object, 'product');
483 } elseif ($modulepart == 'agenda' || $modulepart == 'action' || $modulepart == 'event') {
484 require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
485
486 if (!DolibarrApiAccess::$user->rights->agenda->myactions->read && !DolibarrApiAccess::$user->rights->agenda->allactions->read) {
487 throw new RestException(401);
488 }
489
490 $object = new ActionComm($this->db);
491 $result = $object->fetch($id, $ref);
492 if (!$result) {
493 throw new RestException(404, 'Event not found');
494 }
495
496 $upload_dir = $conf->agenda->dir_output.'/'.dol_sanitizeFileName($object->ref);
497 } elseif ($modulepart == 'expensereport') {
498 require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
499
500 if (!DolibarrApiAccess::$user->rights->expensereport->read && !DolibarrApiAccess::$user->rights->expensereport->read) {
501 throw new RestException(401);
502 }
503
504 $object = new ExpenseReport($this->db);
505 $result = $object->fetch($id, $ref);
506 if (!$result) {
507 throw new RestException(404, 'Expense report not found');
508 }
509
510 $upload_dir = $conf->expensereport->dir_output.'/'.dol_sanitizeFileName($object->ref);
511 } elseif ($modulepart == 'knowledgemanagement') {
512 require_once DOL_DOCUMENT_ROOT.'/knowledgemanagement/class/knowledgerecord.class.php';
513
514 if (!DolibarrApiAccess::$user->hasRight('knowledgemanagement', 'knowledgerecord', 'read') && !DolibarrApiAccess::$user->hasRight('knowledgemanagement', 'knowledgerecord', 'read')) {
515 throw new RestException(401);
516 }
517
518 $object = new KnowledgeRecord($this->db);
519 $result = $object->fetch($id, $ref);
520 if (!$result) {
521 throw new RestException(404, 'KM article not found');
522 }
523
524 $upload_dir = $conf->knowledgemanagement->dir_output.'/knowledgerecord/'.dol_sanitizeFileName($object->ref);
525 } elseif ($modulepart == 'categorie' || $modulepart == 'category') {
526 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
527
528 if (!DolibarrApiAccess::$user->rights->categorie->lire) {
529 throw new RestException(401);
530 }
531
532 $object = new Categorie($this->db);
533 $result = $object->fetch($id, $ref);
534 if (!$result) {
535 throw new RestException(404, 'Category not found');
536 }
537
538 $upload_dir = $conf->categorie->multidir_output[$object->entity].'/'.get_exdir($object->id, 2, 0, 0, $object, 'category').$object->id."/photos/".dol_sanitizeFileName($object->ref);
539 } elseif ($modulepart == 'ecm') {
540 throw new RestException(500, 'Modulepart Ecm not implemented yet.');
541 // require_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmdirectory.class.php';
542
543 // if (!DolibarrApiAccess::$user->rights->ecm->read) {
544 // throw new RestException(401);
545 // }
546
547 // // $object = new EcmDirectory($this->db);
548 // // $result = $object->fetch($ref);
549 // // if (!$result) {
550 // // throw new RestException(404, 'EcmDirectory not found');
551 // // }
552 // $upload_dir = $conf->ecm->dir_output;
553 // $type = 'all';
554 // $recursive = 0;
555 } elseif ($modulepart == 'contrat' || $modulepart == 'contract') {
556 $modulepart = 'contrat';
557 require_once DOL_DOCUMENT_ROOT . '/contrat/class/contrat.class.php';
558
559 $object = new Contrat($this->db);
560 $result = $object->fetch($id, $ref);
561 if (!$result) {
562 throw new RestException(404, 'Contract not found');
563 }
564
565 $upload_dir = $conf->contrat->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'contract');
566 } elseif ($modulepart == 'projet' || $modulepart == 'project') {
567 $modulepart = 'project';
568 require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
569
570 $object = new Project($this->db);
571 $result = $object->fetch($id, $ref);
572 if (!$result) {
573 throw new RestException(404, 'Project not found');
574 }
575
576 $upload_dir = $conf->projet->dir_output . "/" . get_exdir(0, 0, 0, 1, $object, 'project');
577 } else {
578 throw new RestException(500, 'Modulepart '.$modulepart.' not implemented yet.');
579 }
580
581 $objectType = $modulepart;
582 if (! empty($object->id) && ! empty($object->table_element)) {
583 $objectType = $object->table_element;
584 }
585
586 $filearray = dol_dir_list($upload_dir, $type, $recursive, '', '(\.meta|_preview.*\.png)$', $sortfield, (strtolower($sortorder) == 'desc' ? SORT_DESC : SORT_ASC), 1);
587 if (empty($filearray)) {
588 throw new RestException(404, 'Search for modulepart '.$modulepart.' with Id '.$object->id.(!empty($object->ref) ? ' or Ref '.$object->ref : '').' does not return any document.');
589 } else {
590 if (($object->id) > 0 && !empty($modulepart)) {
591 require_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
592 $ecmfile = new EcmFiles($this->db);
593 $result = $ecmfile->fetchAll('', '', 0, 0, array('t.src_object_type' => $objectType, 't.src_object_id' => $object->id));
594 if ($result < 0) {
595 throw new RestException(503, 'Error when retrieve ecm list : '.$this->db->lasterror());
596 } elseif (is_array($ecmfile->lines) && count($ecmfile->lines) > 0) {
597 $count = count($filearray);
598 for ($i = 0 ; $i < $count ; $i++) {
599 foreach ($ecmfile->lines as $line) {
600 if ($filearray[$i]['name'] == $line->filename) {
601 $filearray[$i] = array_merge($filearray[$i], (array) $line);
602 }
603 }
604 }
605 }
606 }
607 }
608
609 return $filearray;
610 }
611
612
621 /*
622 public function get($id) {
623 return array('note'=>'xxx');
624 }*/
625
626
653 public function post($filename, $modulepart, $ref = '', $subdir = '', $filecontent = '', $fileencoding = '', $overwriteifexists = 0, $createdirifnotexists = 1)
654 {
655 global $conf;
656
657 //var_dump($modulepart);
658 //var_dump($filename);
659 //var_dump($filecontent);exit;
660
661 $modulepartorig = $modulepart;
662
663 if (empty($modulepart)) {
664 throw new RestException(400, 'Modulepart not provided.');
665 }
666
667 $newfilecontent = '';
668 if (empty($fileencoding)) {
669 $newfilecontent = $filecontent;
670 }
671 if ($fileencoding == 'base64') {
672 $newfilecontent = base64_decode($filecontent);
673 }
674
675 $original_file = dol_sanitizeFileName($filename);
676
677 // Define $uploadir
678 $object = null;
679 $entity = DolibarrApiAccess::$user->entity;
680 if (empty($entity)) {
681 $entity = 1;
682 }
683
684 if ($ref) {
685 $tmpreldir = '';
686 $fetchbyid = false;
687
688 if ($modulepart == 'facture' || $modulepart == 'invoice') {
689 $modulepart = 'facture';
690
691 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
692 $object = new Facture($this->db);
693 } elseif ($modulepart == 'facture_fournisseur' || $modulepart == 'supplier_invoice') {
694 $modulepart = 'supplier_invoice';
695
696 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
697 $object = new FactureFournisseur($this->db);
698 } elseif ($modulepart == 'commande' || $modulepart == 'order') {
699 $modulepart = 'commande';
700
701 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
702 $object = new Commande($this->db);
703 } elseif ($modulepart == 'commande_fournisseur' || $modulepart == 'supplier_order') {
704 $modulepart = 'supplier_order';
705
706 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
707 $object = new CommandeFournisseur($this->db);
708 } elseif ($modulepart == 'projet' || $modulepart == 'project') {
709 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
710 $object = new Project($this->db);
711 } elseif ($modulepart == 'task' || $modulepart == 'project_task') {
712 $modulepart = 'project_task';
713
714 require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
715 $object = new Task($this->db);
716
717 $task_result = $object->fetch('', $ref);
718
719 // Fetching the tasks project is required because its out_dir might be a sub-directory of the project
720 if ($task_result > 0) {
721 $project_result = $object->fetch_projet();
722
723 if ($project_result >= 0) {
724 $tmpreldir = dol_sanitizeFileName($object->project->ref).'/';
725 }
726 } else {
727 throw new RestException(500, 'Error while fetching Task '.$ref);
728 }
729 } elseif ($modulepart == 'product' || $modulepart == 'produit' || $modulepart == 'service' || $modulepart == 'produit|service') {
730 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
731 $object = new Product($this->db);
732 } elseif ($modulepart == 'expensereport') {
733 require_once DOL_DOCUMENT_ROOT.'/expensereport/class/expensereport.class.php';
734 $object = new ExpenseReport($this->db);
735 } elseif ($modulepart == 'fichinter') {
736 require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
737 $object = new Fichinter($this->db);
738 } elseif ($modulepart == 'adherent' || $modulepart == 'member') {
739 $modulepart = 'adherent';
740 require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
741 $object = new Adherent($this->db);
742 } elseif ($modulepart == 'proposal' || $modulepart == 'propal' || $modulepart == 'propale') {
743 $modulepart = 'propale';
744 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
745 $object = new Propal($this->db);
746 } elseif ($modulepart == 'agenda' || $modulepart == 'action' || $modulepart == 'event') {
747 $modulepart = 'agenda';
748 require_once DOL_DOCUMENT_ROOT . '/comm/action/class/actioncomm.class.php';
749 $object = new ActionComm($this->db);
750 } elseif ($modulepart == 'contact' || $modulepart == 'socpeople') {
751 $modulepart = 'contact';
752 require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
753 $object = new Contact($this->db);
754 $fetchbyid = true;
755 } elseif ($modulepart == 'contrat' || $modulepart == 'contract') {
756 $modulepart = 'contrat';
757 require_once DOL_DOCUMENT_ROOT . '/contrat/class/contrat.class.php';
758 $object = new Contrat($this->db);
759 } else {
760 // TODO Implement additional moduleparts
761 throw new RestException(500, 'Modulepart '.$modulepart.' not implemented yet.');
762 }
763
764 if (is_object($object)) {
765 if ($fetchbyid) {
766 $result = $object->fetch($ref);
767 } else {
768 $result = $object->fetch('', $ref);
769 }
770
771 if ($result == 0) {
772 throw new RestException(404, "Object with ref '".$ref."' was not found.");
773 } elseif ($result < 0) {
774 throw new RestException(500, 'Error while fetching object: '.$object->error);
775 }
776 }
777
778 if (!($object->id > 0)) {
779 throw new RestException(404, 'The object '.$modulepart." with ref '".$ref."' was not found.");
780 }
781
782 // Special cases that need to use get_exdir to get real dir of object
783 // In future, all object should use this to define path of documents.
784 if ($modulepart == 'supplier_invoice') {
785 $tmpreldir = get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier');
786 }
787
788 // Test on permissions
789 if ($modulepart != 'ecm') {
790 $relativefile = $tmpreldir.dol_sanitizeFileName($object->ref);
791 $tmp = dol_check_secure_access_document($modulepart, $relativefile, $entity, DolibarrApiAccess::$user, $ref, 'write');
792 $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
793 } else {
794 if (!DolibarrApiAccess::$user->hasRight('ecm', 'upload')) {
795 throw new RestException(401, 'Missing permission to upload files in ECM module');
796 }
797 $upload_dir = $conf->medias->multidir_output[$conf->entity];
798 }
799
800 if (empty($upload_dir) || $upload_dir == '/') {
801 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.');
802 }
803 } else {
804 if ($modulepart == 'invoice') {
805 $modulepart = 'facture';
806 }
807 if ($modulepart == 'member') {
808 $modulepart = 'adherent';
809 }
810
811 // Test on permissions
812 if ($modulepart != 'ecm') {
813 $relativefile = $subdir;
814 $tmp = dol_check_secure_access_document($modulepart, $relativefile, $entity, DolibarrApiAccess::$user, '', 'write');
815 $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
816 } else {
817 if (!DolibarrApiAccess::$user->hasRight('ecm', 'upload')) {
818 throw new RestException(401, 'Missing permission to upload files in ECM module');
819 }
820 $upload_dir = $conf->medias->multidir_output[$conf->entity];
821 }
822
823 if (empty($upload_dir) || $upload_dir == '/') {
824 if (!empty($tmp['error'])) {
825 throw new RestException(401, 'Error returned by dol_check_secure_access_document: '.$tmp['error']);
826 } else {
827 throw new RestException(500, 'This value of modulepart ('.$modulepart.') is not allowed with this value of subdir ('.$relativefile.')');
828 }
829 }
830 }
831 // $original_file here is still value of filename without any dir.
832
833 $upload_dir = dol_sanitizePathName($upload_dir);
834
835 if (!empty($createdirifnotexists)) {
836 if (dol_mkdir($upload_dir) < 0) { // needed by products
837 throw new RestException(500, 'Error while trying to create directory '.$upload_dir);
838 }
839 }
840
841 $destfile = $upload_dir.'/'.$original_file;
842 $destfiletmp = DOL_DATA_ROOT.'/admin/temp/'.$original_file;
843 dol_delete_file($destfiletmp);
844 //var_dump($original_file);exit;
845
846 if (!dol_is_dir(dirname($destfile))) {
847 throw new RestException(401, 'Directory not exists : '.dirname($destfile));
848 }
849
850 if (!$overwriteifexists && dol_is_file($destfile)) {
851 throw new RestException(500, "File with name '".$original_file."' already exists.");
852 }
853
854 // in case temporary directory admin/temp doesn't exist
855 if (!dol_is_dir(dirname($destfiletmp))) {
856 dol_mkdir(dirname($destfiletmp));
857 }
858
859 $fhandle = @fopen($destfiletmp, 'w');
860 if ($fhandle) {
861 $nbofbyteswrote = fwrite($fhandle, $newfilecontent);
862 fclose($fhandle);
863 dolChmod($destfiletmp);
864 } else {
865 throw new RestException(500, "Failed to open file '".$destfiletmp."' for write");
866 }
867
868 $disablevirusscan = 0;
869 $src_file = $destfiletmp;
870 $dest_file = $destfile;
871
872 // Security:
873 // If we need to make a virus scan
874 if (empty($disablevirusscan) && file_exists($src_file)) {
875 $checkvirusarray = dolCheckVirus($src_file);
876 if (count($checkvirusarray)) {
877 dol_syslog('Files.lib::dol_move_uploaded_file File "'.$src_file.'" (target name "'.$dest_file.'") KO with antivirus: errors='.join(',', $checkvirusarray), LOG_WARNING);
878 throw new RestException(500, 'ErrorFileIsInfectedWithAVirus: '.join(',', $checkvirusarray));
879 }
880 }
881
882 // Security:
883 // Disallow file with some extensions. We rename them.
884 // Because if we put the documents directory into a directory inside web root (very bad), this allows to execute on demand arbitrary code.
885 if (isAFileWithExecutableContent($dest_file) && !getDolGlobalString('MAIN_DOCUMENT_IS_OUTSIDE_WEBROOT_SO_NOEXE_NOT_REQUIRED')) {
886 // $upload_dir ends with a slash, so be must be sure the medias dir to compare to ends with slash too.
887 $publicmediasdirwithslash = $conf->medias->multidir_output[$conf->entity];
888 if (!preg_match('/\/$/', $publicmediasdirwithslash)) {
889 $publicmediasdirwithslash .= '/';
890 }
891
892 if (strpos($upload_dir, $publicmediasdirwithslash) !== 0 || !getDolGlobalInt("MAIN_DOCUMENT_DISABLE_NOEXE_IN_MEDIAS_DIR")) { // We never add .noexe on files into media directory
893 $dest_file .= '.noexe';
894 }
895 }
896
897 // Security:
898 // We refuse cache files/dirs, upload using .. and pipes into filenames.
899 if (preg_match('/^\./', basename($src_file)) || preg_match('/\.\./', $src_file) || preg_match('/[<>|]/', $src_file)) {
900 dol_syslog("Refused to deliver file ".$src_file, LOG_WARNING);
901 throw new RestException(500, "Refused to deliver file ".$src_file);
902 }
903
904 // Security:
905 // We refuse cache files/dirs, upload using .. and pipes into filenames.
906 if (preg_match('/^\./', basename($dest_file)) || preg_match('/\.\./', $dest_file) || preg_match('/[<>|]/', $dest_file)) {
907 dol_syslog("Refused to deliver file ".$dest_file, LOG_WARNING);
908 throw new RestException(500, "Refused to deliver file ".$dest_file);
909 }
910
911 $moreinfo = array('note_private' => 'File uploaded using API /documents from IP '.getUserRemoteIP());
912 if (!empty($object) && is_object($object) && $object->id > 0) {
913 $moreinfo['src_object_type'] = $object->table_element;
914 $moreinfo['src_object_id'] = $object->id;
915 }
916
917 // Move the temporary file at its final emplacement
918 $result = dol_move($destfiletmp, $dest_file, 0, $overwriteifexists, 1, 1, $moreinfo);
919 if (!$result) {
920 throw new RestException(500, "Failed to move file into '".$dest_file."'");
921 }
922
923 return dol_basename($destfile);
924 }
925
939 public function delete($modulepart, $original_file)
940 {
941 global $conf, $langs;
942
943 if (empty($modulepart)) {
944 throw new RestException(400, 'bad value for parameter modulepart');
945 }
946 if (empty($original_file)) {
947 throw new RestException(400, 'bad value for parameter original_file');
948 }
949
950 //--- Finds and returns the document
951 $entity = $conf->entity;
952
953 // Special cases that need to use get_exdir to get real dir of object
954 // If future, all object should use this to define path of documents.
955 /*
956 $tmpreldir = '';
957 if ($modulepart == 'supplier_invoice') {
958 $tmpreldir = get_exdir($object->id, 2, 0, 0, $object, 'invoice_supplier');
959 }
960
961 $relativefile = $tmpreldir.dol_sanitizeFileName($object->ref); */
962 $relativefile = $original_file;
963
964 $check_access = dol_check_secure_access_document($modulepart, $relativefile, $entity, DolibarrApiAccess::$user, '', 'read');
965 $accessallowed = $check_access['accessallowed'];
966 $sqlprotectagainstexternals = $check_access['sqlprotectagainstexternals'];
967 $original_file = $check_access['original_file'];
968
969 if (preg_match('/\.\./', $original_file) || preg_match('/[<>|]/', $original_file)) {
970 throw new RestException(401);
971 }
972 if (!$accessallowed) {
973 throw new RestException(401);
974 }
975
976 $filename = basename($original_file);
977 $original_file_osencoded = dol_osencode($original_file); // New file name encoded in OS encoding charset
978
979 if (!file_exists($original_file_osencoded)) {
980 dol_syslog("Try to download not found file ".$original_file_osencoded, LOG_WARNING);
981 throw new RestException(404, 'File not found');
982 }
983
984 if (@unlink($original_file_osencoded)) {
985 return array(
986 'success' => array(
987 'code' => 200,
988 'message' => 'Document deleted'
989 )
990 );
991 }
992
993 throw new RestException(401);
994 }
995
996 // phpcs:disable PEAR.NamingConventions.ValidFunctionName
1004 private function _validate_file($data)
1005 {
1006 // phpcs:enable
1007 $result = array();
1008 foreach (Documents::$DOCUMENT_FIELDS as $field) {
1009 if (!isset($data[$field])) {
1010 throw new RestException(400, "$field field missing");
1011 }
1012 $result[$field] = $data[$field];
1013 }
1014 return $result;
1015 }
1016}
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 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 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)
Contact()
Old copy.
Definition index.php:572