NEW Provide a way to download a file from a public URL for files in ECM

This commit is contained in:
Laurent Destailleur 2017-09-21 14:02:42 +02:00
parent 96efe43e3c
commit 57358f0ce5
8 changed files with 158 additions and 78 deletions

View File

@ -60,15 +60,14 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
$encoding = '';
$action=GETPOST('action','alpha');
$original_file=GETPOST('file','alpha'); // Do not use urldecode here ($_GET are already decoded by PHP).
$hashn=GETPOST('hashn','aZ09');
$hashc=GETPOST('hashc','aZ09');
$hashp=GETPOST('hashp','aZ09');
$modulepart=GETPOST('modulepart','alpha');
$urlsource=GETPOST('urlsource','alpha');
$entity=GETPOST('entity','int')?GETPOST('entity','int'):$conf->entity;
// Security check
if (empty($modulepart)) accessforbidden('Bad link. Bad value for parameter modulepart',0,0,1);
if (empty($original_file) && empty($hashn) && empty($hashc)) accessforbidden('Bad link. Missing identification to find file (original_file, hasn or hashc)',0,0,1);
if (empty($original_file) && empty($hashp)) accessforbidden('Bad link. Missing identification to find file (original_file or hashp)',0,0,1);
if ($modulepart == 'fckeditor') $modulepart='medias'; // For backward compatibility
$socid=0;
@ -103,12 +102,12 @@ if (preg_match('/\.(html|htm)$/i',$original_file)) $attachment = false;
if (isset($_GET["attachment"])) $attachment = GETPOST("attachment",'alpha')?true:false;
if (! empty($conf->global->MAIN_DISABLE_FORCE_SAVEAS)) $attachment=false;
// If we have a hash (hashc or hashn), we guess the original_file. Note: using hashn is not reliable.
if (! empty($hashn) || ! empty($hashc))
// If we have a hash public (hashp), we guess the original_file.
if (! empty($hashp))
{
include_once DOL_DOCUMENT_ROOT.'/ecm/class/ecmfiles.class.php';
$ecmfile=new EcmFiles($db);
$result = $ecmfile->fetch(0, $hashn, '', $hashc);
$result = $ecmfile->fetch(0, '', '', '', $hashp);
if ($result > 0)
{
$tmp = explode('/', $ecmfile->filepath, 2); // $ecmfile->filepatch is relative to document directory

View File

@ -46,7 +46,9 @@ class EcmFiles //extends CommonObject
/**
*/
public $label; // hash of file md5_file(dol_osencode($destfull)), so MD5 of file content
public $ref; // hash of file path
public $label; // hash of file content (md5_file(dol_osencode($destfull))
public $share; // hash for file sharing. empty by default
public $entity;
public $filename;
public $filepath;
@ -94,10 +96,15 @@ class EcmFiles //extends CommonObject
$error = 0;
// Clean parameters
if (isset($this->ref)) {
$this->ref = trim($this->ref);
}
if (isset($this->label)) {
$this->label = trim($this->label);
}
if (isset($this->share)) {
$this->share = trim($this->share);
}
if (isset($this->entity)) {
$this->entity = trim($this->entity);
}
@ -136,6 +143,10 @@ class EcmFiles //extends CommonObject
}
if (empty($this->date_c)) $this->date_c = dol_now();
// If ref not defined
if (empty($ref)) $ref = dol_hash($this->filepath.'/'.$this->filename, 3);
$maxposition=0;
if (empty($this->position)) // Get max used
{
@ -159,6 +170,7 @@ class EcmFiles //extends CommonObject
$sql = 'INSERT INTO ' . MAIN_DB_PREFIX . $this->table_element . '(';
$sql.= 'ref,';
$sql.= 'label,';
$sql.= 'share,';
$sql.= 'entity,';
$sql.= 'filename,';
$sql.= 'filepath,';
@ -175,8 +187,9 @@ class EcmFiles //extends CommonObject
$sql.= 'fk_user_m,';
$sql.= 'acl';
$sql .= ') VALUES (';
$sql .= " '".dol_hash($this->filepath.'/'.$this->filename, 3)."', ";
$sql .= " '".$ref."', ";
$sql .= ' '.(! isset($this->label)?'NULL':"'".$this->db->escape($this->label)."'").',';
$sql .= ' '.(! isset($this->share)?'NULL':"'".$this->db->escape($this->share)."'").',';
$sql .= ' '.(! isset($this->entity)?$conf->entity:$this->entity).',';
$sql .= ' '.(! isset($this->filename)?'NULL':"'".$this->db->escape($this->filename)."'").',';
$sql .= ' '.(! isset($this->filepath)?'NULL':"'".$this->db->escape($this->filepath)."'").',';
@ -237,9 +250,10 @@ class EcmFiles //extends CommonObject
* @param string $ref Hash of file name (filename+filepath). Not always defined on some version.
* @param string $relativepath Relative path of file from document directory. Example: path/path2/file
* @param string $hashoffile Hash of file content. Take the first one found if same file is at different places. This hash will also change if file content is changed.
* @param string $hashforshare Hash of file sharing.
* @return int <0 if KO, 0 if not found, >0 if OK
*/
public function fetch($id, $ref = '', $relativepath = '', $hashoffile='')
public function fetch($id, $ref = '', $relativepath = '', $hashoffile='', $hashforshare='')
{
dol_syslog(__METHOD__, LOG_DEBUG);
@ -247,6 +261,7 @@ class EcmFiles //extends CommonObject
$sql .= ' t.rowid,';
$sql .= " t.ref,";
$sql .= " t.label,";
$sql .= " t.share,";
$sql .= " t.entity,";
$sql .= " t.filename,";
$sql .= " t.filepath,";
@ -276,11 +291,15 @@ class EcmFiles //extends CommonObject
}
elseif (! empty($hashoffile)) {
$sql .= " AND t.label = '".$this->db->escape($hashoffile)."'";
}
elseif (! empty($hashforshare)) {
$sql .= " AND t.share = '".$this->db->escape($hashforshare)."'";
} else {
$sql .= ' AND t.rowid = ' . $id;
}
// When we search on hash of content, we take the first one. Solve also hash conflict.
$this->db->plimit(1);
$this->db->order('t.rowid', 'ASC'); // When we search on hash of content, we take the first one.
$this->db->order('t.rowid', 'ASC');
$resql = $this->db->query($sql);
if ($resql) {
@ -291,6 +310,7 @@ class EcmFiles //extends CommonObject
$this->id = $obj->rowid;
$this->ref = $obj->ref;
$this->label = $obj->label;
$this->share = $obj->share;
$this->entity = $obj->entity;
$this->filename = $obj->filename;
$this->filepath = $obj->filepath;
@ -352,6 +372,7 @@ class EcmFiles //extends CommonObject
$sql = 'SELECT';
$sql .= ' t.rowid,';
$sql .= " t.label,";
$sql .= " t.share,";
$sql .= " t.entity,";
$sql .= " t.filename,";
$sql .= " t.filepath,";
@ -401,8 +422,9 @@ class EcmFiles //extends CommonObject
$line = new EcmfilesLine();
$line->id = $obj->rowid;
$line->ref = $obj->ref;
$line->label = $obj->label;
$line->share = $obj->share;
$line->entity = $obj->entity;
$line->filename = $obj->filename;
$line->filepath = $obj->filepath;
@ -446,9 +468,15 @@ class EcmFiles //extends CommonObject
// Clean parameters
if (isset($this->ref)) {
$this->ref = trim($this->ref);
}
if (isset($this->label)) {
$this->label = trim($this->label);
}
if (isset($this->share)) {
$this->share = trim($this->share);
}
if (isset($this->entity)) {
$this->entity = trim($this->entity);
}
@ -492,8 +520,9 @@ class EcmFiles //extends CommonObject
// Update request
$sql = 'UPDATE ' . MAIN_DB_PREFIX . $this->table_element . ' SET';
$sql .= ' ref = '.dol_hash($this->filepath.'/'.$this->filename, 3);
$sql .= " ref = '".dol_hash($this->filepath.'/'.$this->filename, 3)."',";
$sql .= ' label = '.(isset($this->label)?"'".$this->db->escape($this->label)."'":"null").',';
$sql .= ' share = '.(! empty($this->share)?"'".$this->db->escape($this->share)."'":"null").',';
$sql .= ' entity = '.(isset($this->entity)?$this->entity:$conf->entity).',';
$sql .= ' filename = '.(isset($this->filename)?"'".$this->db->escape($this->filename)."'":"null").',';
$sql .= ' filepath = '.(isset($this->filepath)?"'".$this->db->escape($this->filepath)."'":"null").',';

View File

@ -39,6 +39,9 @@ $langs->load("bills");
$langs->load("contracts");
$langs->load("categories");
$action = GETPOST('action', 'aZ09');
$cancel = GETPOST('cancel', 'alpha');
if (!$user->rights->ecm->setup) accessforbidden();
// Get parameters
@ -61,8 +64,6 @@ $pagenext = $page + 1;
if (! $sortorder) $sortorder="ASC";
if (! $sortfield) $sortfield="label";
$cancel=GETPOST('cancel','alpha');
$action=GETPOST('action','aZ09');
$section=GETPOST("section");
if (! $section)
{
@ -87,19 +88,25 @@ if (! $result > 0)
$relativepath=$ecmdir->getRelativePath();
$upload_dir = $conf->ecm->dir_output.'/'.$relativepath;
$fullpath=$conf->ecm->dir_output.'/'.$relativepath.$urlfile;
/*
$ecmfile = new ECMFile($db);
if (! empty($_GET["fileid"]))
$file = new stdClass();
$file->section_id=$ecmdir->id;
$file->label=$urlfile;
$relativetodocument = 'ecm/'.$relativepath; // $relativepath is relative to ECM dir, we need relative to document
$filepath=$relativepath.$file->label;
$filepathtodocument=$relativetodocument.$file->label;
// Try to load object from index
$object = new ECMFiles($db);
$result=$object->fetch(0, '', $filepathtodocument);
if (! ($result >= 0))
{
$result=$ecmfile->fetch($_GET["fileid"]);
if (! $result > 0)
{
dol_print_error($db,$ecmfile->error);
exit;
}
dol_print_error($db, $object->error, $object->errors);
exit;
}
*/
@ -107,7 +114,7 @@ if (! empty($_GET["fileid"]))
* Actions
*/
if ($action == 'cancel')
if ($cancel)
{
$action ='';
if ($backtourl)
@ -117,7 +124,7 @@ if ($action == 'cancel')
}
else
{
header("Location: ".DOL_URL_ROOT.'/ecm/index.php?action=file_manager&section='.$section);
header("Location: ".DOL_URL_ROOT.'/ecm/docfile.php?urlfile='.$urlfile.'&section='.$section);
exit;
}
}
@ -127,8 +134,9 @@ if ($action == 'update')
{
$error=0;
$oldlabel=GETPOST('urlfile');
$newlabel=GETPOST('label');
$oldlabel=GETPOST('urlfile', 'alpha');
$newlabel=GETPOST('label', 'alpha');
$shareenabled = GETPOST('shareenabled', 'alpha');
//$db->begin();
@ -142,7 +150,7 @@ if ($action == 'update')
//print $oldfile.' - '.$newfile;
if ($newlabel != $oldlabel)
{
$result=dol_move($oldfile, $newfile);
$result=dol_move($oldfile, $newfile); // This include update of database
if (! $result)
{
$langs->load('errors');
@ -151,14 +159,39 @@ if ($action == 'update')
}
}
// Now we update index of file
$db->begin();
if (! $error)
{
//$db->commit();
if (is_object($object))
{
if ($shareenabled)
{
require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
$object->share = getRandomPassword(true);
}
else
{
$object->share = '';
}
$result = $object->update($user);
if ($result < 0)
{
$error++;
setEventMessages($object->error, $object->errors, 'errors');
}
}
}
if (!$error)
{
$db->commit();
$urlfile=$newlabel;
}
else
{
//$db->rollback();
$db->rollback();
}
}
@ -168,25 +201,20 @@ if ($action == 'update')
* View
*/
llxHeader();
$form=new Form($db);
$fullpath=$conf->ecm->dir_output.'/'.$relativepath.$urlfile;
$file = new stdClass();
$file->section_id=$ecmdir->id;
$file->label=$urlfile;
llxHeader();
$head = ecm_file_prepare_head($file);
if ($_GET["action"] == 'edit')
if ($action == 'edit')
{
print '<form name="update" action="'.$_SERVER["PHP_SELF"].'" method="POST">';
print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
print '<input type="hidden" name="section" value="'.$section.'">';
print '<input type="hidden" name="urlfile" value="'.$urlfile.'">';
print '<input type="hidden" name="action" value="update">';
print '<input type="hidden" name="id" value="'.$object->id.'">';
}
dol_fiche_head($head, 'card', $langs->trans("File"), 0, 'generic');
@ -217,11 +245,11 @@ while ($tmpecmdir && $result > 0)
print img_picto('','object_dir').' <a href="'.DOL_URL_ROOT.'/ecm/index.php">'.$langs->trans("ECMRoot").'</a> -> ';
print $s;
print ' -> ';
if (GETPOST('action','aZ09') == 'edit') print '<input type="text" name="label" class="quatrevingtpercent" value="'.$urlfile.'">';
if ($action == 'edit') print '<input type="text" name="label" class="quatrevingtpercent" value="'.$urlfile.'">';
else print $urlfile;
print '</td></tr>';
/*print '<tr><td class="tdtop">'.$langs->trans("Description").'</td><td>';
if ($_GET["action"] == 'edit')
if ($action == 'edit')
{
print '<textarea class="flat" name="description" cols="80">';
print $ecmdir->description;
@ -249,18 +277,14 @@ print dol_print_size($totalsize);
print '</td></tr>';
*/
$relativetodocument = 'ecm/'.$relativepath; // $relativepath is relative to ECM dir, we need relative to document
$filepath=$relativepath.$file->label;
$filepathtodocument=$relativetodocument.$file->label;
print '<tr><td>'.$langs->trans("HashSaved").'</td><td>';
$ecmfile = new EcmFiles($db);
print '<tr><td>'.$langs->trans("HashOfFileContent").'</td><td>';
$object = new EcmFiles($db);
//$filenametosearch=basename($filepath);
//$filedirtosearch=basedir($filepath);
$ecmfile->fetch(0, '', $filepathtodocument);
if (! empty($ecmfile->label))
$object->fetch(0, '', $filepathtodocument);
if (! empty($object->label))
{
print $ecmfile->label;
print $object->label;
}
else
{
@ -282,29 +306,49 @@ if (! empty($object->entity)) $rellink.='&entity='.$object->entity;
$rellink.='&file='.urlencode($filepath);
$fulllink=$urlwithroot.$rellink;
print img_picto('','object_globe.png').' ';
print '<input type="text" class="quatrevingtpercent" id="downloadinternallink" name="downloadinternellink" value="'.dol_escape_htmltag($fulllink).'">';
print ' <a href="'.$fulllink.'">'.$langs->trans("Download").'</a>';
if ($action != 'edit') print '<input type="text" class="quatrevingtpercent" id="downloadinternallink" name="downloadinternellink" value="'.dol_escape_htmltag($fulllink).'">';
else print $fulllink;
if ($action != 'edit') print ' <a href="'.$fulllink.'">'.$langs->trans("Download").'</a>';
print '</td></tr>';
print '<tr><td>'.$langs->trans("DirectDownloadLink").'</td><td>';
if (! empty($ecmfile->ref) || ! empty($ecmfile->label))
print '<tr><td>';
if ($action != 'edit') print $langs->trans("DirectDownloadLink");
else print $langs->trans("FileSharedViaALink");
print '</td><td>';
if (! empty($object->share))
{
$modulepart='ecm';
$forcedownload=1;
$rellink='/document.php?modulepart='.$modulepart;
if ($forcedownload) $rellink.='&attachment=1';
if (! empty($object->entity)) $rellink.='&entity='.$object->entity;
//$rellink.='&file='.urlencode($filepath); // No need of name of file for public link, we will use the hash
$fulllink=$urlwithroot.$rellink;
if (! empty($ecmfile->ref)) $fulllink.='&hashn='.$ecmfile->ref; // Hash of file path
elseif (! empty($ecmfile->label)) $fulllink.='&hashc='.$ecmfile->label; // Hash of file content
print img_picto('','object_globe.png').' ';
print '<input type="text" class="quatrevingtpercent" id="downloadlink" name="downloadexternallink" value="'.dol_escape_htmltag($fulllink).'">';
print ' <a href="'.$fulllink.'">'.$langs->trans("Download").'</a>';
if ($action != 'edit')
{
$modulepart='ecm';
$forcedownload=1;
$rellink='/document.php?modulepart='.$modulepart;
if ($forcedownload) $rellink.='&attachment=1';
if (! empty($object->entity)) $rellink.='&entity='.$object->entity;
//$rellink.='&file='.urlencode($filepath); // No need of name of file for public link, we will use the hash
$fulllink=$urlwithroot.$rellink;
//if (! empty($object->ref)) $fulllink.='&hashn='.$object->ref; // Hash of file path
//elseif (! empty($object->label)) $fulllink.='&hashc='.$object->label; // Hash of file content
if (! empty($object->share)) $fulllink.='&hashp='.$object->share; // Hash for public share
print img_picto('','object_globe.png').' ';
if ($action != 'edit') print '<input type="text" class="quatrevingtpercent" id="downloadlink" name="downloadexternallink" value="'.dol_escape_htmltag($fulllink).'">';
else print $fulllink;
if ($action != 'edit') print ' <a href="'.$fulllink.'">'.$langs->trans("Download").'</a>';
}
else
{
print '<input type="checkbox" name="shareenabled"'.($object->share?' checked="checked"':'').' /> ';
}
}
else
{
print img_warning().' '.$langs->trans("FileNotYetIndexedInDatabase");
if ($action != 'edit')
{
print '<span class="opacitymedium">'.$langs->trans("FileNotShared").'</span>';
}
else
{
print '<input type="checkbox" name="shareenabled"'.($object->share?' checked="checked"':'').' /> ';
}
}
print '</td></tr>';
@ -315,7 +359,7 @@ print ajax_autoselect('downloadlink');
dol_fiche_end();
if ($_GET["action"] == 'edit')
if ($action == 'edit')
{
print '<div class="center">';
print '<input type="submit" class="button" name="submit" value="'.$langs->trans("Save").'">';
@ -328,13 +372,13 @@ if ($_GET["action"] == 'edit')
// Confirmation de la suppression d'une ligne categorie
if ($_GET['action'] == 'delete_file')
if ($action == 'delete_file')
{
print $form->formconfirm($_SERVER["PHP_SELF"].'?section='.urlencode($_GET["section"]), $langs->trans('DeleteFile'), $langs->trans('ConfirmDeleteFile',$urlfile), 'confirm_deletefile', '', 1, 1);
}
if ($_GET["action"] != 'edit')
if ($action != 'edit')
{
// Actions buttons
print '<div class="tabsAction">';
@ -343,7 +387,7 @@ if ($_GET["action"] != 'edit')
{
print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?action=edit&section='.$section.'&urlfile='.urlencode($urlfile).'">'.$langs->trans('Edit').'</a>';
print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?action=cancel&section='.$section.'&urlfile='.urlencode($urlfile).'&backtourl='.urlencode($backtourl).'">'.$langs->trans('Cancel').'</a>';
//print '<a class="butAction" href="'.$_SERVER['PHP_SELF'].'?action=cancel&section='.$section.'&urlfile='.urlencode($urlfile).'&backtourl='.urlencode($backtourl).'">'.$langs->trans('Cancel').'</a>';
}
/*
if ($user->rights->ecm->setup)

View File

@ -41,6 +41,11 @@ ALTER TABLE llx_website_page ADD COLUMN fk_user_modif integer;
-- For 7.0
ALTER TABLE llx_ecm_files MODIFY label varchar(128) NOT NULL;
ALTER TABLE llx_ecm_files ADD COLUMN share varchar(128) NULL after label;
ALTER TABLE llx_c_paiement ADD COLUMN position integer NOT NULL DEFAULT 0;
ALTER TABLE llx_c_payment_term ADD COLUMN position integer NOT NULL DEFAULT 0;

View File

@ -19,8 +19,9 @@
CREATE TABLE llx_ecm_files
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
ref varchar(128), -- Not used yet. Will contains a hash id from filename+filepath
label varchar(64) NOT NULL, -- label contains a md5
ref varchar(128), -- contains a hash id from filename+filepath
label varchar(128) NOT NULL, -- contains hash of file content
share varchar(128) NULL, -- contains a hash for file sharing
entity integer DEFAULT 1 NOT NULL, -- multi company id
filepath varchar(255) NOT NULL, -- relative to dolibarr document dir. Example module/def
filename varchar(255) NOT NULL, -- file name only without any directory

View File

@ -43,5 +43,6 @@ ECMFileManager=File manager
ECMSelectASection=Select a directory on left tree...
DirNotSynchronizedSyncFirst=This directory seems to be created or modified outside ECM module. You must click on "Resync" button first to synchronize disk and database to get content of this directory.
ReSyncListOfDir=Resync list of directories
HashSaved=Hash of file
FileNotYetIndexedInDatabase=File not yet indexed into database (try to re-upload it)
HashOfFileContent=Hash of file content
FileNotYetIndexedInDatabase=File not yet indexed into database (try to re-upload it)
FileSharedViaALink=File shared via a link

View File

@ -793,7 +793,7 @@ ViewFlatList=View flat list
RemoveString=Remove string '%s'
SomeTranslationAreUncomplete=Some languages may be partially translated or may contains errors. If you detect some, you can fix language files registering to <a href="https://transifex.com/projects/p/dolibarr/" target="_blank">https://transifex.com/projects/p/dolibarr/</a>.
DirectDownloadLink=Direct download link (public/external)
DirectDownloadInternalLink=Direct download link (need to be logged and permissions)
DirectDownloadInternalLink=Direct download link (need to be logged and need permissions)
Download=Download
ActualizeCurrency=Update currency rate
Fiscalyear=Fiscal year
@ -810,6 +810,7 @@ ImportId=Import id
Websites=Web sites
Events=Events
EMailTemplates=Emails templates
FileNotShared=File not shared to exernal public
# Week day
Monday=Monday
Tuesday=Tuesday

View File

@ -37,7 +37,7 @@ VirtualHostUrlNotDefined=URL of the virtual host served by external web server n
NoPageYet=No pages yet
SyntaxHelp=Help on specific syntax tips
YouCanEditHtmlSourceckeditor=You can edit HTML source code using the "Source" button in editor.
YouCanEditHtmlSource=You can include PHP code into this source using tags <strong>&lt;?php ?&gt;</strong>. The following global variables are available: $conf, $langs, $db, $mysoc, $user, $website.<br><br>You can also include content of another Page/Container with the following syntax: <strong>&lt;?php dolIncludeHtmlContent($websitekey.'/contentaliastoinclude.php'); ?&gt;</strong><br><br>To include a link to download a file stored into the <strong>documents</strong> directory, use the <strong>document.php</strong> wrapper:<br>Example, for a file into documents/ecm (need to be logged), syntax is:<br><strong>&lt;a href="/document.php?modulepart=ecm&file=reldir/filename.ext"&gt;</strong>.<br>for a file into documents/media (open access), syntax is:<br><strong>&lt;a href="/document.php?modulepart=medias&file=reldir/filename.ext"&gt;</strong>.<br><br>To include an image stored into the <strong>documents</strong> directory, use the <strong>viewimage.php</strong> wrapper:<br>Example, for an image into documents/media (open access), syntax is:<br><strong>&lt;a href="/viewimage.php?modulepart=medias&amp;file=filename.ext"&gt;</strong>.
YouCanEditHtmlSource=You can include PHP code into this source using tags <strong>&lt;?php ?&gt;</strong>. The following global variables are available: $conf, $langs, $db, $mysoc, $user, $website.<br><br>You can also include content of another Page/Container with the following syntax: <strong>&lt;?php dolIncludeHtmlContent($websitekey.'/contentaliastoinclude.php'); ?&gt;</strong><br><br>To include a link to download a file stored into the <strong>documents</strong> directory, use the <strong>document.php</strong> wrapper:<br>Example, for a file into documents/ecm (need to be logged), syntax is:<br><strong>&lt;a href="/document.php?modulepart=ecm&file=reldir/filename.ext"&gt;</strong>.<br>for a file into documents/media (open public access), syntax is:<br><strong>&lt;a href="/document.php?modulepart=medias[&hashp=publicsharekey if modulepart != medias]"&gt;</strong>.<br><br>To include an image stored into the <strong>documents</strong> directory, use the <strong>viewimage.php</strong> wrapper:<br>Example, for an image into documents/media (open access), syntax is:<br><strong>&lt;a href="/viewimage.php?modulepart=medias&amp;file=filename.ext"&gt;</strong>.
ClonePage=Clone page/container
CloneSite=Clone site
ConfirmClonePage=Please enter code/alias of new page and if it is a translation of the cloned page.