1<?php
2/* Copyright (C) 2008-2020 Laurent Destailleur  <eldy@users.sourceforge.net>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18/**
19 *	\file      	htdocs/ecm/file_card.php
20 *	\ingroup   	ecm
21 *	\brief     	Card of a file for ECM module
22 */
23
24require '../main.inc.php';
25require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
26require_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmdirectory.class.php';
27require_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
28require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
29require_once DOL_DOCUMENT_ROOT.'/core/lib/ecm.lib.php';
30require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
31
32// Load translation files required by page
33$langs->loadLangs(array('ecm', 'companies', 'other', 'users', 'orders', 'propal', 'bills', 'contracts', 'categories'));
34
35$action = GETPOST('action', 'aZ09');
36$cancel = GETPOST('cancel', 'alpha');
37$backtopage = GETPOST('backtopage', 'alpha');
38
39// Get parameters
40$socid = GETPOST("socid", "int");
41
42// Security check
43if ($user->socid > 0) {
44	$action = '';
45	$socid = $user->socid;
46}
47
48$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit;
49$sortfield = GETPOST("sortfield", 'alpha');
50$sortorder = GETPOST("sortorder", 'alpha');
51$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
52if (empty($page) || $page == -1) {
53	$page = 0;
54}     // If $page is not defined, or '' or -1
55$offset = $limit * $page;
56$pageprev = $page - 1;
57$pagenext = $page + 1;
58if (!$sortorder) {
59	$sortorder = "ASC";
60}
61if (!$sortfield) {
62	$sortfield = "label";
63}
64
65$section = GETPOST("section", 'alpha');
66if (!$section) {
67	dol_print_error('', 'Error, section parameter missing');
68	exit;
69}
70$urlfile = (string) dol_sanitizePathName(GETPOST("urlfile"), '_', 0);
71if (!$urlfile) {
72	dol_print_error('', "ErrorParamNotDefined");
73	exit;
74}
75
76// Load ecm object
77$ecmdir = new EcmDirectory($db);
78$result = $ecmdir->fetch(GETPOST("section", 'alpha'));
79if (!$result > 0) {
80	dol_print_error($db, $ecmdir->error);
81	exit;
82}
83$relativepath = $ecmdir->getRelativePath();
84$upload_dir = $conf->ecm->dir_output.'/'.$relativepath;
85
86$fullpath = $conf->ecm->dir_output.'/'.$relativepath.$urlfile;
87
88$relativetodocument = 'ecm/'.$relativepath; // $relativepath is relative to ECM dir, we need relative to document
89$filepath = $relativepath.$urlfile;
90$filepathtodocument = $relativetodocument.$urlfile;
91
92// Try to load object from index
93$object = new ECMFiles($db);
94$extrafields = new ExtraFields($db);
95// fetch optionals attributes and labels
96$extrafields->fetch_name_optionals_label($object->table_element);
97
98$result = $object->fetch(0, '', $filepathtodocument);
99if ($result < 0) {
100	dol_print_error($db, $object->error, $object->errors);
101	exit;
102}
103
104// Permissions
105$permtoread = $user->rights->ecm->read;
106$permtoadd = $user->rights->ecm->setup;
107$permtoupload = $user->rights->ecm->upload;
108
109if (!$permtoread) {
110	accessforbidden();
111}
112
113
114/*
115 * Actions
116 */
117
118if ($cancel) {
119	$action = '';
120	if ($backtopage) {
121		header("Location: ".$backtopage);
122		exit;
123	} else {
124		header('Location: '.$_SERVER["PHP_SELF"].'?urlfile='.urlencode($urlfile).'&section='.urlencode($section).($module ? '&module='.urlencode($module) : ''));
125		exit;
126	}
127}
128
129// Rename file
130if ($action == 'update' && $permtoadd) {
131	$error = 0;
132
133	$oldlabel = GETPOST('urlfile', 'alpha');
134	$newlabel = dol_sanitizeFileName(GETPOST('label', 'alpha'), '_', 0);
135	$shareenabled = GETPOST('shareenabled', 'alpha');
136
137	//$db->begin();
138
139	$olddir = $ecmdir->getRelativePath(0); // Relative to ecm
140	$olddirrelativetodocument = 'ecm/'.$olddir; // Relative to document
141	$newdirrelativetodocument = 'ecm/'.$olddir;
142	$olddir = $conf->ecm->dir_output.'/'.$olddir;
143	$newdir = $olddir;
144
145	$oldfile = $olddir.$oldlabel;
146	$newfile = $newdir.$newlabel;
147	$newfileformove = $newfile;
148	// If old file end with .noexe, new file must also end with .noexe
149	if (preg_match('/\.noexe$/', $oldfile) && !preg_match('/\.noexe$/', $newfileformove)) {
150		$newfileformove .= '.noexe';
151	}
152	//var_dump($oldfile);var_dump($newfile);exit;
153
154	// Now we update index of file
155	$db->begin();
156	//print $oldfile.' - '.$newfile;
157	if ($newlabel != $oldlabel) {
158		$result = dol_move($oldfile, $newfileformove); // This include update of database
159		if (!$result) {
160			$langs->load('errors');
161			setEventMessages($langs->trans('ErrorFailToRenameFile', $oldfile, $newfile), null, 'errors');
162			$error++;
163		}
164
165		// Reload object after the move
166		$result = $object->fetch(0, '', $newdirrelativetodocument.$newlabel);
167		if ($result < 0) {
168			dol_print_error($db, $object->error, $object->errors);
169			exit;
170		}
171	}
172
173	if (!$error) {
174		if ($shareenabled) {
175			require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
176			$object->share = getRandomPassword(true);
177		} else {
178			$object->share = '';
179		}
180
181		if ($object->id > 0) {
182			$ret = $extrafields->setOptionalsFromPost(null, $object);
183			if ($ret < 0) {
184				$error++;
185			}
186			if (!$error) {
187				// Actions on extra fields
188				$result = $object->insertExtraFields();
189				if ($result < 0) {
190					setEventMessages($object->error, $object->errors, 'errors');
191					$error++;
192				}
193			}
194			// Call update to set the share key
195			$result = $object->update($user);
196			if ($result < 0) {
197				setEventMessages($object->error, $object->errors, 'warnings');
198			}
199		} else {
200			// Call create to insert record
201			$object->entity = $conf->entity;
202			$object->filepath = preg_replace('/[\\/]+$/', '', $newdirrelativetodocument);
203			$object->filename = $newlabel;
204			$object->label = md5_file(dol_osencode($newfileformove)); // hash of file content
205			$object->fullpath_orig = '';
206			$object->gen_or_uploaded = 'unknown';
207			$object->description = ''; // indexed content
208			$object->keywords = ''; // keyword content
209			$result = $object->create($user);
210			if ($result < 0) {
211				setEventMessages($object->error, $object->errors, 'warnings');
212			}
213		}
214	}
215
216	if (!$error) {
217		$db->commit();
218
219		$urlfile = $newlabel;
220		// If old file end with .noexe, new file must also end with .noexe
221		if (preg_match('/\.noexe$/', $newfileformove)) {
222			$urlfile .= '.noexe';
223		}
224
225		header('Location: '.$_SERVER["PHP_SELF"].'?urlfile='.urlencode($urlfile).'&section='.urlencode($section));
226		exit;
227	} else {
228		$db->rollback();
229	}
230}
231
232
233
234/*
235 * View
236 */
237
238$form = new Form($db);
239
240llxHeader();
241
242$object->section_id = $ecmdir->id;
243$object->label = $urlfile;
244$head = ecm_file_prepare_head($object);
245
246if ($action == 'edit') {
247	print '<form name="update" action="'.$_SERVER["PHP_SELF"].'" method="POST">';
248	print '<input type="hidden" name="token" value="'.newToken().'">';
249	print '<input type="hidden" name="section" value="'.$section.'">';
250	print '<input type="hidden" name="urlfile" value="'.$urlfile.'">';
251	print '<input type="hidden" name="module" value="'.$module.'">';
252	print '<input type="hidden" name="action" value="update">';
253	print '<input type="hidden" name="id" value="'.$object->id.'">';
254}
255
256print dol_get_fiche_head($head, 'card', $langs->trans("File"), -1, 'generic');
257
258
259$s = '';
260$tmpecmdir = new EcmDirectory($db); // Need to create a new one
261$tmpecmdir->fetch($ecmdir->id);
262$result = 1;
263$i = 0;
264while ($tmpecmdir && $result > 0) {
265	$tmpecmdir->ref = $tmpecmdir->label;
266	$s = $tmpecmdir->getNomUrl(1).$s;
267	if ($tmpecmdir->fk_parent) {
268		$s = ' -> '.$s;
269		$result = $tmpecmdir->fetch($tmpecmdir->fk_parent);
270	} else {
271		$tmpecmdir = 0;
272	}
273	$i++;
274}
275
276$urlfiletoshow = preg_replace('/\.noexe$/', '', $urlfile);
277
278$s = img_picto('', 'object_dir').' <a href="'.DOL_URL_ROOT.'/ecm/index.php">'.$langs->trans("ECMRoot").'</a> -> '.$s.' -> ';
279if ($action == 'edit') {
280	$s .= '<input type="text" name="label" class="quatrevingtpercent" value="'.$urlfiletoshow.'">';
281} else {
282	$s .= $urlfiletoshow;
283}
284
285$linkback = '';
286if ($backtopage) {
287	$linkback = '<a href="'.$backtopage.'">'.$langs->trans("BackToTree").'</a>';
288}
289
290$object->ref = ''; // Force to hide ref
291dol_banner_tab($object, '', $linkback, 0, '', '', $s);
292
293print '<div class="fichecenter">';
294
295print '<div class="underbanner clearboth"></div>';
296print '<table class="border centpercent tableforfield">';
297print '<tr><td class="titlefieldcreate">'.$langs->trans("ECMCreationDate").'</td><td>';
298print dol_print_date(dol_filemtime($fullpath), 'dayhour');
299print '</td></tr>';
300/*print '<tr><td>'.$langs->trans("ECMDirectoryForFiles").'</td><td>';
301print '/ecm/'.$relativepath;
302print '</td></tr>';
303print '<tr><td>'.$langs->trans("ECMNbOfDocs").'</td><td>';
304print count($filearray);
305print '</td></tr>';
306print '<tr><td>'.$langs->trans("TotalSizeOfAttachedFiles").'</td><td>';
307print dol_print_size($totalsize);
308print '</td></tr>';
309*/
310
311// Hash of file content
312print '<tr><td>'.$langs->trans("HashOfFileContent").'</td><td>';
313$object = new EcmFiles($db);
314$object->fetch(0, '', $filepathtodocument);
315if (!empty($object->label)) {
316	print $object->label;
317} else {
318	print img_warning().' '.$langs->trans("FileNotYetIndexedInDatabase");
319}
320print '</td></tr>';
321
322// Define $urlwithroot
323$urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
324$urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
325//$urlwithroot=DOL_MAIN_URL_ROOT;					// This is to use same domain name than current
326
327// Link for internal download
328print '<tr><td>';
329print $form->textwithpicto($langs->trans("DirectDownloadInternalLink"), $langs->trans("PrivateDownloadLinkDesc"));
330print '</td><td>';
331$modulepart = 'ecm';
332$forcedownload = 1;
333$rellink = '/document.php?modulepart='.$modulepart;
334if ($forcedownload) {
335	$rellink .= '&attachment=1';
336}
337if (!empty($object->entity)) {
338	$rellink .= '&entity='.$object->entity;
339}
340$rellink .= '&file='.urlencode($filepath);
341$fulllink = $urlwithroot.$rellink;
342print img_picto('', 'globe').' ';
343if ($action != 'edit') {
344	print '<input type="text" class="quatrevingtpercent" id="downloadinternallink" name="downloadinternellink" value="'.dol_escape_htmltag($fulllink).'">';
345} else {
346	print $fulllink;
347}
348if ($action != 'edit') {
349	print ' <a href="'.$fulllink.'">'.$langs->trans("Download").'</a>'; // No target here.
350}
351print '</td></tr>';
352
353// Link for direct external download
354print '<tr><td>';
355if ($action != 'edit') {
356	print $form->textwithpicto($langs->trans("DirectDownloadLink"), $langs->trans("PublicDownloadLinkDesc"));
357} else {
358	print $form->textwithpicto($langs->trans("FileSharedViaALink"), $langs->trans("PublicDownloadLinkDesc"));
359}
360print '</td><td>';
361if (!empty($object->share)) {
362	if ($action != 'edit') {
363		$forcedownload = 0;
364
365		$paramlink = '';
366		if (!empty($object->share)) {
367			$paramlink .= ($paramlink ? '&' : '').'hashp='.$object->share; // Hash for public share
368		}
369		if ($forcedownload) {
370			$paramlink .= ($paramlink ? '&' : '').'attachment=1';
371		}
372
373		$fulllink = $urlwithroot.'/document.php'.($paramlink ? '?'.$paramlink : '');
374		//if (! empty($object->ref))       $fulllink.='&hashn='.$object->ref;		// Hash of file path
375		//elseif (! empty($object->label)) $fulllink.='&hashc='.$object->label;		// Hash of file content
376
377		print img_picto('', 'globe').' ';
378		if ($action != 'edit') {
379			print '<input type="text" class="quatrevingtpercent" id="downloadlink" name="downloadexternallink" value="'.dol_escape_htmltag($fulllink).'">';
380		} else {
381			print $fulllink;
382		}
383		if ($action != 'edit') {
384			print ' <a href="'.$fulllink.'">'.$langs->trans("Download").'</a>'; // No target here
385		}
386	} else {
387		print '<input type="checkbox" name="shareenabled"'.($object->share ? ' checked="checked"' : '').' /> ';
388	}
389} else {
390	if ($action != 'edit') {
391		print '<span class="opacitymedium">'.$langs->trans("FileNotShared").'</span>';
392	} else {
393		print '<input type="checkbox" name="shareenabled"'.($object->share ? ' checked="checked"' : '').' /> ';
394	}
395}
396print '</td>';
397print '</tr>';
398print $object->showOptionals($extrafields, ($action == 'edit' ? 'edit' : 'view'));
399print '</table>';
400print '</div>';
401
402print ajax_autoselect('downloadinternallink');
403print ajax_autoselect('downloadlink');
404
405print dol_get_fiche_end();
406
407if ($action == 'edit') {
408	print '<div class="center">';
409	print '<input type="submit" class="button button-save" name="submit" value="'.$langs->trans("Save").'">';
410	print ' &nbsp; &nbsp; ';
411	print '<input type="submit" class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
412	print '</div>';
413
414	print '</form>';
415}
416
417
418// Confirmation de la suppression d'une ligne categorie
419if ($action == 'delete_file') {
420	print $form->formconfirm($_SERVER["PHP_SELF"].'?section='.urlencode($section), $langs->trans('DeleteFile'), $langs->trans('ConfirmDeleteFile', $urlfile), 'confirm_deletefile', '', 1, 1);
421}
422
423if ($action != 'edit') {
424	// Actions buttons
425	print '<div class="tabsAction">';
426
427	if ($user->rights->ecm->setup) {
428		print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?action=edit&section='.urlencode($section).'&urlfile='.urlencode($urlfile).'">'.$langs->trans('Edit').'</a>';
429	}
430	/*
431	if ($user->rights->ecm->setup)
432	{
433		print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?action=delete_file&token='.newToken().'&section='.$section.'&urlfile='.urlencode($urlfile).'">'.$langs->trans('Delete').'</a>';
434	}
435	else
436	{
437		print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("NotAllowed").'">'.$langs->trans('Delete').'</a>';
438	}
439	*/
440	print '</div>';
441}
442
443
444// End of page
445llxFooter();
446$db->close();
447