mirror of
https://github.com/Dolibarr/dolibarr.git
synced 2025-12-05 09:08:09 +01:00
NEW: Add Shared links on links in attachements (#33459)
* NEW: add share option for URL link in attachement * NEW: fix #33456 * NEW: shared link on links * NEW: shared link on links --------- Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
This commit is contained in:
@@ -217,6 +217,14 @@ if ($action == 'confirm_deletefile' && $confirm == 'yes' && !empty($permissionto
|
||||
$link->url = 'http://'.$link->url;
|
||||
}
|
||||
$link->label = GETPOST('label', 'alphanohtml');
|
||||
|
||||
$shareenabled = GETPOST('shareenabled', 'alpha');
|
||||
if ($shareenabled) {
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
|
||||
$link->share = getRandomPassword(true);
|
||||
} else {
|
||||
$link->share = '';
|
||||
}
|
||||
$res = $link->update($user);
|
||||
if (!$res) {
|
||||
setEventMessages($langs->trans("ErrorFailedToUpdateLink", $link->label), null, 'mesgs');
|
||||
|
||||
@@ -2222,7 +2222,7 @@ class FormFile
|
||||
$sortfield = '';
|
||||
}
|
||||
$res = $link->fetchAll($links, $object->element, $object->id, $sortfield, $sortorder);
|
||||
$param .= (isset($object->id) ? '&id='.$object->id : '');
|
||||
$param .= (isset($object->id) && !preg_match('/&id='.$object->id.'/i', $param) ? '&id='.$object->id : '');
|
||||
|
||||
$permissiontoedit = $permissiontodelete;
|
||||
|
||||
@@ -2289,6 +2289,7 @@ class FormFile
|
||||
'',
|
||||
'center '
|
||||
);
|
||||
// Shared or not - Hash of file
|
||||
print_liste_field_titre('', '', '');
|
||||
print '</tr>';
|
||||
$nboflinks = count($links);
|
||||
@@ -2298,7 +2299,7 @@ class FormFile
|
||||
foreach ($links as $link) {
|
||||
print '<tr class="oddeven">';
|
||||
//edit mode
|
||||
if ($action == 'update' && $selected === (int) $link->id && $permissiontoedit) {
|
||||
if ($action == 'update' && (int) $selected === (int) $link->id && $permissiontoedit) {
|
||||
print '<td>';
|
||||
print '<input type="hidden" name="id" value="'.$object->id.'">';
|
||||
print '<input type="hidden" name="linkid" value="'.$link->id.'">';
|
||||
@@ -2309,7 +2310,10 @@ class FormFile
|
||||
print $langs->trans('Label').': <input type="text" name="label" value="'.dol_escape_htmltag($link->label).'">';
|
||||
print '</td>';
|
||||
print '<td class="center">'.dol_print_date(dol_now(), "dayhour", "tzuser").'</td>';
|
||||
print '<td class="right"></td>';
|
||||
print '<td class="right">';
|
||||
print '<label for="idshareenabled'.$key.'">'.$langs->trans("LinkSharedViaALink").'</label> ';
|
||||
print '<input class="inline-block" type="checkbox" id="idshareenabled'.$key.'" name="shareenabled"'.($link->share ? ' checked="checked"' : '').' /> ';
|
||||
print '</td>';
|
||||
print '<td class="right">';
|
||||
print '<input type="submit" class="button button-save" name="save" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
|
||||
print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
|
||||
@@ -2323,7 +2327,17 @@ class FormFile
|
||||
print '</td>'."\n";
|
||||
print '<td class="right"></td>';
|
||||
print '<td class="center">'.dol_print_date($link->datea, "dayhour", "tzuser").'</td>';
|
||||
print '<td class="center"></td>';
|
||||
print '<td class="center">';
|
||||
if ($link->share) {
|
||||
global $dolibarr_main_url_root;
|
||||
$urlwithouturlroot = preg_replace('/' . preg_quote(DOL_URL_ROOT, '/') . '$/i', '', trim($dolibarr_main_url_root));
|
||||
$urlwithroot = $urlwithouturlroot . DOL_URL_ROOT; // This is to use external domain name found into config file
|
||||
$fulllink = $urlwithroot.'/document.php?type=link&hashp=' . $link->share;
|
||||
|
||||
print '<a href="'.$fulllink.'" target="_blank" rel="noopener">'.img_picto($langs->trans("FileSharedViaALink"), 'globe').'</a> ';
|
||||
print '<input type="text" class="centpercentminusx minwidth200imp nopadding small" id="downloadlink'.$link->id.'" name="downloadexternallink" title="'.dol_escape_htmltag($langs->trans("LinkSharedViaALink")).'" value="'.dol_escape_htmltag($fulllink).'">';
|
||||
}
|
||||
print '</td>';
|
||||
print '<td class="right">';
|
||||
print '<a href="'.$_SERVER['PHP_SELF'].'?action=update&linkid='.$link->id.$param.'&token='.newToken().'" class="editfilelink editfielda reposition" >'.img_edit().'</a>'; // id= is included into $param
|
||||
if ($permissiontodelete) {
|
||||
|
||||
@@ -70,6 +70,15 @@ class Link extends CommonObject
|
||||
*/
|
||||
public $objectid;
|
||||
|
||||
/**
|
||||
* @var string share hash
|
||||
*/
|
||||
public $share;
|
||||
|
||||
/**
|
||||
* @var string share pass hash
|
||||
*/
|
||||
public $share_pass;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
@@ -113,12 +122,14 @@ class Link extends CommonObject
|
||||
|
||||
$this->db->begin();
|
||||
|
||||
$sql = "INSERT INTO ".$this->db->prefix()."links (entity, datea, url, label, objecttype, objectid)";
|
||||
$sql = "INSERT INTO ".$this->db->prefix()."links (entity, datea, url, label, objecttype, objectid, share,share_pass)";
|
||||
$sql .= " VALUES (".$conf->entity.", '".$this->db->idate($this->datea)."'";
|
||||
$sql .= ", '".$this->db->escape($this->url)."'";
|
||||
$sql .= ", '".$this->db->escape($this->label)."'";
|
||||
$sql .= ", '".$this->db->escape($this->objecttype)."'";
|
||||
$sql .= ", ".((int) $this->objectid).")";
|
||||
$sql .= ", ".((int) $this->objectid);
|
||||
$sql .= ', '.(!empty($this->share) ? "'".$this->db->escape($this->share)."'" : "null");
|
||||
$sql .= ', '.(!empty($this->share_pass) ? "'".$this->db->escape($this->share_pass)."'" : "null").")";
|
||||
|
||||
dol_syslog(get_class($this)."::create", LOG_DEBUG);
|
||||
$result = $this->db->query($sql);
|
||||
@@ -198,6 +209,8 @@ class Link extends CommonObject
|
||||
$sql .= ", label = '".$this->db->escape($this->label)."'";
|
||||
$sql .= ", objecttype = '".$this->db->escape($this->objecttype)."'";
|
||||
$sql .= ", objectid = ".$this->objectid;
|
||||
$sql .= ', share = '.(!empty($this->share) ? "'".$this->db->escape($this->share)."'" : "null");
|
||||
$sql .= ', share_pass = '.(!empty($this->share_pass) ? "'".$this->db->escape($this->share_pass)."'" : "null");
|
||||
$sql .= " WHERE rowid = ".((int) $this->id);
|
||||
|
||||
dol_syslog(get_class($this)."::update sql = ".$sql);
|
||||
@@ -249,7 +262,7 @@ class Link extends CommonObject
|
||||
{
|
||||
global $conf;
|
||||
|
||||
$sql = "SELECT rowid, entity, datea, url, label, objecttype, objectid FROM ".$this->db->prefix()."links";
|
||||
$sql = "SELECT rowid, entity, datea, url, label, objecttype, objectid, share,share_pass FROM ".$this->db->prefix()."links";
|
||||
$sql .= " WHERE objecttype = '".$this->db->escape($objecttype)."' AND objectid = ".((int) $objectid);
|
||||
if ($conf->entity != 0) {
|
||||
$sql .= " AND entity = ".((int) $conf->entity);
|
||||
@@ -276,6 +289,8 @@ class Link extends CommonObject
|
||||
$link->label = $obj->label;
|
||||
$link->objecttype = $obj->objecttype;
|
||||
$link->objectid = $obj->objectid;
|
||||
$link->share = $obj->share;
|
||||
$link->share_pass = $obj->share_pass;
|
||||
$links[] = $link;
|
||||
}
|
||||
return 1;
|
||||
@@ -319,9 +334,10 @@ class Link extends CommonObject
|
||||
* Loads a link from database
|
||||
*
|
||||
* @param int $rowid Id of link to load
|
||||
* @param string $hashforshare Hash of file sharing, or 'shared'
|
||||
* @return int 1 if ok, 0 if no record found, -1 if error
|
||||
**/
|
||||
public function fetch($rowid = null)
|
||||
public function fetch($rowid = null, $hashforshare = '')
|
||||
{
|
||||
global $conf;
|
||||
|
||||
@@ -329,10 +345,21 @@ class Link extends CommonObject
|
||||
$rowid = $this->id;
|
||||
}
|
||||
|
||||
$sql = "SELECT rowid, entity, datea, url, label, objecttype, objectid FROM ".$this->db->prefix()."links";
|
||||
$sql .= " WHERE rowid = ".((int) $rowid);
|
||||
$sqlwhere=[];
|
||||
|
||||
$sql = "SELECT rowid, entity, datea, url, label, objecttype, objectid, share, share_pass FROM ".$this->db->prefix()."links";
|
||||
if (!empty((int) $rowid)) {
|
||||
$sqlwhere[] = " rowid = ".((int) $rowid);
|
||||
}
|
||||
if (!empty($hashforshare)) {
|
||||
$sqlwhere[] = " share = '".$this->db->escape($hashforshare)."'";
|
||||
}
|
||||
|
||||
if ($conf->entity != 0) {
|
||||
$sql .= " AND entity = ".$conf->entity;
|
||||
$sqlwhere[] = " entity = ".$conf->entity;
|
||||
}
|
||||
if (count($sqlwhere)>0) {
|
||||
$sql .=' WHERE '.implode(' AND ', $sqlwhere);
|
||||
}
|
||||
|
||||
dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
|
||||
@@ -348,6 +375,8 @@ class Link extends CommonObject
|
||||
$this->label = $obj->label;
|
||||
$this->objecttype = $obj->objecttype;
|
||||
$this->objectid = $obj->objectid;
|
||||
$this->share = $obj->share;
|
||||
$this->share_pass = $obj->share_pass;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
|
||||
@@ -177,43 +177,58 @@ if (in_array($modulepart, array('facture_paiement', 'unpaid'))) {
|
||||
// If we have a hash public (hashp), we guess the original_file.
|
||||
$ecmfile = '';
|
||||
if (!empty($hashp)) {
|
||||
include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
|
||||
$ecmfile = new EcmFiles($db);
|
||||
$result = $ecmfile->fetch(0, '', '', '', $hashp);
|
||||
if ($result > 0) {
|
||||
$tmp = explode('/', $ecmfile->filepath, 2); // $ecmfile->filepath is relative to document directory
|
||||
// filepath can be 'users/X' or 'X/propale/PR11111'
|
||||
if (is_numeric($tmp[0])) { // If first tmp is numeric, it is subdir of company for multicompany, we take next part.
|
||||
$tmp = explode('/', $tmp[1], 2);
|
||||
}
|
||||
$moduleparttocheck = $tmp[0]; // moduleparttocheck is first part of path
|
||||
|
||||
if ($modulepart) { // Not required, so often not defined, for link using public hashp parameter.
|
||||
if ($moduleparttocheck == $modulepart) {
|
||||
// We remove first level of directory
|
||||
$original_file = (($tmp[1] ? $tmp[1].'/' : '').$ecmfile->filename); // this is relative to module dir
|
||||
//var_dump($original_file); exit;
|
||||
} else {
|
||||
httponly_accessforbidden('Bad link. File is from another module part.', 403);
|
||||
}
|
||||
if (GETPOST('type', 'alpha')=='link') {
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
|
||||
$link = new Link($db);
|
||||
$result = $link->fetch(0, $hashp);
|
||||
if ($result > 0 && !empty($link->url)) {
|
||||
header('Location: '.$link->url);
|
||||
exit;
|
||||
} else {
|
||||
$modulepart = $moduleparttocheck;
|
||||
$original_file = (($tmp[1] ? $tmp[1].'/' : '').$ecmfile->filename); // this is relative to module dir
|
||||
}
|
||||
$entity = $ecmfile->entity;
|
||||
if (isModEnabled('multicompany') && !empty($ecmfile->src_object_type) && $ecmfile->src_object_id > 0) {
|
||||
$object = fetchObjectByElement($ecmfile->src_object_id, $ecmfile->src_object_type);
|
||||
if (is_object($object) && $object->id > 0) {
|
||||
$entity = $object->entity;
|
||||
}
|
||||
}
|
||||
if ($entity != $conf->entity) {
|
||||
$conf->entity = $entity;
|
||||
$conf->setValues($db);
|
||||
$langs->load("errors");
|
||||
httponly_accessforbidden($langs->trans("ErrorLinkNotFoundWithSharedLink"), 403, 1);
|
||||
}
|
||||
} else {
|
||||
$langs->load("errors");
|
||||
httponly_accessforbidden($langs->trans("ErrorFileNotFoundWithSharedLink"), 403, 1);
|
||||
include_once DOL_DOCUMENT_ROOT . '/ecm/class/ecmfiles.class.php';
|
||||
$ecmfile = new EcmFiles($db);
|
||||
$result = $ecmfile->fetch(0, '', '', '', $hashp);
|
||||
if ($result > 0) {
|
||||
$tmp = explode('/', $ecmfile->filepath, 2); // $ecmfile->filepath is relative to document directory
|
||||
// filepath can be 'users/X' or 'X/propale/PR11111'
|
||||
if (is_numeric($tmp[0])) { // If first tmp is numeric, it is subdir of company for multicompany, we take next part.
|
||||
$tmp = explode('/', $tmp[1], 2);
|
||||
}
|
||||
$moduleparttocheck = $tmp[0]; // moduleparttocheck is first part of path
|
||||
|
||||
if ($modulepart) { // Not required, so often not defined, for link using public hashp parameter.
|
||||
if ($moduleparttocheck == $modulepart) {
|
||||
// We remove first level of directory
|
||||
$original_file = (($tmp[1] ? $tmp[1] . '/' : '') . $ecmfile->filename); // this is relative to module dir
|
||||
//var_dump($original_file); exit;
|
||||
} else {
|
||||
httponly_accessforbidden('Bad link. File is from another module part.', 403);
|
||||
}
|
||||
} else {
|
||||
$modulepart = $moduleparttocheck;
|
||||
$original_file = (($tmp[1] ? $tmp[1] . '/' : '') . $ecmfile->filename); // this is relative to module dir
|
||||
}
|
||||
|
||||
$entity = $ecmfile->entity;
|
||||
if (isModEnabled('multicompany') && !empty($ecmfile->src_object_type) && $ecmfile->src_object_id > 0) {
|
||||
$object = fetchObjectByElement($ecmfile->src_object_id, $ecmfile->src_object_type);
|
||||
if (is_object($object) && $object->id > 0) {
|
||||
$entity = $object->entity;
|
||||
}
|
||||
}
|
||||
|
||||
if ($entity != $conf->entity) {
|
||||
$conf->entity = $entity;
|
||||
$conf->setValues($db);
|
||||
}
|
||||
} else {
|
||||
$langs->load("errors");
|
||||
httponly_accessforbidden($langs->trans("ErrorFileNotFoundWithSharedLink"), 403, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user