123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570 |
- <?php
- /* Copyright (C) 2008-2011 Laurent Destailleur <eldy@users.sourceforge.net>
- * Copyright (C) 2008-2017 Regis Houssin <regis.houssin@capnetworks.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * or see http://www.gnu.org/
- */
- /**
- * \file htdocs/core/lib/security.lib.php
- * \ingroup core
- * \brief Set of function used for dolibarr security (common function included into filefunc.inc.php)
- * Warning, this file must not depends on other library files, except function.lib.php
- * because it is used at low code level.
- */
- /**
- * Encode a string with base 64 algorithm + specific change
- * Code of this function is useless and we should use base64_encode only instead
- *
- * @param string $chain string to encode
- * @return string encoded string
- */
- function dol_encode($chain)
- {
- $strlength=dol_strlen($chain);
- for ($i=0; $i < $strlength; $i++)
- {
- $output_tab[$i] = chr(ord(substr($chain,$i,1))+17);
- }
- $string_coded = base64_encode(implode("",$output_tab));
- return $string_coded;
- }
- /**
- * Decode a base 64 encoded + specific string.
- * This function is called by filefunc.inc.php at each page call.
- * Code of this function is useless and we should use base64_decode only instead
- *
- * @param string $chain string to decode
- * @return string decoded string
- */
- function dol_decode($chain)
- {
- $chain = base64_decode($chain);
- $strlength=dol_strlen($chain);
- for($i=0; $i < $strlength;$i++)
- {
- $output_tab[$i] = chr(ord(substr($chain,$i,1))-17);
- }
- $string_decoded = implode("",$output_tab);
- return $string_decoded;
- }
- /**
- * Returns a hash of a string.
- * If constant MAIN_SECURITY_HASH_ALGO is defined, we use this function as hashing function.
- * If constant MAIN_SECURITY_SALT is defined, we use it as a salt.
- *
- * @param string $chain String to hash
- * @param int $type Type of hash (0:auto, 1:sha1, 2:sha1+md5, 3:md5, 4:md5 for OpenLdap). Use 3 here, if hash is not needed for security purpose, for security need, prefer 0.
- * @return string Hash of string
- */
- function dol_hash($chain,$type=0)
- {
- global $conf;
- // Salt value
- if (! empty($conf->global->MAIN_SECURITY_SALT)) $chain=$conf->global->MAIN_SECURITY_SALT.$chain;
- if ($type == 1) return sha1($chain);
- else if ($type == 2) return sha1(md5($chain));
- else if ($type == 3) return md5($chain);
- else if ($type == 4) return '{md5}'.base64_encode(mhash(MHASH_MD5,$chain)); // For OpenLdap with md5
- else if (! empty($conf->global->MAIN_SECURITY_HASH_ALGO) && $conf->global->MAIN_SECURITY_HASH_ALGO == 'sha1') return sha1($chain);
- else if (! empty($conf->global->MAIN_SECURITY_HASH_ALGO) && $conf->global->MAIN_SECURITY_HASH_ALGO == 'sha1md5') return sha1(md5($chain));
- // No particular enconding defined, use default
- return md5($chain);
- }
- /**
- * Check permissions of a user to show a page and an object. Check read permission.
- * If GETPOST('action','aZ09') defined, we also check write and delete permission.
- *
- * @param User $user User to check
- * @param string $features Features to check (it must be module name. Examples: 'societe', 'contact', 'produit&service', 'produit|service', ...)
- * @param int $objectid Object ID if we want to check a particular record (optional) is linked to a owned thirdparty (optional).
- * @param string $tableandshare 'TableName&SharedElement' with Tablename is table where object is stored. SharedElement is an optional key to define where to check entity for multicompany modume. Param not used if objectid is null (optional).
- * @param string $feature2 Feature to check, second level of permission (optional). Can be or check with 'level1|level2'.
- * @param string $dbt_keyfield Field name for socid foreign key if not fk_soc. Not used if objectid is null (optional)
- * @param string $dbt_select Field name for select if not rowid. Not used if objectid is null (optional)
- * @param Canvas $objcanvas Object canvas
- * @return int Always 1, die process if not allowed
- * @see dol_check_secure_access_document
- */
- function restrictedArea($user, $features, $objectid=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $objcanvas=null)
- {
- global $db, $conf;
- //dol_syslog("functions.lib:restrictedArea $feature, $objectid, $dbtablename,$feature2,$dbt_socfield,$dbt_select");
- //print "user_id=".$user->id.", features=".$features.", feature2=".$feature2.", objectid=".$objectid;
- //print ", dbtablename=".$dbtablename.", dbt_socfield=".$dbt_keyfield.", dbt_select=".$dbt_select;
- //print ", perm: ".$features."->".$feature2."=".($user->rights->$features->$feature2->lire)."<br>";
- // If we use canvas, we try to use function that overlod restrictarea if provided with canvas
- if (is_object($objcanvas))
- {
- if (method_exists($objcanvas->control,'restrictedArea')) return $objcanvas->control->restrictedArea($user,$features,$objectid,$dbtablename,$feature2,$dbt_keyfield,$dbt_select);
- }
- if ($dbt_select != 'rowid' && $dbt_select != 'id') $objectid = "'".$objectid."'";
- // Features/modules to check
- $featuresarray = array($features);
- if (preg_match('/&/', $features)) $featuresarray = explode("&", $features);
- else if (preg_match('/\|/', $features)) $featuresarray = explode("|", $features);
- // More subfeatures to check
- if (! empty($feature2)) $feature2 = explode("|", $feature2);
- // More parameters
- $params = explode('&', $tableandshare);
- $dbtablename=(! empty($params[0]) ? $params[0] : '');
- $sharedelement=(! empty($params[1]) ? $params[1] : $dbtablename);
- $listofmodules=explode(',',$conf->global->MAIN_MODULES_FOR_EXTERNAL);
- // Check read permission from module
- $readok=1; $nbko=0;
- foreach ($featuresarray as $feature) // first we check nb of test ko
- {
- if (! empty($user->societe_id) && ! empty($conf->global->MAIN_MODULES_FOR_EXTERNAL) && ! in_array($feature,$listofmodules)) // If limits on modules for external users, module must be into list of modules for external users
- {
- $readok=0; $nbko++;
- continue;
- }
- if ($feature == 'societe')
- {
- if (! $user->rights->societe->lire && ! $user->rights->fournisseur->lire) { $readok=0; $nbko++; }
- }
- else if ($feature == 'contact')
- {
- if (! $user->rights->societe->contact->lire) { $readok=0; $nbko++; }
- }
- else if ($feature == 'produit|service')
- {
- if (! $user->rights->produit->lire && ! $user->rights->service->lire) { $readok=0; $nbko++; }
- }
- else if ($feature == 'prelevement')
- {
- if (! $user->rights->prelevement->bons->lire) { $readok=0; $nbko++; }
- }
- else if ($feature == 'cheque')
- {
- if (! $user->rights->banque->cheque) { $readok=0; $nbko++; }
- }
- else if ($feature == 'projet')
- {
- if (! $user->rights->projet->lire && ! $user->rights->projet->all->lire) { $readok=0; $nbko++; }
- }
- else if (! empty($feature2)) // This should be used for future changes
- {
- $tmpreadok=1;
- foreach($feature2 as $subfeature)
- {
- if (! empty($subfeature) && empty($user->rights->$feature->$subfeature->lire) && empty($user->rights->$feature->$subfeature->read)) { $tmpreadok=0; }
- else if (empty($subfeature) && empty($user->rights->$feature->lire) && empty($user->rights->$feature->read)) { $tmpreadok=0; }
- else { $tmpreadok=1; break; } // Break is to bypass second test if the first is ok
- }
- if (! $tmpreadok) // We found a test on feature that is ko
- {
- $readok=0; // All tests are ko (we manage here the and, the or will be managed later using $nbko).
- $nbko++;
- }
- }
- else if (! empty($feature) && ($feature!='user' && $feature!='usergroup')) // This is for old permissions
- {
- if (empty($user->rights->$feature->lire)
- && empty($user->rights->$feature->read)
- && empty($user->rights->$feature->run)) { $readok=0; $nbko++; }
- }
- }
- // If a or and at least one ok
- if (preg_match('/\|/', $features) && $nbko < count($featuresarray)) $readok=1;
- if (! $readok) accessforbidden();
- //print "Read access is ok";
- // Check write permission from module
- $createok=1; $nbko=0;
- if (GETPOST('action','aZ09') == 'create')
- {
- foreach ($featuresarray as $feature)
- {
- if ($feature == 'contact')
- {
- if (! $user->rights->societe->contact->creer) { $createok=0; $nbko++; }
- }
- else if ($feature == 'produit|service')
- {
- if (! $user->rights->produit->creer && ! $user->rights->service->creer) { $createok=0; $nbko++; }
- }
- else if ($feature == 'prelevement')
- {
- if (! $user->rights->prelevement->bons->creer) { $createok=0; $nbko++; }
- }
- else if ($feature == 'commande_fournisseur')
- {
- if (! $user->rights->fournisseur->commande->creer) { $createok=0; $nbko++; }
- }
- else if ($feature == 'banque')
- {
- if (! $user->rights->banque->modifier) { $createok=0; $nbko++; }
- }
- else if ($feature == 'cheque')
- {
- if (! $user->rights->banque->cheque) { $createok=0; $nbko++; }
- }
- else if (! empty($feature2)) // This should be used
- {
- foreach($feature2 as $subfeature)
- {
- if (empty($user->rights->$feature->$subfeature->creer)
- && empty($user->rights->$feature->$subfeature->write)
- && empty($user->rights->$feature->$subfeature->create)) { $createok=0; $nbko++; }
- else { $createok=1; break; } // Break to bypass second test if the first is ok
- }
- }
- else if (! empty($feature)) // This is for old permissions ('creer' or 'write')
- {
- //print '<br>feature='.$feature.' creer='.$user->rights->$feature->creer.' write='.$user->rights->$feature->write;
- if (empty($user->rights->$feature->creer)
- && empty($user->rights->$feature->write)) { $createok=0; $nbko++; }
- }
- }
- // If a or and at least one ok
- if (preg_match('/\|/', $features) && $nbko < count($featuresarray)) $createok=1;
- if (! $createok) accessforbidden();
- //print "Write access is ok";
- }
- // Check create user permission
- $createuserok=1;
- if (GETPOST('action','aZ09') == 'confirm_create_user' && GETPOST("confirm") == 'yes')
- {
- if (! $user->rights->user->user->creer) $createuserok=0;
- if (! $createuserok) accessforbidden();
- //print "Create user access is ok";
- }
- // Check delete permission from module
- $deleteok=1; $nbko=0;
- if ((GETPOST('action','aZ09') == 'confirm_delete' && GETPOST("confirm") == 'yes') || GETPOST('action','aZ09') == 'delete')
- {
- foreach ($featuresarray as $feature)
- {
- if ($feature == 'contact')
- {
- if (! $user->rights->societe->contact->supprimer) $deleteok=0;
- }
- else if ($feature == 'produit|service')
- {
- if (! $user->rights->produit->supprimer && ! $user->rights->service->supprimer) $deleteok=0;
- }
- else if ($feature == 'commande_fournisseur')
- {
- if (! $user->rights->fournisseur->commande->supprimer) $deleteok=0;
- }
- else if ($feature == 'banque')
- {
- if (! $user->rights->banque->modifier) $deleteok=0;
- }
- else if ($feature == 'cheque')
- {
- if (! $user->rights->banque->cheque) $deleteok=0;
- }
- else if ($feature == 'ecm')
- {
- if (! $user->rights->ecm->upload) $deleteok=0;
- }
- else if ($feature == 'ftp')
- {
- if (! $user->rights->ftp->write) $deleteok=0;
- }
- else if (! empty($feature2)) // This should be used for future changes
- {
- foreach($feature2 as $subfeature)
- {
- if (empty($user->rights->$feature->$subfeature->supprimer) && empty($user->rights->$feature->$subfeature->delete)) $deleteok=0;
- else { $deleteok=1; break; } // For bypass the second test if the first is ok
- }
- }
- else if (! empty($feature)) // This is for old permissions
- {
- //print '<br>feature='.$feature.' creer='.$user->rights->$feature->supprimer.' write='.$user->rights->$feature->delete;
- if (empty($user->rights->$feature->supprimer)
- && empty($user->rights->$feature->delete)
- && empty($user->rights->$feature->run)) $deleteok=0;
- }
- }
- // If a or and at least one ok
- if (preg_match('/\|/', $features) && $nbko < count($featuresarray)) $deleteok=1;
- if (! $deleteok) accessforbidden();
- //print "Delete access is ok";
- }
- // If we have a particular object to check permissions on, we check this object
- // is linked to a company allowed to $user.
- if (! empty($objectid) && $objectid > 0)
- {
- $ok = checkUserAccessToObject($user, $featuresarray, $objectid, $tableandshare, $feature2, $dbt_keyfield, $dbt_select);
- return $ok ? 1 : accessforbidden();
- }
- return 1;
- }
- /**
- * Check access by user to object.
- * This function is also called by restrictedArea
- *
- * @param User $user User to check
- * @param array $featuresarray Features/modules to check. Example: ('user','service')
- * @param int $objectid Object ID if we want to check a particular record (optional) is linked to a owned thirdparty (optional).
- * @param string $tableandshare 'TableName&SharedElement' with Tablename is table where object is stored. SharedElement is an optional key to define where to check entity for multicompany modume. Param not used if objectid is null (optional).
- * @param string $feature2 Feature to check, second level of permission (optional). Can be or check with 'level1|level2'.
- * @param string $dbt_keyfield Field name for socid foreign key if not fk_soc. Not used if objectid is null (optional)
- * @param string $dbt_select Field name for select if not rowid. Not used if objectid is null (optional)
- * @return bool True if user has access, False otherwise
- * @see restrictedArea
- */
- function checkUserAccessToObject($user, $featuresarray, $objectid=0, $tableandshare='', $feature2='', $dbt_keyfield='', $dbt_select='rowid')
- {
- global $db, $conf;
- // More parameters
- $params = explode('&', $tableandshare);
- $dbtablename=(! empty($params[0]) ? $params[0] : '');
- $sharedelement=(! empty($params[1]) ? $params[1] : $dbtablename);
- foreach ($featuresarray as $feature)
- {
- $sql='';
- // For backward compatibility
- if ($feature == 'member') $feature='adherent';
- $check = array('adherent','banque','user','usergroup','produit','service','produit|service','categorie'); // Test on entity only (Objects with no link to company)
- $checksoc = array('societe'); // Test for societe object
- $checkother = array('contact'); // Test on entity and link to societe. Allowed if link is empty (Ex: contacts...).
- $checkproject = array('projet'); // Test for project object
- $nocheck = array('barcode','stock','fournisseur'); // No test
- $checkdefault = 'all other not already defined'; // Test on entity and link to third party. Not allowed if link is empty (Ex: invoice, orders...).
- // If dbtable not defined, we use same name for table than module name
- if (empty($dbtablename)) $dbtablename = $feature;
- // Check permission for object with entity
- if (in_array($feature,$check))
- {
- $sql = "SELECT dbt.".$dbt_select;
- $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
- $sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
- if (($feature == 'user' || $feature == 'usergroup') && ! empty($conf->multicompany->enabled) && $conf->entity == 1 && $user->admin && ! $user->entity)
- {
- $sql.= " AND dbt.entity IS NOT NULL";
- }
- else
- {
- $sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
- }
- }
- else if (in_array($feature,$checksoc)) // We check feature = checksoc
- {
- // If external user: Check permission for external users
- if ($user->societe_id > 0)
- {
- if ($user->societe_id <> $objectid) return false;
- }
- // If internal user: Check permission for internal users that are restricted on their objects
- else if (! empty($conf->societe->enabled) && ($user->rights->societe->lire && ! $user->rights->societe->client->voir))
- {
- $sql = "SELECT sc.fk_soc";
- $sql.= " FROM (".MAIN_DB_PREFIX."societe_commerciaux as sc";
- $sql.= ", ".MAIN_DB_PREFIX."societe as s)";
- $sql.= " WHERE sc.fk_soc = ".$objectid;
- $sql.= " AND sc.fk_user = ".$user->id;
- $sql.= " AND sc.fk_soc = s.rowid";
- $sql.= " AND s.entity IN (".getEntity($sharedelement, 1).")";
- }
- // If multicompany and internal users with all permissions, check user is in correct entity
- else if (! empty($conf->multicompany->enabled))
- {
- $sql = "SELECT s.rowid";
- $sql.= " FROM ".MAIN_DB_PREFIX."societe as s";
- $sql.= " WHERE s.rowid = ".$objectid;
- $sql.= " AND s.entity IN (".getEntity($sharedelement, 1).")";
- }
- }
- else if (in_array($feature,$checkother)) // Test on entity and link to societe. Allowed if link is empty (Ex: contacts...).
- {
- // If external user: Check permission for external users
- if ($user->societe_id > 0)
- {
- $sql = "SELECT dbt.".$dbt_select;
- $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
- $sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
- $sql.= " AND dbt.fk_soc = ".$user->societe_id;
- }
- // If internal user: Check permission for internal users that are restricted on their objects
- else if (! empty($conf->societe->enabled) && ($user->rights->societe->lire && ! $user->rights->societe->client->voir))
- {
- $sql = "SELECT dbt.".$dbt_select;
- $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
- $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON dbt.fk_soc = sc.fk_soc AND sc.fk_user = '".$user->id."'";
- $sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
- $sql.= " AND (dbt.fk_soc IS NULL OR sc.fk_soc IS NOT NULL)"; // Contact not linked to a company or to a company of user
- $sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
- }
- // If multicompany and internal users with all permissions, check user is in correct entity
- else if (! empty($conf->multicompany->enabled))
- {
- $sql = "SELECT dbt.".$dbt_select;
- $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
- $sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
- $sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
- }
- }
- else if (in_array($feature,$checkproject))
- {
- if (! empty($conf->projet->enabled) && ! $user->rights->projet->all->lire)
- {
- include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
- $projectstatic=new Project($db);
- $tmps=$projectstatic->getProjectsAuthorizedForUser($user,0,1,0);
- $tmparray=explode(',',$tmps);
- if (! in_array($objectid,$tmparray)) return false;
- }
- else
- {
- $sql = "SELECT dbt.".$dbt_select;
- $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
- $sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
- $sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
- }
- }
- else if (! in_array($feature,$nocheck)) // By default we check with link to third party
- {
- // If external user: Check permission for external users
- if ($user->societe_id > 0)
- {
- if (empty($dbt_keyfield)) dol_print_error('','Param dbt_keyfield is required but not defined');
- $sql = "SELECT dbt.".$dbt_keyfield;
- $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
- $sql.= " WHERE dbt.rowid = ".$objectid;
- $sql.= " AND dbt.".$dbt_keyfield." = ".$user->societe_id;
- }
- // If internal user: Check permission for internal users that are restricted on their objects
- else if (! empty($conf->societe->enabled) && ($user->rights->societe->lire && ! $user->rights->societe->client->voir))
- {
- if (empty($dbt_keyfield)) dol_print_error('','Param dbt_keyfield is required but not defined');
- $sql = "SELECT sc.fk_soc";
- $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
- $sql.= ", ".MAIN_DB_PREFIX."societe as s";
- $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
- $sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
- $sql.= " AND sc.fk_soc = dbt.".$dbt_keyfield;
- $sql.= " AND dbt.".$dbt_keyfield." = s.rowid";
- $sql.= " AND s.entity IN (".getEntity($sharedelement, 1).")";
- $sql.= " AND sc.fk_user = ".$user->id;
- }
- // If multicompany and internal users with all permissions, check user is in correct entity
- else if (! empty($conf->multicompany->enabled))
- {
- $sql = "SELECT dbt.".$dbt_select;
- $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
- $sql.= " WHERE dbt.".$dbt_select." = ".$objectid;
- $sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")";
- }
- }
- //print "sql=".$sql."<br>";
- if ($sql)
- {
- $resql=$db->query($sql);
- if ($resql)
- {
- if ($db->num_rows($resql) == 0) return false;
- }
- else
- {
- return false;
- }
- }
- }
- return true;
- }
- /**
- * Show a message to say access is forbidden and stop program
- * Calling this function terminate execution of PHP.
- *
- * @param string $message Force error message
- * @param int $printheader Show header before
- * @param int $printfooter Show footer after
- * @param int $showonlymessage Show only message parameter. Otherwise add more information.
- * @return void
- */
- function accessforbidden($message='',$printheader=1,$printfooter=1,$showonlymessage=0)
- {
- global $conf, $db, $user, $langs;
- if (! is_object($langs))
- {
- include_once DOL_DOCUMENT_ROOT.'/core/class/translate.class.php';
- $langs=new Translate('',$conf);
- }
- $langs->load("errors");
- if ($printheader)
- {
- if (function_exists("llxHeader")) llxHeader('');
- else if (function_exists("llxHeaderVierge")) llxHeaderVierge('');
- }
- print '<div class="error">';
- if (! $message) print $langs->trans("ErrorForbidden");
- else print $message;
- print '</div>';
- print '<br>';
- if (empty($showonlymessage))
- {
- if ($user->login)
- {
- print $langs->trans("CurrentLogin").': <font class="error">'.$user->login.'</font><br>';
- print $langs->trans("ErrorForbidden2",$langs->trans("Home"),$langs->trans("Users"));
- }
- else
- {
- print $langs->trans("ErrorForbidden3");
- }
- }
- if ($printfooter && function_exists("llxFooter")) llxFooter();
- exit(0);
- }
|