PageRenderTime 601ms CodeModel.GetById 101ms app.highlight 369ms RepoModel.GetById 78ms app.codeStats 1ms

/htdocs/document.php

https://github.com/asterix14/dolibarr
PHP | 550 lines | 374 code | 70 blank | 106 comment | 203 complexity | 5d666758b2317438cd95b33c9c078611 MD5 | raw file
  1<?php
  2/* Copyright (C) 2004-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3 * Copyright (C) 2004-2010 Laurent Destailleur  <eldy@users.sourceforge.net>
  4 * Copyright (C) 2005      Simon Tosser         <simon@kornog-computing.com>
  5 * Copyright (C) 2005-2011 Regis Houssin        <regis@dolibarr.fr>
  6 * Copyright (C) 2010	   Pierre Morin         <pierre.morin@auguria.net>
  7 * Copyright (C) 2010	   Juanjo Menent        <jmenent@2byte.es>
  8 *
  9 * This program is free software; you can redistribute it and/or modify
 10 * it under the terms of the GNU General Public License as published by
 11 * the Free Software Foundation; either version 2 of the License, or
 12 * (at your option) any later version.
 13 *
 14 * This program is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 17 * GNU General Public License for more details.
 18 *
 19 * You should have received a copy of the GNU General Public License
 20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 21 * or see http://www.gnu.org/
 22 */
 23
 24/**
 25 *	\file       htdocs/document.php
 26 *  \brief      Wrapper to download data files
 27 *  \remarks    Call of this wrapper is made with URL:
 28 * 				document.php?modulepart=repfichierconcerne&file=pathrelatifdufichier
 29 */
 30
 31define('NOTOKENRENEWAL',1); // Disables token renewal
 32// Pour autre que bittorrent, on charge environnement + info issus de logon (comme le user)
 33if (isset($_GET["modulepart"]) && $_GET["modulepart"] == 'bittorrent' && ! defined("NOLOGIN"))
 34{
 35	define("NOLOGIN",1);
 36	define("NOCSRFCHECK",1);	// We accept to go on this page from external web site.
 37}
 38if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1');
 39if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1');
 40if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1');
 41
 42/**
 43 * Wrapper, donc header vierge
 44 *
 45 * @return  null
 46 */
 47function llxHeader() { }
 48
 49require("./main.inc.php");	// Load $user and permissions
 50require_once(DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php');
 51
 52$encoding = '';
 53$action = GETPOST("action");
 54$original_file = GETPOST("file");	// Do not use urldecode here ($_GET are already decoded by PHP).
 55$modulepart = GETPOST("modulepart");
 56$urlsource = GETPOST("urlsource");
 57
 58// Security check
 59if (empty($modulepart)) accessforbidden('Bad value for parameter modulepart');
 60
 61
 62/*
 63 * Action
 64 */
 65
 66// None
 67
 68
 69/*
 70 * View
 71 */
 72
 73// Define mime type
 74$type = 'application/octet-stream';
 75if (GETPOST('type')) $type=GETPOST('type');
 76else $type=dol_mimetype($original_file);
 77//print 'X'.$type.'-'.$original_file;exit;
 78
 79// Define attachment (attachment=true to force choice popup 'open'/'save as')
 80$attachment = true;
 81// Text files
 82if (preg_match('/\.txt$/i',$original_file))  	{ $attachment = false; }
 83if (preg_match('/\.csv$/i',$original_file))  	{ $attachment = true; }
 84if (preg_match('/\.tsv$/i',$original_file))  	{ $attachment = true; }
 85// Documents MS office
 86if (preg_match('/\.doc(x)?$/i',$original_file)) { $attachment = true; }
 87if (preg_match('/\.dot(x)?$/i',$original_file)) { $attachment = true; }
 88if (preg_match('/\.mdb$/i',$original_file))     { $attachment = true; }
 89if (preg_match('/\.ppt(x)?$/i',$original_file)) { $attachment = true; }
 90if (preg_match('/\.xls(x)?$/i',$original_file)) { $attachment = true; }
 91// Documents Open office
 92if (preg_match('/\.odp$/i',$original_file))     { $attachment = true; }
 93if (preg_match('/\.ods$/i',$original_file))     { $attachment = true; }
 94if (preg_match('/\.odt$/i',$original_file))     { $attachment = true; }
 95// Misc
 96if (preg_match('/\.(html|htm)$/i',$original_file)) 	{ $attachment = false; }
 97if (preg_match('/\.pdf$/i',$original_file))  	{ $attachment = true; }
 98if (preg_match('/\.sql$/i',$original_file))     { $attachment = true; }
 99// Images
100if (preg_match('/\.jpg$/i',$original_file)) 	{ $attachment = true; }
101if (preg_match('/\.jpeg$/i',$original_file)) 	{ $attachment = true; }
102if (preg_match('/\.png$/i',$original_file)) 	{ $attachment = true; }
103if (preg_match('/\.gif$/i',$original_file)) 	{ $attachment = true; }
104if (preg_match('/\.bmp$/i',$original_file)) 	{ $attachment = true; }
105if (preg_match('/\.tiff$/i',$original_file)) 	{ $attachment = true; }
106// Calendar
107if (preg_match('/\.vcs$/i',$original_file))  	{ $attachment = true; }
108if (preg_match('/\.ics$/i',$original_file))  	{ $attachment = true; }
109if (GETPOST("attachment"))                      { $attachment = true; }
110if (! empty($conf->global->MAIN_DISABLE_FORCE_SAVEAS)) $attachment=false;
111//print "XX".$attachment;exit;
112
113// Suppression de la chaine de caractere ../ dans $original_file
114$original_file = str_replace("../","/", $original_file);
115
116// find the subdirectory name as the reference
117$refname=basename(dirname($original_file)."/");
118
119// Security check
120$accessallowed=0;
121$sqlprotectagainstexternals='';
122if ($modulepart)
123{
124	// On fait une verification des droits et on definit le repertoire concerne
125
126	// Wrapping for third parties
127	if ($modulepart == 'company')
128	{
129		if ($user->rights->societe->lire || preg_match('/^specimen/i',$original_file))
130		{
131			$accessallowed=1;
132		}
133		$original_file=$conf->societe->dir_output.'/'.$original_file;
134		$sqlprotectagainstexternals = "SELECT rowid as fk_soc FROM ".MAIN_DB_PREFIX."societe WHERE rowid='".$refname."' AND entity=".$conf->entity;
135	}
136
137	// Wrapping for invoices
138	else if ($modulepart == 'facture')
139	{
140		if ($user->rights->facture->lire || preg_match('/^specimen/i',$original_file))
141		{
142			$accessallowed=1;
143		}
144		$original_file=$conf->facture->dir_output.'/'.$original_file;
145		$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."facture WHERE ref='".$refname."' AND entity=".$conf->entity;
146	}
147
148	else if ($modulepart == 'unpaid')
149	{
150		if ($user->rights->facture->lire || preg_match('/^specimen/i',$original_file))
151		{
152			$accessallowed=1;
153		}
154		$original_file=$conf->facture->dir_output.'/unpaid/temp/'.$original_file;
155	}
156
157	// Wrapping pour les fiches intervention
158	else if ($modulepart == 'ficheinter')
159	{
160		if ($user->rights->ficheinter->lire || preg_match('/^specimen/i',$original_file))
161		{
162			$accessallowed=1;
163		}
164		$original_file=$conf->ficheinter->dir_output.'/'.$original_file;
165		$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."fichinter WHERE ref='".$refname."' AND entity=".$conf->entity;
166	}
167
168	// Wrapping pour les prelevements
169	else if ($modulepart == 'prelevement')
170	{
171		if ($user->rights->prelevement->bons->lire || preg_match('/^specimen/i',$original_file))
172		{
173			$accessallowed=1;
174		}
175		$original_file=$conf->prelevement->dir_output.'/'.$original_file;
176	}
177
178	// Wrapping pour les propales
179	else if ($modulepart == 'propal')
180	{
181		if ($user->rights->propale->lire || preg_match('/^specimen/i',$original_file))
182		{
183			$accessallowed=1;
184		}
185
186		$original_file=$conf->propale->dir_output.'/'.$original_file;
187		$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."propal WHERE ref='".$refname."' AND entity=".$conf->entity;
188	}
189
190	// Wrapping pour les commandes
191	else if ($modulepart == 'commande')
192	{
193		if ($user->rights->commande->lire || preg_match('/^specimen/i',$original_file))
194		{
195			$accessallowed=1;
196		}
197		$original_file=$conf->commande->dir_output.'/'.$original_file;
198		$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."commande WHERE ref='".$refname."' AND entity=".$conf->entity;
199	}
200
201	// Wrapping pour les projets
202	else if ($modulepart == 'project')
203	{
204		if ($user->rights->projet->lire || preg_match('/^specimen/i',$original_file))
205		{
206			$accessallowed=1;
207		}
208		$original_file=$conf->projet->dir_output.'/'.$original_file;
209		$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."projet WHERE ref='".$refname."' AND entity=".$conf->entity;
210	}
211
212	// Wrapping pour les commandes fournisseurs
213	else if ($modulepart == 'commande_fournisseur')
214	{
215		if ($user->rights->fournisseur->commande->lire || preg_match('/^specimen/i',$original_file))
216		{
217			$accessallowed=1;
218		}
219		$original_file=$conf->fournisseur->commande->dir_output.'/'.$original_file;
220		$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."commande_fournisseur WHERE ref='".$refname."' AND entity=".$conf->entity;
221	}
222
223	// Wrapping pour les factures fournisseurs
224	else if ($modulepart == 'facture_fournisseur' || $modulepart == 'invoice_supplier')
225	{
226		if ($user->rights->fournisseur->facture->lire || preg_match('/^specimen/i',$original_file))
227		{
228			$accessallowed=1;
229		}
230		$original_file=$conf->fournisseur->facture->dir_output.'/'.$original_file;
231		$sqlprotectagainstexternals = "SELECT fk_soc as fk_soc FROM ".MAIN_DB_PREFIX."facture_fourn WHERE facnumber='".$refname."' AND entity=".$conf->entity;
232	}
233
234	// Wrapping pour les rapport de paiements
235	else if ($modulepart == 'facture_paiement')
236	{
237		if ($user->rights->facture->lire || preg_match('/^specimen/i',$original_file))
238		{
239			$accessallowed=1;
240		}
241		if ($user->societe_id > 0) $original_file=$conf->facture->dir_output.'/payments/private/'.$user->id.'/'.$original_file;
242		else $original_file=$conf->facture->dir_output.'/payments/'.$original_file;
243	}
244
245	// Wrapping pour les exports de compta
246	else if ($modulepart == 'export_compta')
247	{
248		if ($user->rights->compta->ventilation->creer || preg_match('/^specimen/i',$original_file))
249		{
250			$accessallowed=1;
251		}
252		$original_file=$conf->compta->dir_output.'/'.$original_file;
253	}
254
255	// Wrapping pour les societe
256	else if ($modulepart == 'societe')
257	{
258		if ($user->rights->societe->lire || preg_match('/^specimen/i',$original_file))
259		{
260			$accessallowed=1;
261		}
262		$original_file=$conf->societe->dir_output.'/'.$original_file;
263		$sqlprotectagainstexternals = "SELECT rowid as fk_soc FROM ".MAIN_DB_PREFIX."societe WHERE rowid='".$refname."' AND entity=".$conf->entity;
264	}
265
266	// Wrapping pour les expedition
267	else if ($modulepart == 'expedition')
268	{
269		if ($user->rights->expedition->lire || preg_match('/^specimen/i',$original_file))
270		{
271			$accessallowed=1;
272		}
273		$original_file=$conf->expedition->dir_output."/sending/".$original_file;
274	}
275
276	// Wrapping pour les bons de livraison
277	else if ($modulepart == 'livraison')
278	{
279		if ($user->rights->expedition->livraison->lire || preg_match('/^specimen/i',$original_file))
280		{
281			$accessallowed=1;
282		}
283		$original_file=$conf->expedition->dir_output."/receipt/".$original_file;
284	}
285
286	// Wrapping pour les actions
287	else if ($modulepart == 'actions')
288	{
289		if ($user->rights->agenda->myactions->read || preg_match('/^specimen/i',$original_file))
290		{
291		$accessallowed=1;
292		}
293		$original_file=$conf->agenda->dir_output.'/'.$original_file;
294	}
295
296	// Wrapping pour les actions
297	else if ($modulepart == 'actionsreport')
298	{
299		if ($user->rights->agenda->allactions->read || preg_match('/^specimen/i',$original_file))
300		{
301			$accessallowed=1;
302		}
303		$original_file = $conf->agenda->dir_temp."/".$original_file;
304	}
305
306	// Wrapping pour les produits et services
307	else if ($modulepart == 'produit' || $modulepart == 'service')
308	{
309		if (($user->rights->produit->lire || $user->rights->service->lire) || preg_match('/^specimen/i',$original_file))
310		{
311			$accessallowed=1;
312		}
313		if ($conf->product->enabled) $original_file=$conf->product->dir_output.'/'.$original_file;
314		elseif ($conf->service->enabled) $original_file=$conf->service->dir_output.'/'.$original_file;
315	}
316
317	// Wrapping pour les contrats
318	else if ($modulepart == 'contract')
319	{
320		if ($user->rights->contrat->lire || preg_match('/^specimen/i',$original_file))
321		{
322			$accessallowed=1;
323		}
324		$original_file=$conf->contrat->dir_output.'/'.$original_file;
325	}
326
327	// Wrapping pour les documents generaux
328	else if ($modulepart == 'ged')
329	{
330		if ($user->rights->document->lire)
331		{
332			$accessallowed=1;
333		}
334		$original_file= $conf->ged->dir_output.'/'.$original_file;
335	}
336
337	// Wrapping pour les dons
338	else if ($modulepart == 'donation')
339	{
340		if ($user->rights->don->lire || preg_match('/^specimen/i',$original_file))
341		{
342			$accessallowed=1;
343		}
344		$original_file=$conf->don->dir_output.'/'.$original_file;
345	}
346
347	// Wrapping pour les remises de cheques
348	else if ($modulepart == 'remisecheque')
349	{
350		if ($user->rights->banque->lire || preg_match('/^specimen/i',$original_file))
351		{
352			$accessallowed=1;
353		}
354
355		$original_file=$conf->banque->dir_output.'/bordereau/'.get_exdir(basename($original_file,".pdf"),2,1).$original_file;
356	}
357
358	// Wrapping for export module
359	else if ($modulepart == 'export')
360	{
361		// Aucun test necessaire car on force le rep de download sur
362		// le rep export qui est propre a l'utilisateur
363		$accessallowed=1;
364		$original_file=$conf->export->dir_temp.'/'.$user->id.'/'.$original_file;
365	}
366
367	// Wrapping for import module
368	else if ($modulepart == 'import')
369	{
370		// Aucun test necessaire car on force le rep de download sur
371		// le rep export qui est propre a l'utilisateur
372		$accessallowed=1;
373		$original_file=$conf->import->dir_temp.'/'.$original_file;
374	}
375
376	// Wrapping pour l'editeur wysiwyg
377	else if ($modulepart == 'editor')
378	{
379		// Aucun test necessaire car on force le rep de download sur
380		// le rep export qui est propre a l'utilisateur
381		$accessallowed=1;
382		$original_file=$conf->fckeditor->dir_output.'/'.$original_file;
383	}
384
385	// Wrapping pour les backups
386	else if ($modulepart == 'systemtools')
387	{
388		if ($user->admin)
389		{
390			$accessallowed=1;
391		}
392		$original_file=$conf->admin->dir_output.'/'.$original_file;
393	}
394
395	// Wrapping pour BitTorrent
396	else if ($modulepart == 'bittorrent')
397	{
398		$accessallowed=1;
399		$dir='files';
400		if ($type == 'application/x-bittorrent') $dir='torrents';
401		$original_file=$conf->bittorrent->dir_output.'/'.$dir.'/'.$original_file;
402	}
403
404    // Wrapping pour Foundation module
405    else if ($modulepart == 'member')
406    {
407        if ($user->rights->adherent->lire || preg_match('/^specimen/i',$original_file))
408        {
409            $accessallowed=1;
410        }
411        $original_file=$conf->adherent->dir_output.'/'.$original_file;
412    }
413
414    // Wrapping for Scanner
415    else if ($modulepart == 'scanner_user_temp')
416    {
417        $accessallowed=1;
418        $original_file=$conf->scanner->dir_temp.'/'.$user->id.'/'.$original_file;
419    }
420
421	// Generic wrapping
422	else
423	{
424		// Define $accessallowed
425		if (($user->rights->$modulepart->lire) || ($user->rights->$modulepart->read) || ($user->rights->$modulepart->download)) $accessallowed=1;	// No subpermission, we have checked on main permission
426		elseif (preg_match('/^specimen/i',$original_file))	$accessallowed=1;    // If link to a specimen
427 		elseif ($user->admin) $accessallowed=1;    // If user is admin
428
429 		// For modules who wants to manage different levels of permissions for documents
430	    $subPermCategoryConstName = strtoupper($modulepart).'_SUBPERMCATEGORY_FOR_DOCUMENTS';
431		if (! empty($conf->global->$subPermCategoryConstName))
432		{
433		    $subPermCategory = $conf->global->$subPermCategoryConstName;
434    		if (! empty($subPermCategory) && (($user->rights->$modulepart->$subPermCategory->lire) || ($user->rights->$modulepart->$subPermCategory->read) || ($user->rights->$modulepart->$subPermCategory->download)))
435    		{
436    		    $accessallowed=1;
437    		}
438		}
439
440 		// Define $original_file
441 		$original_file=$conf->$modulepart->dir_output.'/'.$original_file;
442
443 		// Define $sqlprotectagainstexternals for modules who want to protect access using a SQL query.
444 		$sqlProtectConstName = strtoupper($modulepart).'_SQLPROTECTAGAINSTEXTERNALS_FOR_DOCUMENTS';
445		if (! empty($conf->global->$sqlProtectConstName))	// If module want to define its own $sqlprotectagainstexternals
446		{
447			// Example: mymodule__SQLPROTECTAGAINSTEXTERNALS_FOR_DOCUMENTS = "SELECT fk_soc FROM ".MAIN_DB_PREFIX.$modulepart." WHERE ref='".$refname."' AND entity=".$conf->entity;
448			eval('$sqlprotectagainstexternals = "'.$conf->global->$sqlProtectConstName.'";');
449		}
450	}
451}
452
453// Basic protection (against external users only)
454if ($user->societe_id > 0)
455{
456	if ($sqlprotectagainstexternals)
457	{
458		$resql = $db->query($sqlprotectagainstexternals);
459		if ($resql)
460		{
461			$num=$db->num_rows($resql);
462			$i=0;
463			while ($i < $num)
464			{
465				$obj = $db->fetch_object($resql);
466				if ($user->societe_id != $obj->fk_soc)
467				{
468					$accessallowed=0;
469					break;
470				}
471				$i++;
472			}
473		}
474	}
475}
476
477// Security:
478// Limite acces si droits non corrects
479if (! $accessallowed)
480{
481	accessforbidden();
482}
483
484// Security:
485// On interdit les remontees de repertoire ainsi que les pipe dans
486// les noms de fichiers.
487if (preg_match('/\.\./',$original_file) || preg_match('/[<>|]/',$original_file))
488{
489	dol_syslog("Refused to deliver file ".$original_file);
490	$file=basename($original_file);		// Do no show plain path of original_file in shown error message
491	dol_print_error(0,$langs->trans("ErrorFileNameInvalid",$file));
492	exit;
493}
494
495
496if ($action == 'remove_file')	// Remove a file
497{
498	clearstatcache();
499
500	dol_syslog("document.php remove $original_file $urlsource", LOG_DEBUG);
501
502	// This test should be useless. We keep it to find bug more easily
503	$original_file_osencoded=dol_osencode($original_file);	// New file name encoded in OS encoding charset
504	if (! file_exists($original_file_osencoded))
505	{
506		$file=basename($original_file);		// Do no show plain path of original_file in shown error message
507		dol_print_error(0,$langs->trans("ErrorFileDoesNotExists",$file));
508		exit;
509	}
510
511	dol_delete_file($original_file);
512
513	dol_syslog("document.php back to ".urldecode($urlsource), LOG_DEBUG);
514
515	header("Location: ".urldecode($urlsource));
516
517	return;
518}
519else						// Open and return file
520{
521	clearstatcache();
522
523	$filename = basename($original_file);
524
525	// Output file on browser
526	dol_syslog("document.php download $original_file $filename content-type=$type");
527	$original_file_osencoded=dol_osencode($original_file);	// New file name encoded in OS encoding charset
528
529	// This test if file exists should be useless. We keep it to find bug more easily
530	if (! file_exists($original_file_osencoded))
531	{
532		dol_print_error(0,$langs->trans("ErrorFileDoesNotExists",$original_file));
533		exit;
534	}
535
536	// Les drois sont ok et fichier trouve, on l'envoie
537
538	if ($encoding)   header('Content-Encoding: '.$encoding);
539	if ($type)       header('Content-Type: '.$type.(preg_match('/text/',$type)?'; charset="'.$conf->file->character_set_client:''));
540	if ($attachment) header('Content-Disposition: attachment; filename="'.$filename.'"');
541	else header('Content-Disposition: inline; filename="'.$filename.'"');
542
543	// Ajout directives pour resoudre bug IE
544	header('Cache-Control: Public, must-revalidate');
545	header('Pragma: public');
546
547	readfile($original_file_osencoded);
548}
549
550?>