Compare commits

...

10 commits

14 changed files with 1486 additions and 424 deletions

View file

@ -23,3 +23,14 @@
// Accesslog base DN
define('LS_ACCESSLOG_BASEDN', 'cn=ldapsaisie-accesslog');
/*
* Enable logging write events on LDAP entries managed by LdapSaisie in the accesslog base
*
* The feature permit to LdapSaisie to write it self log entries in accesslog base about
* modifications made with its system account with the right author DN.
*
* Note: If your LDAP directory ACL permit to your users to do them self modifications on LDAP
* directory, the recommanded way is to use authz proxy authentication (see useAuthzProxyControl
* configuration parameter).
*/
define('LS_ACCESSLOG_LOG_WRITE_EVENTS', false);

View file

@ -0,0 +1,36 @@
table.objectAccessLogs tbody tr {
border-bottom: 1px dotted;
}
table.objectAccessLogs table.mods {
width: 100%;
table-layout: fixed;
border-collapse: collapse;
}
table.objectAccessLogs table.mods td, table.objectAccessLogs table.mods th {
border-left: 1px dotted;
}
table.objectAccessLogs table.mods tr {
border: none!important;
}
table.objectAccessLogs .col-attr {
width: 15em;
}
table.objectAccessLogs .col-op {
width: 6em;
}
table.objectAccessLogs .col-value {
width: 25em;
}
table.objectAccessLogs .col-value div {
overflow: scroll;
width: 100%;
margin: 0;
padding: 0;
}

View file

@ -25,30 +25,37 @@ LSerror :: defineError('ACCESSLOG_SUPPORT_01',
);
$GLOBALS['accesslog_reqTypes'] = array(
'add' => _('Add'),
'bind' => _('Log in'),
'compare' => _('Compare'),
'delete' => _('Delete'),
'extended' => _('Extended'),
'modify' => _('Modify'),
'modrdn' => _('Modify RDN'),
'search' => _('Search'),
'unbind' => _('Log out'),
'add' => ___('Add'),
'bind' => ___('Log in'),
'compare' => ___('Compare'),
'delete' => ___('Delete'),
'extended' => ___('Extended'),
'modify' => ___('Modify'),
'modrdn' => ___('Modify RDN'),
'search' => ___('Search'),
'unbind' => ___('Log out'),
);
$GLOBALS['accesslog_modOps'] = array(
'+' => _('Add'),
'-' => _('Delete'),
'=' => _('Replace'),
'' => _('Replace'),
'#' => _('Increment'),
'+' => ___('Add'),
'-' => ___('Delete'),
'=' => ___('Replace'),
'' => ___('Replace'),
'#' => ___('Increment'),
);
function LSaddon_accesslog_support() {
if (!defined('LS_ACCESSLOG_BASEDN')) {
LSerror :: addErrorCode('ACCESSLOG_SUPPORT_01', 'LS_ACCESSLOG_BASEDN');
$MUST_DEFINE_CONST= array(
'LS_ACCESSLOG_BASEDN',
'LS_ACCESSLOG_LOG_WRITE_EVENTS',
);
foreach($MUST_DEFINE_CONST as $const) {
if (!defined($const) || is_empty(constant($const))) {
LSerror :: addErrorCode('ACCESSLOG_SUPPORT_01', $const);
return false;
}
}
if (php_sapi_name() === 'cli') {
LScli::add_command(
'getEntryAccessLog',
@ -57,10 +64,18 @@ function LSaddon_accesslog_support() {
'[entry DN] [page]'
);
}
elseif (LS_ACCESSLOG_LOG_WRITE_EVENTS && LSsession :: loadLSclass('LSldap')) {
LSldap :: addEvent('updated', 'onEntryUpdated');
LSldap :: addEvent('moved', 'onEntryMoved');
LSldap :: addEvent('user_password_updated', 'onEntryUserPasswordUpdated');
LSldap :: addEvent('deleted', 'onEntryDeleted');
}
return true;
}
function mapAccessLogEntry(&$entry) {
foreach($entry['attrs'] as $attr => $values)
$entry['attrs'][$attr] = ensureIsArray($values);
$attrs = $entry['attrs'];
$entry['start'] = LSldap::parseDate(LSldap::getAttr($attrs, 'reqStart'));
$entry['end'] = LSldap::parseDate(LSldap::getAttr($attrs, 'reqEnd'));
@ -73,21 +88,23 @@ function mapAccessLogEntry(&$entry) {
$entry['type'] = LSldap::getAttr($attrs, 'reqType');
$entry['result'] = ldap_err2str(LSldap::getAttr($attrs, 'reqResult'));
$entry['message'] = LSldap::getAttr($attrs, 'reqMessage');
if ($entry['type'] === 'modify' && LSldap::getAttr($attrs, 'reqMod', true)) {
$mods = array();
foreach(LSldap::getAttr($attrs, 'reqMod', true) as $mod) {
if (preg_match('/^([^\:]+)\:([^ ]?) (.*)$/', $mod, $m)) {
$attr = $m[1];
$op = $m[2];
$value = $m[3];
if (preg_match('/^(?P<attr>[^\:]+)\:(?P<op>[^ ]?)( (?P<value>.*))?$/', $mod, $m)) {
$attr = $m['attr'];
$op = $m['op'];
$value = isset($m['value'])?$m['value']:null;
if (!array_key_exists($attr, $mods)) {
$mods[$attr] = array(
'mods' => array(),
'changes' => array(),
'old_values' => array(),
);
}
$mods[$attr]['changes'][] = array(
'op' => array_key_exists($op, $GLOBALS['accesslog_modOps']) ? $GLOBALS['accesslog_modOps'][$op] : $op,
'op' => (
array_key_exists($op, $GLOBALS['accesslog_modOps'])?
_($GLOBALS['accesslog_modOps'][$op]): $op
),
'value' => $value,
);
}
@ -99,23 +116,39 @@ function mapAccessLogEntry(&$entry) {
}
}
}
if ($mods)
$entry['mods'] = $mods;
if ($entry['type'] === 'modrdn') {
$new_rdn = LSldap::getAttr($attrs, 'reqNewRDN', false);
$superior_dn = LSldap::getAttr($attrs, 'reqNewSuperior', false);
if (!$superior_dn) {
$superior_dn = parentDn(LSldap::getAttr($attrs, 'reqDN', false));
}
$entry['new_dn'] = "$new_rdn,$superior_dn";
}
if (array_key_exists($entry['type'], $GLOBALS['accesslog_reqTypes'])) {
$entry['type'] = $GLOBALS['accesslog_reqTypes'][$entry['type']];
$entry['type'] = _($GLOBALS['accesslog_reqTypes'][$entry['type']]);
}
}
function sortLogEntryByDate($a, $b) {
return ($a['start'] === $b['start']) ? 0 : ($a['start'] < $b['start']) ? -1 : 1;
function sortLogEntriesByDate(&$a, &$b) {
$astart = LSldap::getAttr($a['attrs'], 'reqStart');
$bstart = LSldap::getAttr($b['attrs'], 'reqStart');
return ($astart === $bstart) ? 0 : ($astart < $bstart) ? -1 : 1;
}
function getEntryAccessLog($dn) {
$data = LSldap::search(
Net_LDAP2_Filter::create('reqDn', 'equals', $dn),
function getEntryAccessLog($dn, $start_date=null) {
$filter = Net_LDAP2_Filter::create('reqDn', 'equals', $dn);
if ($start_date) {
$date_filter = Net_LDAP2_Filter::create('reqStart', 'greaterOrEqual', $start_date);
$filter = Net_LDAP2_Filter::combine('and', array($filter, $date_filter));
}
$entries = LSldap::search(
$filter,
LS_ACCESSLOG_BASEDN,
array(
'attributes' => array(
'reqDN',
'reqStart',
'reqEnd',
'reqAuthzID',
@ -124,22 +157,33 @@ function getEntryAccessLog($dn) {
'reqMessage',
'reqMod',
'reqOld',
'reqNewRDN',
'reqNewSuperior',
),
)
);
if (!is_array($data)) {
if (!is_array($entries)) {
return;
}
usort($entries, 'sortLogEntriesByDate');
$logs = array();
foreach($data as $entry) {
foreach($entry['attrs'] as $attr => $values) {
$entry['attrs'][$attr] = ensureIsArray($values);
}
$new_dn = null;
$rename_date = null;
foreach($entries as $entry) {
mapAccessLogEntry($entry);
$logs[] = $entry;
if (isset($entry['new_dn'])) {
$new_dn = $entry['new_dn'];
$rename_date = LSldap::formatDate($entry['start']);
break;
}
usort($logs, 'sortLogEntryByDate');
return array_reverse($logs);
}
if ($new_dn) {
$next_logs = getEntryAccessLog($new_dn, $rename_date);
if (is_array($next_logs))
$logs = array_merge($logs, $next_logs);
}
return $start_date?$logs:array_reverse($logs);
}
function getEntryAccessLogPage($dn, $page = false, $nbByPage = 30) {
@ -183,11 +227,136 @@ function showObjectAccessLogs($obj) {
'action' => 'view',
);
LStemplate::assign('LSview_actions', $LSview_actions);
LStemplate::addCSSFile('showObjectAccessLogs.css');
LSsession::setTemplate('showObjectAccessLogs.tpl');
LSsession::displayTemplate();
exit();
}
function onEntryUpdated($data) {
$now = LSldap::formatDate();
$dn = "reqStart=$now,".LS_ACCESSLOG_BASEDN;
$new_entry = $data['original_entry']->isNew();
$attrs = array(
'reqStart' => array($now),
'reqEnd' => array($now),
'reqType' => array($new_entry?"add":"modify"),
'reqSession' => array("1024"),
'reqAuthzID' => array(LSsession :: get('authenticated_user_dn')),
'reqDN' => array($data["dn"]),
'reqResult' => array("0"),
);
// Compute modifications
$mods = array();
$olds = array();
if ($new_entry)
foreach(ensureIsArray($data['entry']->getValue('objectClass', 'all')) as $value)
$mods[] = "objectClass:+ $value";
foreach($data['changes'] as $attr => $values) {
if (strtolower($attr) == 'userpassword')
foreach(array_keys($values) as $idx)
$values[$idx] = hashPasswordForLogs($values[$idx]);
if ($values) {
foreach($values as $value)
$mods[] = $new_entry?"$attr:+ $value":"$attr:= $value";
}
else if (!$new_entry) {
$mods[] = "$attr:=";
}
if (!$new_entry)
foreach(ensureIsArray($data['original_entry']->getValue($attr, 'all')) as $value)
$olds[] = "$attr: $value";
}
if (!$mods) return true;
$attrs['reqMod'] = $mods;
if ($olds)
$attrs['reqOld'] = $olds;
LSldap::getNewEntry($dn, array($new_entry?'auditAdd':'auditModify'), $attrs, true);
}
function onEntryUserPasswordUpdated($data) {
$now = LSldap::formatDate();
$dn = "reqStart=$now,".LS_ACCESSLOG_BASEDN; $mods = array();
// Compute modifications
$mods = array();
// Retreive fresh entry to retreive hased/stored password
$attrs = LSldap :: getAttrs($data['dn'], null, array('userPassword'));
$new_passwords = $data["new_passwords"];
if ($attrs)
$new_passwords = LSldap :: getAttr($attrs, 'userPassword', true);
if ($new_passwords) {
foreach($new_passwords as $password)
$mods[] = "userPassword:= ".hashPasswordForLogs($password);
}
else
$mods[] = "userPassword:=";
$attrs = array(
'reqStart' => array($now),
'reqEnd' => array($now),
'reqType' => array("modify"),
'reqSession' => array("1024"),
'reqAuthzID' => array(LSsession :: get('authenticated_user_dn')),
'reqDN' => array($data["dn"]),
'reqResult' => array("0"),
'reqMod' => $mods,
);
LSldap::getNewEntry($dn, array('auditModify'), $attrs, true);
}
function onEntryMoved($data) {
$now = LSldap::formatDate();
$dn = "reqStart=$now,".LS_ACCESSLOG_BASEDN;
$attrs = array(
'reqStart' => array($now),
'reqEnd' => array($now),
'reqType' => array("modrdn"),
'reqSession' => array("1024"),
'reqAuthzID' => array(LSsession :: get('authenticated_user_dn')),
'reqDN' => array($data["old"]),
'reqNewRDN' => array(getRdn($data["new"])),
'reqResult' => array("0"),
);
$new_superior = parentDn($data["new"]);
$old_superior = parentDn($data["old"]);
if ($new_superior != $old_superior)
$attrs['reqNewSuperior'] = array($new_superior);
LSldap::getNewEntry($dn, array('auditModRDN'), $attrs, true);
}
function onEntryDeleted($data) {
$now = LSldap::formatDate();
$dn = "reqStart=$now,".LS_ACCESSLOG_BASEDN;
$attrs = array(
'reqStart' => array($now),
'reqEnd' => array($now),
'reqType' => array("delete"),
'reqSession' => array("1024"),
'reqAuthzID' => array(LSsession :: get('authenticated_user_dn')),
'reqDN' => array($data["dn"]),
'reqResult' => array("0"),
);
LSldap::getNewEntry($dn, array('auditDelete'), $attrs, true);
}
function hashPasswordForLogs($password) {
if (preg_match('/^{[^}]+}.*/', $password))
// Already hashed
return $password;
if(defined('PASSWORD_ARGON2I'))
return '{ARGON2}'.password_hash($password, PASSWORD_ARGON2I);
if(defined('MHASH_SHA512') && function_exists('mhash') && function_exists('mhash_keygen_s2k')) {
mt_srand( (double) microtime() * 1000000 );
$salt = mhash_keygen_s2k(MHASH_SHA512, $password, substr( pack( "h*", md5( mt_rand() ) ), 0, 8 ), 4 );
return "{SSHA512}".base64_encode(mhash($mhash_type, $password.$salt).$salt);
}
return '[not logged]';
}
if (php_sapi_name() !== 'cli') {
return true;
}

View file

@ -88,46 +88,54 @@ class LScli extends LSlog_staticLoggerClass {
* Show usage message
*
* @param string|false $error Error message to display before usage message (optional, default: false)
* @param string $extra_args Optional argument use to compute error message using sprintf (if provided)
* @return void
**/
public static function usage($error=false) {
public static function usage($error=false, ...$extra_args) {
global $argv;
if ($error)
if ($error) {
if ($extra_args)
$error = call_user_func_array('sprintf', array_merge(array($error), $extra_args));
echo "$error\n\n";
}
echo "Usage : ".basename($argv[0])." [-h] [-qdC] command\n";
echo " -h Show this message\n";
echo " -q|--quiet Quiet mode: nothing log on console (but keep other logging handler)\n";
echo " -d|--debug Debug mode (set log level to DEBUG, default: WARNING)\n";
echo " -v|--verbose Verbose mode (set log level to INFO, default: WARNING)\n";
echo " --trace Trace mode (set log level to TRACE, default: WARNING)\n";
echo " -C|--console Log on console with same log level as other handlers (otherwise, log only errors)\n";
echo " -S|--ldap-server Connect to a specific LDAP server: you could specify a LDAP\n";
echo " server by its declaration order in configuration (default:\n";
echo " first one).\n";
echo " -L|--load-class Load specific class to permit access to its CLI commands\n";
echo " -A|--load-addons Load specific addon to permit access to its CLI commands\n";
echo " command Command to run\n";
echo "\n";
echo "Available commands :\n";
printf(_(
"Usage: %s [-h] [-qdC] command
-h Show this message
-q|--quiet Quiet mode: nothing log on console (but keep other logging handler)
-d|--debug Debug mode (set log level to DEBUG, default: WARNING)
-v|--verbose Verbose mode (set log level to INFO, default: WARNING)
--trace Trace mode (set log level to TRACE, default: WARNING)
-C|--console Log on console with same log level as other handlers (otherwise, log only errors)
-S|--ldap-server Connect to a specific LDAP server: you could specify a LDAP
server by its declaration order in configuration (default:
first one).
-L|--load-class Load specific class to permit access to its CLI commands
-A|--load-addons Load specific addon to permit access to its CLI commands
command Command to run
Available commands:
"), basename($argv[0]));
foreach (self :: $commands as $command => $info) {
if (self :: $current_command and self :: $current_command != $command)
continue;
echo " $command : ".$info['short_desc']."\n";
echo " ".basename($argv[0])." $command ".($info['usage_args']?$info['usage_args']:'')."\n";
echo " $command: ".__($info['short_desc'])."\n";
echo " ".basename($argv[0])." $command ".($info['usage_args']?__($info['usage_args']):'')."\n";
if ($info['long_desc']) {
if (is_array($info['long_desc']))
if (is_array($info['long_desc'])) {
$info['long_desc'] = array_map('__', $info['long_desc']);
$info['long_desc'] = implode("\n", $info['long_desc']);
echo "\n ".str_replace("\n", "\n ", wordwrap($info['long_desc']))."\n";
}
echo "\n ".str_replace("\n", "\n ", wordwrap(__($info['long_desc'])))."\n";
}
echo "\n";
}
if (empty(self :: $commands))
echo " Currently no available command is declared.\n";
echo " "._("Currently no available command is declared.")."\n";
exit(($error?1:0));
exit($error?1:0);
}
/**
@ -186,7 +194,7 @@ class LScli extends LSlog_staticLoggerClass {
$i++;
$ldap_server_id = intval($argv[$i]);
if(!LSsession :: setLdapServer($ldap_server_id))
self :: usage("Fail to select LDAP server #$ldap_server_id.");
self :: usage(_("Fail to select LDAP server #%s."), $ldap_server_id);
break;
case '--sub-dn':
$i++;
@ -197,14 +205,14 @@ class LScli extends LSlog_staticLoggerClass {
$i++;
$class = $argv[$i];
if(!LSsession :: loadLSclass($class))
self :: usage("Fail to load class '$class'.");
self :: usage(_("Fail to load class '%s'."), $class);
break;
case '-A':
case '--load-addon':
$i++;
$addon = $argv[$i];
if(!LSsession :: loadLSaddon($addon))
self :: usage("Fail to load addon '$addon'.");
self :: usage(_("Fail to load addon '%s'."), $addon);
break;
case '--':
$command_args = array_merge($command_args, array_slice($argv, $i));
@ -215,7 +223,8 @@ class LScli extends LSlog_staticLoggerClass {
$command_args[] = $argv[$i];
else
self :: usage(
getFData(_("Invalid parameter \"%{parameter}\".\nNote: Command's parameter/argument must be place after the command."), $argv[$i])
_("Invalid parameter \"%s\".\nNote: Command's parameter/argument must be place after the command."),
$argv[$i]
);
}
}
@ -249,7 +258,7 @@ class LScli extends LSlog_staticLoggerClass {
if ($ldap_server_subDn) {
self :: need_ldap_con();
if(!LSsession :: setSubDn($ldap_server_subDn))
self :: usage("Fail to select sub DN '$ldap_server_subDn'.");
self :: usage(_("Fail to select sub DN '%s'."), $ldap_server_subDn);
}
if (!$command) {
@ -259,7 +268,7 @@ class LScli extends LSlog_staticLoggerClass {
// Select LDAP server (if not already done with -S/--ldap-server parameter)
if ($ldap_server_id === false && !LSsession :: setLdapServer(0))
self :: log_fatal('Fail to select first LDAP server.');
self :: log_fatal(_('Fail to select first LDAP server.'));
// Run command
self :: run_command($command, $command_args);
@ -379,12 +388,12 @@ class LScli extends LSlog_staticLoggerClass {
**/
public static function confirm($question=null) {
if (is_null($question))
$question = "Are you sure?";
echo "\n$question Type 'yes' to continue: ";
$question = _("Are you sure?");
printf(_("\n%s Type 'yes' to continue: "), $question);
$handle = fopen ("php://stdin","r");
$line = fgets($handle);
if(trim($line) != 'yes'){
echo "User cancel\n";
if(trim($line) != _('yes')){
echo _("User cancel\n");
return false;
}
echo "\n";
@ -456,7 +465,7 @@ class LScli extends LSlog_staticLoggerClass {
$ldap_server_id = intval($comp_words[$i]);
self :: unquote_word($ldap_server_id);
if(!LSsession :: setLdapServer($ldap_server_id))
self :: usage("Fail to select LDAP server #$ldap_server_id.");
self :: usage(_("Fail to select LDAP server #%s."), $ldap_server_id);
}
break;
case '--sub-dn':
@ -476,7 +485,7 @@ class LScli extends LSlog_staticLoggerClass {
self :: unquote_word($ldap_server_subDn);
self :: need_ldap_con();
if(!LSsession :: setSubDn($ldap_server_subDn))
self :: usage("Fail to select sub DN '$ldap_server_subDn'.");
self :: usage(_("Fail to select sub DN '%s'.", $ldap_server_subDn));
break;
case '-L':
case '--load-class':
@ -491,7 +500,7 @@ class LScli extends LSlog_staticLoggerClass {
$class = $comp_words[$i];
self :: unquote_word($class);
if(!LSsession :: loadLSclass($class))
self :: usage("Fail to load class '$class'.");
self :: usage(_("Fail to load class '%s'."), $class);
break;
case '-A':
case '--load-addon':
@ -506,7 +515,7 @@ class LScli extends LSlog_staticLoggerClass {
$addon = $comp_words[$i];
self :: unquote_word($addon);
if(!LSsession :: loadLSaddon($addon))
self :: usage("Fail to load addon '$addon'.");
self :: usage(_("Fail to load addon '%s'."), $addon);
break;
default:
if (!in_array($comp_words[$i], $opts)) {
@ -524,7 +533,7 @@ class LScli extends LSlog_staticLoggerClass {
asort($subDns);
$subDn = key($subDns);
if(!LSsession :: setSubDn($subDn))
self :: usage("Fail to select sub DN '$subDn'.");
self :: usage(_("Fail to select sub DN '%s'."), $subDn);
$opts[] = '--sub-dn';
}
}
@ -852,7 +861,7 @@ ___("LScli : The CLI command '%{command}' handler is not callable.")
LScli :: add_command(
'bash_autocomplete',
array('LScli', 'bash_autocomplete'),
'Handle BASH completion',
___('Handle BASH completion'),
'[arg num to autocomplete] -- [command args]',
null,
false

View file

@ -279,12 +279,16 @@ function _cli_interactive_ask($context, $msg) {
}
// Format question
$empty_action = ($copyoriginalvalue?'copy original message':'pass');
$question ="\"$msg\"\n\n => Please enter translated string";
$question ="\"$msg\"\n\n => "._("Please enter translated string");
$empty_action = (
$copyoriginalvalue?
_("or leave empty to copy original message"):
_("or leave empty to pass")
);
$question .= " (i";
if (!$copyoriginalvalue)
$question .= "/c";
$question .= "/q/? or leave empty to $empty_action): ";
$question .= "/e/q/? $empty_action): ";
while (true) {
if ($context)
@ -303,14 +307,46 @@ function _cli_interactive_ask($context, $msg) {
case 'C': // Copy
if (!$copyoriginalvalue)
return $msg;
case 'e':
case 'E': // Open editor
$tmp_file = tempnam(sys_get_temp_dir(), 'ldapsaisie_translation');
if ($tmp_file === false) {
fwrite(STDERR, _('Fail to create temporary file.'));
break;
}
$fd = fopen($tmp_file, 'w');
if ($fd === false) {
fwrite(STDERR, _('Fail to open temporary file.'));
break;
}
$nb_lines = 1;
if ($context) {
fwrite($fd, "# $context\n");
$nb_lines++;
}
$lines = explode("\n", $msg);
$nb_lines += count($lines);
fwrite($fd, "# ".implode("\n# ", $lines)."\n\n");
fclose($fd);
system("editor +$nb_lines $tmp_file > `tty`", $exit_code);
$result = array();
foreach(file($tmp_file) as $line)
if (!preg_match('/^# /', $line) || $result)
$result[] = preg_replace("/\n$/", "", $line);
unlink($tmp_file);
return implode("\n", $result);
case '?': // Help message
fwrite(STDERR, "Available choices:\n");
fwrite(STDERR, " - i: ignore this message\n");
fwrite(STDERR, _("Available choices:\n"));
fwrite(STDERR, _(" - i: ignore this message\n"));
if (!$copyoriginalvalue)
fwrite(STDERR, " - c: copy original message\n");
fwrite(STDERR, " - q: quit interactive mode and ignore all following untranslated messages\n");
fwrite(STDERR, " - ?: Show this message\n");
fwrite(STDERR, "Or leave empty to $empty_action.\n");
fwrite(STDERR, _(" - c: copy original message\n"));
fwrite(STDERR, _(" - e: translate message in text editor\n"));
fwrite(STDERR, _(" - q: quit interactive mode and ignore all following untranslated messages\n"));
fwrite(STDERR, _(" - ?: Show this message\n"));
if ($copyoriginalvalue)
fwrite(STDERR, _("Or leave empty to copy original message.\n"));
else
fwrite(STDERR, _("Or leave empty to pass.\n"));
break;
case "": // Empty
// On copy orignal value mode, return $msg
@ -719,9 +755,9 @@ function cli_generate_lang_file($command_args) {
$i++;
$without = strtolower($command_args[$i]);
if (!in_array($without, $available_withouts))
LScli :: usage("Invalid -W/--without parameter. Must be one of the following values : '".implode("','", $available_withouts)."'.");
LScli :: usage(_("Invalid -W/--without parameter. Must be one of the following values: %s.'"), implode("','", $available_withouts));
elseif ($only)
LScli :: usage("You could not use only -W/--without parameter combined with -O/--only parameter.");
LScli :: usage(_("You could not use -W/--without parameter combined with -O/--only parameter."));
$withouts[] = $without;
break;
@ -729,12 +765,12 @@ function cli_generate_lang_file($command_args) {
case '-O':
$i++;
if ($only)
LScli :: usage("You could specify only on -O/--only parameter.");
LScli :: usage(_("You could specify only one -O/--only parameter."));
$only = strtolower($command_args[$i]);
if (!in_array($only, $available_onlys))
LScli :: usage("Invalid -O/--only parameter. Must be one of the following values : '".implode("','", $available_onlys)."'.");
LScli :: usage(_("Invalid -O/--only parameter. Must be one of the following values: %s.'"), implode("','", $available_onlys));
elseif ($withouts)
LScli :: usage("You could not use only -O/--only parameter combined with -W/--without parameter.");
LScli :: usage(_("You could not use -W/--without parameter combined with -O/--only parameter."));
break;
case '-I':
@ -766,7 +802,7 @@ function cli_generate_lang_file($command_args) {
$encoding = $parse_lang[1];
}
else {
LScli :: usage("Invalid --lang parameter. Must be compose in format : [lang].[encoding]");
LScli :: usage(_("Invalid -l/--lang parameter. Must be compose in format : [lang].[encoding]"));
}
break;
@ -781,7 +817,7 @@ function cli_generate_lang_file($command_args) {
$i++;
$format = strtolower($command_args[$i]);
if (!in_array($format, $available_formats)) {
LScli :: usage("Invalid -f/--format parameter. Must be one of the following values : '".implode("','", $available_formats)."'.");
LScli :: usage(_("Invalid -f/--format parameter. Must be one of the following values: %s.'"), implode("','", $available_formats));
}
break;
@ -805,7 +841,7 @@ function cli_generate_lang_file($command_args) {
if (is_file($path))
$load_files[] = $path;
else
LScli :: usage($command_args[$i]." : Invalid parameter or lang file to load.");
LScli :: usage(_("%s: Invalid parameter or lang file to load."), $command_args[$i]);
}
}
@ -1097,29 +1133,32 @@ function cli_generate_lang_file_args_autocompleter($comp_words, $comp_word_num,
LScli :: add_command(
'generate_lang_file',
'cli_generate_lang_file',
'Generate lang.php file',
'l [lang] [-o output.file] [file1] [file2] [-h] [options]',
___('Generate lang.php file'),
'-l [lang] [-o output.file] [file1] [file2] [-h] [options]',
array(
" -W/--without Disable specified messages. Must be one of",
" the following values :",
___(
" -W/--without Disable specified messages. Must be one of
the following values:"),
" - ".implode("\n - ", $available_withouts),
" -O/--only Only handle specified messages. Must be one",
" of the following values :",
___(
" -O/--only Only handle specified messages. Must be one
of the following values :"),
" - ".implode("\n - ", $available_onlys),
" -I/--include-upstream Include upstream code to message lookup",
" -c/--copy-original-value Copy original value as translated value when",
" no translated value exists",
" -i/--interactive Interactive mode : ask user to enter",
" translated on each translation needed",
" -a/--additional-file-format Additional file format output",
" -l/--lang Load the specify lang",
" Format: [lang].[encoding]",
" -o/--output Output file (default: stdout)",
" -f/--format Output file format : php or pot",
" (default: php)",
" -K/--keep-unused Keep unused translations in resulting file",
" -F/--fix-utf8 Try to load and fix broken UTF-8 characters in",
" existing lang files."
___(
" -I/--include-upstream Include upstream code to message lookup
-c/--copy-original-value Copy original value as translated value when
no translated value exists
-i/--interactive Interactive mode : ask user to enter
translated on each translation needed
-a/--additional-file-format Additional file format output
-l/--lang Language of the translation
Format: [lang].[encoding]
-o/--output Output file (default: stdout)
-f/--format Output file format : php or pot
(default: php)
-K/--keep-unused Keep unused translations in resulting file
-F/--fix-utf8 Try to load and fix broken UTF-8 characters
in existing lang files.")
),
false, // This command does not need LDAP connection
'cli_generate_lang_file_args_autocompleter'
@ -1210,16 +1249,16 @@ function cli_generate_ldapsaisie_pot($command_args) {
LScli :: add_command(
'generate_ldapsaisie_pot',
'cli_generate_ldapsaisie_pot',
'Generate ldapsaisie.pot files :',
___('Generate POT files:'),
null,
array(
"This command generate 3 POT files:",
___("This command generate 3 POT files:"),
" - ".LS_I18N_DIR_PATH."/ldapsaisie-main.pot",
" => contains messages from PHP files",
___(" => contains messages from PHP files"),
" - ".LS_I18N_DIR_PATH."/ldapsaisie-templates.pot",
" => contains messages from templates files",
___(" => contains messages from templates files"),
" - ".LS_I18N_DIR_PATH."/ldapsaisie.pot",
" => contains all messages",
___(" => contains all messages"),
),
false // This command does not need LDAP connection
);

View file

@ -51,6 +51,14 @@ class LSldap extends LSlog_staticLoggerClass {
*/
private static $cnx = NULL;
/**
* Registered events
* @see self::addEvent()
* @see self::fireEvent()
* @var array
*/
private static $_events = array();
/**
* Set configuration
*
@ -81,12 +89,16 @@ class LSldap extends LSlog_staticLoggerClass {
if ($config) {
self :: setConfig($config);
}
if (!self :: fireEvent('connecting'))
return false;
self :: $cnx = Net_LDAP2::connect(self :: $config);
if (Net_LDAP2::isError(self :: $cnx)) {
self :: fireEvent('connection_failure', array('error' => self :: $cnx -> getMessage()));
LSerror :: addErrorCode('LSldap_01',self :: $cnx -> getMessage());
self :: $cnx = NULL;
return false;
}
self :: fireEvent('connected');
return true;
}
@ -112,12 +124,19 @@ class LSldap extends LSlog_staticLoggerClass {
$config = self :: $config;
$config['binddn'] = $dn;
$config['bindpw'] = $pwd;
if (!self :: fireEvent('reconnecting', array('dn' => $dn)))
return false;
self :: $cnx = Net_LDAP2::connect($config);
if (Net_LDAP2::isError(self :: $cnx)) {
self :: fireEvent(
'reconnection_failure',
array('dn' => $dn, 'error' => self :: $cnx -> getMessage())
);
LSerror :: addErrorCode('LSldap_01', self :: $cnx -> getMessage());
self :: $cnx = NULL;
return false;
}
self :: fireEvent('reconnected', array('dn' => $dn));
return true;
}
@ -134,6 +153,8 @@ class LSldap extends LSlog_staticLoggerClass {
if (!self :: $cnx) {
self :: connect();
}
if (!self :: fireEvent('setting_authz_proxy', array('dn' => $dn)))
return false;
$result = self :: $cnx -> setOption(
'LDAP_OPT_SERVER_CONTROLS',
array (
@ -147,9 +168,11 @@ class LSldap extends LSlog_staticLoggerClass {
// Also check user exists to validate the connection with
// authz proxy control.
if ($result !== True || !self :: exists($dn)) {
self :: fireEvent('setting_authz_proxy_failure', array('dn' => $dn));
LSerror :: addErrorCode('LSldap_09');
return False;
}
self :: fireEvent('set_authz_proxy', array('dn' => $dn));
return True;
}
@ -163,8 +186,11 @@ class LSldap extends LSlog_staticLoggerClass {
* @return void
*/
public static function close() {
if (!self :: fireEvent('closing'))
return;
self :: $cnx -> done();
self :: $cnx = null;
self :: fireEvent('closed');
}
/**
@ -306,6 +332,27 @@ class LSldap extends LSlog_staticLoggerClass {
);
}
/**
* Format a Datetime object as LDAP date string
*
* @param DateTime|null $datetime The DateTime object to format (optional, default: now)
* @param bool $utc Force UTC timezone (optional, default: false)
*
* @return string|false LDAP date string, or false
*/
public static function formatDate($datetime=null, $utc=true) {
if (is_null($datetime))
$datetime = new DateTime('now');
elseif (!$datetime instanceof DateTime)
return false;
$datetime -> setTimezone(timezone_open($utc?'utc':date_default_timezone_get()));
$datetime_string = $datetime -> format('YmdHis.uO');
// Replace +0000 or -0000 end by Z
$datetime_string = preg_replace('/[\+\-]0000$/', 'Z', $datetime_string);
return $datetime_string;
}
/**
* Check if an attribute exists in specified attributes collection
*
@ -333,12 +380,13 @@ class LSldap extends LSlog_staticLoggerClass {
* @param string $name Name of a attribute
* @param boolean $multiple true if we must return array
*
* @return mixed Found value (or array of values) or null
* @return ($multiple is True ? array<int,string> : string|null) Found value (or array of values) or null
*/
public static function getAttr($attrs, $name, $multiple=false) {
$name = strtolower($name);
foreach ($attrs as $k => $v) {
if (strtolower($k) === $name) {
$v = ensureIsArray($v);
return $multiple ? $v : $v[0];
}
}
@ -456,12 +504,12 @@ class LSldap extends LSlog_staticLoggerClass {
*
* @param string $object_type The object type
* @param string $dn DN of the LDAP object
* @param array $change Array of object attributes changes
* @param array $changes Array of object attributes changes
*
* @return boolean True if object was updated, False otherwise.
*/
public static function update($object_type, $dn, $change) {
self :: log_trace("update($object_type, $dn): change=".varDump($change));
public static function update($object_type, $dn, $changes) {
self :: log_trace("update($object_type, $dn): change=".varDump($changes));
// Retrieve current LDAP entry
$entry = self :: getEntry($object_type, $dn);
@ -470,10 +518,18 @@ class LSldap extends LSlog_staticLoggerClass {
return false;
}
if (
!self :: fireEvent(
'updating',
array('object_type' => $object_type, 'dn' => $dn, 'entry' => &$entry, 'changes' => $changes)
)
)
return false;
// Distinguish drop attributes from change attributes
$changed_attrs = array();
$dropped_attrs = array();
foreach($change as $attrName => $attrVal) {
foreach($changes as $attrName => $attrVal) {
$drop = true;
if (is_array($attrVal)) {
foreach($attrVal as $val) {
@ -507,6 +563,9 @@ class LSldap extends LSlog_staticLoggerClass {
}
}
// Keep original entry (to provide to hooks)
$original_entry = clone $entry;
// Handle attributes changes (if need)
if ($changed_attrs) {
@ -521,10 +580,26 @@ class LSldap extends LSlog_staticLoggerClass {
}
if (Net_LDAP2::isError($ret)) {
self :: fireEvent(
'update_failure',
array(
'object_type' => $object_type, 'dn' => $dn,
'original_entry' => &$original_entry, 'entry' => &$entry,
'changes' => $changed_attrs, 'error' => $ret->getMessage()
)
);
LSerror :: addErrorCode('LSldap_05',$dn);
LSerror :: addErrorCode(0,'NetLdap-Error : '.$ret->getMessage());
return false;
}
self :: fireEvent(
'updated',
array(
'object_type' => $object_type, 'dn' => $dn,
'original_entry' => &$original_entry, 'entry' => &$entry,
'changes' => $changed_attrs
)
);
}
elseif ($entry -> isNew()) {
self :: log_error("update($object_type, $dn): no changed attribute but it's a new entry...");
@ -560,10 +635,26 @@ class LSldap extends LSlog_staticLoggerClass {
// Check result
if (Net_LDAP2::isError($ret)) {
self :: fireEvent(
'update_failure',
array(
'object_type' => $object_type, 'dn' => $dn,
'original_entry' => &$original_entry, 'entry' => &$entry,
'changes' => $replace_attrs, 'error' => $ret->getMessage()
)
);
LSerror :: addErrorCode('LSldap_06');
LSerror :: addErrorCode(0,'NetLdap-Error : '.$ret->getMessage());
return false;
}
self :: fireEvent(
'updated',
array(
'object_type' => $object_type, 'dn' => $dn,
'original_entry' => &$original_entry, 'entry' => &$entry,
'changes' => $replace_attrs
)
);
}
return true;
}
@ -606,11 +697,15 @@ class LSldap extends LSlog_staticLoggerClass {
* @return boolean True if object was removed, False otherwise.
*/
public static function remove($dn) {
if (!self :: fireEvent('removing', array('dn' => $dn)))
return false;
$ret = self :: $cnx -> delete($dn,array('recursive' => true));
if (Net_LDAP2::isError($ret)) {
self :: fireEvent('remove_failure', array('dn' => $dn, 'error' => $ret->getMessage()));
LSerror :: addErrorCode(0,'NetLdap-Error : '.$ret->getMessage());
return false;
}
self :: fireEvent('removed', array('dn' => $dn));
return true;
}
@ -623,12 +718,19 @@ class LSldap extends LSlog_staticLoggerClass {
* @return boolean True if object was moved, False otherwise.
*/
public static function move($old, $new) {
if (!self :: fireEvent('moving', array('old' => $old, 'new' => $new)))
return false;
$ret = self :: $cnx -> move($old, $new);
if (Net_LDAP2::isError($ret)) {
self :: fireEvent(
'move_failure',
array('old' => $old, 'new' => $new, 'error' => $ret->getMessage())
);
LSerror :: addErrorCode('LSldap_07');
LSerror :: addErrorCode(0,'NetLdap-Error : '.$ret->getMessage());
return false;
}
self :: fireEvent('moved', array('old' => $old, 'new' => $new));
return true;
}
@ -720,22 +822,63 @@ class LSldap extends LSlog_staticLoggerClass {
_('It is too soon to change the password'),
_('This password was recently used and cannot be used again'),
);
self :: log_debug("update($object_type, $dn): update entry for userPassword");
self :: log_debug("updateUserPassword($object_type, $dn): update entry userPassword attribute");
$changes = array('userPassword' => self :: getAttr($changed_attrs, 'userPassword', true));
if (
!self :: fireEvent(
'user_password_updating',
array(
'object_type' => $object_type, 'dn' => $dn,
'new_passwords' => $changes['userPassword']
)
)
)
return false;
$ldap = self :: $cnx->getLink();
$attr = array('userPassword' => self :: getAttr($changed_attrs, 'userPassword'));
$ctrlRequest = array(array('oid' => LDAP_CONTROL_PASSWORDPOLICYREQUEST));
$r = ldap_mod_replace_ext($ldap, $dn, $attr, $ctrlRequest);
$r = ldap_mod_replace_ext($ldap, $dn, $changes, $ctrlRequest);
if ($r && ldap_parse_result($ldap, $r, $errcode, $matcheddn, $errmsg, $ref, $ctrlResponse)) {
if ($errcode !== 0 && isset($ctrlResponse[LDAP_CONTROL_PASSWORDPOLICYRESPONSE])) {
LSerror :: addErrorCode('LSldap_10', $ppolicyErrorMsg[$ctrlResponse[LDAP_CONTROL_PASSWORDPOLICYRESPONSE]['value']['error']]);
self :: fireEvent(
'user_password_update_failure',
array(
'object_type' => $object_type, 'dn' => $dn,
'error' => $ppolicyErrorMsg[
$ctrlResponse[LDAP_CONTROL_PASSWORDPOLICYRESPONSE]['value']['error']
]
)
);
LSerror :: addErrorCode(
'LSldap_10',
$ppolicyErrorMsg[$ctrlResponse[LDAP_CONTROL_PASSWORDPOLICYRESPONSE]['value']['error']]
);
return false;
}
// If everything OK, remove userPassword to prevent it from being processed by Net_LDAP2
// Password updated
self :: fireEvent(
'user_password_updated',
array(
'object_type' => $object_type, 'dn' => $dn,
'new_passwords' => $changes['userPassword']
)
);
// Remove userPassword to prevent it from being processed by update()
unset($changed_attrs['userPassword']);
} else {
}
else {
self :: fireEvent(
'user_password_update_failure',
array(
'object_type' => $object_type, 'dn' => $dn,
'error' => ldap_errno($ldap) !== 0?ldap_error($ldap):'unknown'
)
);
if (ldap_errno($ldap) !== 0) {
LSerror :: addErrorCode('LSldap_10', ldap_error($ldap));
} else {
}
else {
LSerror :: addErrorCode('LSldap_11');
}
return false;
@ -755,6 +898,66 @@ class LSldap extends LSlog_staticLoggerClass {
private static function getConfig($param, $default=null, $cast=null) {
return LSconfig :: get($param, $default, $cast, self :: $config);
}
/**
* Registered an action on a specific event
*
* @param string $event The event name
* @param callable $callable The callable to run on event
* @param array $params Paremeters that will be pass to the callable
*
* @return void
*/
public static function addEvent($event, $callable, $params=NULL) {
self :: $_events[$event][] = array(
'callable' => $callable,
'params' => is_array($params)?$params:array(),
);
}
/**
* Run triggered actions on specific event
*
* @param string $event Event name
* @param mixed $data Event data
*
* @return boolean True if all triggered actions succefully runned, false otherwise
*/
public static function fireEvent($event, $data=null) {
$return = true;
// Binding via addEvent
if (isset(self :: $_events[$event]) && is_array(self :: $_events[$event])) {
foreach (self :: $_events[$event] as $e) {
if (is_callable($e['callable'])) {
try {
call_user_func_array(
$e['callable'],
array_merge(
array($data), $e['params']
)
);
}
catch(Exception $er) {
LSerror :: addErrorCode(
'LSldap_13',
array('callable' => format_callable($e['callable']), 'event' => $event)
);
$return = false;
}
}
else {
LSerror :: addErrorCode(
'LSldap_12',
array('callable' => format_callable($e['callable']), 'event' => $event)
);
$return = false;
}
}
}
return $return;
}
}
/*
@ -793,3 +996,9 @@ LSerror :: defineError('LSldap_10',
LSerror :: defineError('LSldap_11',
___("LSldap: Unknown LDAP error while updating user password")
);
LSerror :: defineError('LSldap_12',
___("LSldap: Fail to execute trigger %{callable} on event %{event} : is not callable.")
);
LSerror :: defineError('LSldap_13',
___("LSldap: Error during the execution of the trigger %{callable} on event %{event}.")
);

View file

@ -497,13 +497,6 @@ class LSsession {
)
))
return False;
LStemplate :: addHelpInfo(
'LSdefault',
array(
'copy_to_clipboard' => _('Copy to clipboard'),
'copied' => _('Copied!'),
)
);
return True;
}
return False;

View file

@ -416,6 +416,13 @@ class LStemplate extends LSlog_staticLoggerClass {
**/
public static function assignCommonVars() {
// JS config
LStemplate :: addHelpInfo(
'LSdefault',
array(
'copy_to_clipboard' => _('Copy to clipboard'),
'copied' => _('Copied!'),
)
);
LStemplate :: assign('LSjsConfig', base64_encode(json_encode(self :: $JSconfigParams)));
// JS files

View file

@ -405,6 +405,35 @@ function sumDn($dn1,$dn2) {
return $basedn;
}
/**
* Extract and retreive RDN from DN
* @param string $dn
* @param bool $with_attr If true, include the RDN attribute name (optional, default: true)
* @return string|null|false The parent object DN, null if no parent or false in case of error
*/
function getRdn($dn, $with_attr=true) {
$parts = ldap_explode_dn($dn, 0);
if (!is_array($parts) || !isset($parts['count'])) return false;
if ($with_attr)
return $parts[0];
$equal_pos = strpos($parts[0], '=');
if ($equal_pos !== false)
return substr($parts[0], $equal_pos+1);
return $parts[0];
}
/**
* Retreive parent object DN
* @param string $dn
* @return string|null|false The parent object DN, null if no parent or false in case of error
*/
function parentDn($dn) {
$parts = ldap_explode_dn($dn, 0);
if (!is_array($parts) || !isset($parts['count'])) return false;
if ($parts['count'] == 1) return null;
return implode(',', array_slice($parts, 2));
}
function checkEmail($value,$domain=NULL,$checkDns=true) {
$log = LSlog :: get_logger('checkEmail');
$regex = '/^((\"[^\"\f\n\r\t\v\b]+\")|([\w\!\#\$\%\&\'\*\+\-\~\/\^\`\|\{\}]+(\.[\w\!\#\$\%\&\'\*\+\-\~\/\^\`\|\{\}]+)*))@((\[(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))\])|(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))|((([A-Za-z0-9\-])+\.)+[A-Za-z\-]+))$/';
@ -781,3 +810,29 @@ function timestamp2LdapDate($value, $timezone=null, $format=null) {
return dateTime2LdapDate($datetime, $timezone, $format);
return false;
}
/**
* Generate an UUID
* @return string
*/
function generate_uuid() {
return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
// 32 bits for "time_low"
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),
// 16 bits for "time_mid"
mt_rand( 0, 0xffff ),
// 16 bits for "time_hi_and_version",
// four most significant bits holds version number 4
mt_rand( 0, 0x0fff ) | 0x4000,
// 16 bits, 8 bits for "clk_seq_hi_res",
// 8 bits for "clk_seq_low",
// two most significant bits holds zero and one for variant DCE1.1
mt_rand( 0, 0x3fff ) | 0x8000,
// 48 bits for "node"
mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
);
}

View file

@ -76,6 +76,12 @@ var LSdefault = new Class({
this.initializeLang();
document.getElements('.copyable').each(function(el) {
if (el.hasClass('copyable-no-btn')) {
el.addEvent('click', this.onCopyBtnClick.bind(this, {btn: null, element: el}));
el.setStyle('cursor', 'copy');
this.addHelpInfo(el, 'LSdefault', 'copy_to_clipboard');
return;
}
var btn = new Element('img');
btn.setProperties({
src: this.imagePath('copy')

File diff suppressed because it is too large Load diff

View file

@ -217,7 +217,7 @@ msgid "Download"
msgstr ""
#: includes/addons/LSaddons.showSupportInfo.php:78
#: includes/addons/LSaddons.accesslog.php:181
#: includes/addons/LSaddons.accesslog.php:225
#: includes/addons/LSaddons.showTechInfo.php:117
msgid "Go back"
msgstr ""
@ -350,8 +350,8 @@ msgstr ""
msgid "Increment"
msgstr ""
#: includes/addons/LSaddons.accesslog.php:176
#: includes/class/class.LSsession.php:1862 includes/routes.php:157
#: includes/addons/LSaddons.accesslog.php:220
#: includes/class/class.LSsession.php:1855 includes/routes.php:157
#: includes/routes.php:470 templates/default/select.tpl:29
msgid "Refresh"
msgstr ""
@ -390,15 +390,15 @@ msgstr ""
msgid "SUPANN: Fail to load nomenclature %{nomenclature}."
msgstr ""
#: includes/addons/LSaddons.supann.php:376
#: includes/addons/LSaddons.supann.php:447
msgid "Entity %{id} (unrecognized)"
msgstr ""
#: includes/addons/LSaddons.supann.php:448
#: includes/addons/LSaddons.supann.php:519
msgid "Godfather %{dn} (unrecognized)"
msgstr ""
#: includes/addons/LSaddons.supann.php:575
#: includes/addons/LSaddons.supann.php:646
#: includes/class/class.LSformElement_select.php:58
#: includes/class/class.LSformElement_select_object.php:108
msgid "%{value} (unrecognized value)"
@ -740,7 +740,7 @@ msgid ""
msgstr ""
#: includes/class/class.LSformElement.php:262
#: templates/default/showObjectAccessLogs.tpl:28
#: templates/default/showObjectAccessLogs.tpl:29
msgid "Attribute"
msgstr ""
@ -918,6 +918,149 @@ msgstr ""
msgid "Clear selected date."
msgstr ""
#: includes/class/class.LSlang.php:282
msgid "Please enter translated string"
msgstr ""
#: includes/class/class.LSlang.php:285
msgid "or leave empty to copy original message"
msgstr ""
#: includes/class/class.LSlang.php:286
msgid "or leave empty to pass"
msgstr ""
#: includes/class/class.LSlang.php:314
msgid "Fail to create temporary file."
msgstr ""
#: includes/class/class.LSlang.php:319
msgid "Fail to open temporary file."
msgstr ""
#: includes/class/class.LSlang.php:339
msgid "Available choices:\n"
msgstr ""
#: includes/class/class.LSlang.php:340
msgid " - i: ignore this message\n"
msgstr ""
#: includes/class/class.LSlang.php:342
msgid " - c: copy original message\n"
msgstr ""
#: includes/class/class.LSlang.php:343
msgid " - e: translate message in text editor\n"
msgstr ""
#: includes/class/class.LSlang.php:344
msgid ""
" - q: quit interactive mode and ignore all following untranslated messages\n"
msgstr ""
#: includes/class/class.LSlang.php:345
msgid " - ?: Show this message\n"
msgstr ""
#: includes/class/class.LSlang.php:347
msgid "Or leave empty to copy original message.\n"
msgstr ""
#: includes/class/class.LSlang.php:349
msgid "Or leave empty to pass.\n"
msgstr ""
#: includes/class/class.LSlang.php:758
#, php-format
msgid ""
"Invalid -W/--without parameter. Must be one of the following values: %s.'"
msgstr ""
#: includes/class/class.LSlang.php:760 includes/class/class.LSlang.php:773
msgid ""
"You could not use -W/--without parameter combined with -O/--only parameter."
msgstr ""
#: includes/class/class.LSlang.php:768
msgid "You could specify only one -O/--only parameter."
msgstr ""
#: includes/class/class.LSlang.php:771
#, php-format
msgid "Invalid -O/--only parameter. Must be one of the following values: %s.'"
msgstr ""
#: includes/class/class.LSlang.php:805
msgid ""
"Invalid -l/--lang parameter. Must be compose in format : [lang].[encoding]"
msgstr ""
#: includes/class/class.LSlang.php:820
#, php-format
msgid ""
"Invalid -f/--format parameter. Must be one of the following values: %s.'"
msgstr ""
#: includes/class/class.LSlang.php:844
#, php-format
msgid "%s: Invalid parameter or lang file to load."
msgstr ""
#: includes/class/class.LSlang.php:1136
msgid "Generate lang.php file"
msgstr ""
#: includes/class/class.LSlang.php:1140
msgid ""
" -W/--without Disable specified messages. Must be one of\n"
" the following values:"
msgstr ""
#: includes/class/class.LSlang.php:1144
msgid ""
" -O/--only Only handle specified messages. Must be one\n"
" of the following values :"
msgstr ""
#: includes/class/class.LSlang.php:1148
msgid ""
" -I/--include-upstream Include upstream code to message lookup\n"
" -c/--copy-original-value Copy original value as translated value when\n"
" no translated value exists\n"
" -i/--interactive Interactive mode : ask user to enter\n"
" translated on each translation needed\n"
" -a/--additional-file-format Additional file format output\n"
" -l/--lang Language of the translation\n"
" Format: [lang].[encoding]\n"
" -o/--output Output file (default: stdout)\n"
" -f/--format Output file format : php or pot\n"
" (default: php)\n"
" -K/--keep-unused Keep unused translations in resulting file\n"
" -F/--fix-utf8 Try to load and fix broken UTF-8 characters\n"
" in existing lang files."
msgstr ""
#: includes/class/class.LSlang.php:1252
msgid "Generate POT files:"
msgstr ""
#: includes/class/class.LSlang.php:1255
msgid "This command generate 3 POT files:"
msgstr ""
#: includes/class/class.LSlang.php:1257
msgid " => contains messages from PHP files"
msgstr ""
#: includes/class/class.LSlang.php:1259
msgid " => contains messages from templates files"
msgstr ""
#: includes/class/class.LSlang.php:1261
msgid " => contains all messages"
msgstr ""
#: includes/class/class.LStemplate.php:160
msgid "LStemplate : compile directory is not writable (dir : %{dir})"
msgstr ""
@ -944,38 +1087,46 @@ msgid ""
"upgrade documentation to adapt your templates."
msgstr ""
#: includes/class/class.LStemplate.php:478
#: includes/class/class.LStemplate.php:422
msgid "Copy to clipboard"
msgstr ""
#: includes/class/class.LStemplate.php:423
msgid "Copied!"
msgstr ""
#: includes/class/class.LStemplate.php:485
msgid "Smarty - An exception occured displaying template '%{template}'"
msgstr ""
#: includes/class/class.LStemplate.php:498
#: includes/class/class.LStemplate.php:505
msgid "Smarty - An exception occured fetching template '%{template}'"
msgstr ""
#: includes/class/class.LStemplate.php:514
#: includes/class/class.LStemplate.php:528
#: includes/class/class.LStemplate.php:521
#: includes/class/class.LStemplate.php:535
msgid "A fatal error occured. If problem persist, please contact support."
msgstr ""
#: includes/class/class.LStemplate.php:524
#: includes/class/class.LStemplate.php:531
msgid "<h1>Loop detected displaying this error:</h1><pre>%{error}</pre>"
msgstr ""
#: includes/class/class.LStemplate.php:527
#: includes/class/class.LStemplate.php:534
msgid "A fatal error occured."
msgstr ""
#: includes/class/class.LStemplate.php:724
#: includes/class/class.LStemplate.php:731
msgid "LStemplate : Template %{file} not found."
msgstr ""
#: includes/class/class.LStemplate.php:727
#: includes/class/class.LStemplate.php:734
msgid ""
"LStemplate : Fail to execute trigger %{callable} on event %{event} : is not "
"callable."
msgstr ""
#: includes/class/class.LStemplate.php:730
#: includes/class/class.LStemplate.php:737
msgid ""
"LStemplate : Error during the execution of the trigger %{callable} on event "
"%{event}."
@ -1123,165 +1274,157 @@ msgstr ""
msgid "Clear"
msgstr ""
#: includes/class/class.LSsession.php:503
msgid "Copy to clipboard"
msgstr ""
#: includes/class/class.LSsession.php:504
msgid "Copied!"
msgstr ""
#: includes/class/class.LSsession.php:1647
#: includes/class/class.LSsession.php:1640
msgid "Connection"
msgstr ""
#: includes/class/class.LSsession.php:1667
#: includes/class/class.LSsession.php:1660
msgid "Recovery of your credentials"
msgstr ""
#: includes/class/class.LSsession.php:1676
#: includes/class/class.LSsession.php:1669
msgid "Please fill the identifier field to proceed recovery procedure"
msgstr ""
#: includes/class/class.LSsession.php:1681
#: includes/class/class.LSsession.php:1674
msgid ""
"An email has been sent to %{mail}. Please follow the instructions on it."
msgstr ""
#: includes/class/class.LSsession.php:1690
#: includes/class/class.LSsession.php:1683
msgid "Your new password has been sent to %{mail}."
msgstr ""
#: includes/class/class.LSsession.php:2952 templates/default/select.tpl:20
#: includes/class/class.LSsession.php:2945 templates/default/select.tpl:20
#: templates/default/recoverpassword.tpl:17 templates/default/login.tpl:16
msgid "Level"
msgstr ""
#: includes/class/class.LSsession.php:3120
#: includes/class/class.LSsession.php:3113
msgid "LSsession : The constant '%{const}' is not defined."
msgstr ""
#: includes/class/class.LSsession.php:3123
#: includes/class/class.LSsession.php:3116
msgid ""
"LSsession : The addon '%{addon}' support is uncertain. Verify system "
"compatibility and the add-on configuration."
msgstr ""
#: includes/class/class.LSsession.php:3126
#: includes/class/class.LSsession.php:3119
msgid ""
"LSsession : LDAP server's configuration data are invalid. Can't connect."
msgstr ""
#: includes/class/class.LSsession.php:3129
#: includes/class/class.LSsession.php:3122
msgid "LSsession : Failed to load LSobject type '%{type}' : unknon type."
msgstr ""
#: includes/class/class.LSsession.php:3132
#: includes/class/class.LSsession.php:3125
msgid "LSsession : Failed to load LSclass '%{class}'."
msgstr ""
#: includes/class/class.LSsession.php:3135
#: includes/class/class.LSsession.php:3128
msgid "LSsession : Login or password incorrect."
msgstr ""
#: includes/class/class.LSsession.php:3138
#: includes/class/class.LSsession.php:3131
msgid "LSsession : Impossible to identify you : Duplication of identities."
msgstr ""
#: includes/class/class.LSsession.php:3141
#: includes/class/class.LSsession.php:3134
msgid "LSsession : Can't load class of authentification (%{class})."
msgstr ""
#: includes/class/class.LSsession.php:3144
#: includes/class/class.LSsession.php:3137
msgid "LSsession : Can't connect to LDAP server."
msgstr ""
#: includes/class/class.LSsession.php:3147
#: includes/class/class.LSsession.php:3140
msgid "LSsession : Impossible to authenticate you."
msgstr ""
#: includes/class/class.LSsession.php:3150
#: includes/class/class.LSsession.php:3143
msgid "LSsession : Your are not authorized to do this action."
msgstr ""
#: includes/class/class.LSsession.php:3153
#: includes/class/class.LSsession.php:3146
msgid "LSsession : Some informations are missing to display this page."
msgstr ""
#: includes/class/class.LSsession.php:3156
#: includes/class/class.LSsession.php:3149
msgid ""
"LSsession : The function '%{function}' of the custom action "
"'%{customAction}' does not exists or is not configured."
msgstr ""
#: includes/class/class.LSsession.php:3159
#: includes/class/class.LSsession.php:3152
msgid "LSsession : Fail to retrieve user's LDAP credentials from LSauth."
msgstr ""
#: includes/class/class.LSsession.php:3162
#: includes/class/class.LSsession.php:3155
msgid ""
"LSsession : Fail to reconnect to LDAP server with user's LDAP credentials."
msgstr ""
#: includes/class/class.LSsession.php:3165
#: includes/class/class.LSsession.php:3158
msgid "LSsession : No import/export format define for this object type."
msgstr ""
#: includes/class/class.LSsession.php:3168
#: includes/class/class.LSsession.php:3161
msgid ""
"LSsession : Error during creation of list of levels. Contact administrators. "
"(Code : %{code})"
msgstr ""
#: includes/class/class.LSsession.php:3171
#: includes/class/class.LSsession.php:3164
msgid "LSsession : The password recovery is disabled for this LDAP server."
msgstr ""
#: includes/class/class.LSsession.php:3174
#: includes/class/class.LSsession.php:3167
msgid ""
"LSsession : Some informations are missing to recover your password. Contact "
"administrators."
msgstr ""
#: includes/class/class.LSsession.php:3177
#: includes/class/class.LSsession.php:3170
msgid ""
"LSsession : Error during password recovery. Contact administrators.(Step : "
"%{step})"
msgstr ""
#: includes/class/class.LSsession.php:3180
#: includes/class/class.LSsession.php:3173
msgid ""
"LSsession : The function '%{func}' configured for the view '%{view}' of the "
"LSaddon '%{addon}' is not declared in the LSaddon file."
msgstr ""
#: includes/class/class.LSsession.php:3183
#: includes/class/class.LSsession.php:3176
msgid "LSsession : Failed to load resource file '%{file}'."
msgstr ""
#: includes/class/class.LSsession.php:3186
#: includes/class/class.LSsession.php:3179
msgid ""
"LSsession : The function '%{func}' configured for the view '%{view}' of the "
"LSaddon '%{addon}' doesn't exist."
msgstr ""
#: includes/class/class.LSsession.php:3189
#: includes/class/class.LSsession.php:3182
msgid "LSsession : invalid related object's DN pass in parameter."
msgstr ""
#: includes/class/class.LSsession.php:3192
#: includes/class/class.LSsession.php:3185
msgid ""
"LSsession : the LSaddon %{addon} keep using old-style addon view URL. Please "
"upgrade it."
msgstr ""
#: includes/class/class.LSsession.php:3195
#: includes/class/class.LSsession.php:3188
msgid ""
"LSsession : You have been redirect from an old-style URL %{url}. Please "
"upgrade this link."
msgstr ""
#: includes/class/class.LSsession.php:3198
#: includes/class/class.LSsession.php:3191
msgid ""
"LSsession : You always seem to use %{old} in your custom code: Please "
"upgrade it and use %{new}.<pre>\n"
@ -1294,199 +1437,199 @@ msgstr ""
msgid "Invalid file type (%{type})."
msgstr ""
#: includes/class/class.LSldapObject.php:566
#: includes/class/class.LSldapObject.php:577
msgid "The attribute %{attr} is not valid."
msgstr ""
#: includes/class/class.LSldapObject.php:3139
#: includes/class/class.LSldapObject.php:3150
msgid "LSldapObject : Object type unknown."
msgstr ""
#: includes/class/class.LSldapObject.php:3142
#: includes/class/class.LSldapObject.php:3153
msgid "LSldapObject : Update form is not defined for the object %{obj}."
msgstr ""
#: includes/class/class.LSldapObject.php:3145
#: includes/class/class.LSldapObject.php:3156
msgid "LSldapObject : No form exists for the object %{obj}."
msgstr ""
#: includes/class/class.LSldapObject.php:3148
#: includes/class/class.LSldapObject.php:3159
msgid ""
"LSldapObject : The function %{func} to validate the attribute %{attr} the "
"object %{obj} is unknow."
msgstr ""
#: includes/class/class.LSldapObject.php:3151
#: includes/class/class.LSldapObject.php:3162
msgid ""
"LSldapObject : Configuration data are missing to validate the attribute "
"%{attr} of the object %{obj}."
msgstr ""
#: includes/class/class.LSldapObject.php:3155
#: includes/class/class.LSldapObject.php:3166
msgid ""
"LSldapObject : The function %{func} to be executed on the object event "
"%{event} doesn't exist."
msgstr ""
#: includes/class/class.LSldapObject.php:3158
#: includes/class/class.LSldapObject.php:3169
msgid ""
"LSldapObject : The %{func} execution on the object event %{event} failed."
msgstr ""
#: includes/class/class.LSldapObject.php:3162
#: includes/class/class.LSldapObject.php:3173
msgid ""
"LSldapObject : Class %{class}, which method %{meth} to be executed on the "
"object event %{event}, doesn't exist."
msgstr ""
#: includes/class/class.LSldapObject.php:3165
#: includes/class/class.LSldapObject.php:3176
msgid ""
"LSldapObject : Method %{meth} within %{class} class to be executed on object "
"event %{event}, doesn't exist."
msgstr ""
#: includes/class/class.LSldapObject.php:3168
#: includes/class/class.LSldapObject.php:3179
msgid ""
"LSldapObject : Error during execute %{meth} method within %{class} class, to "
"be executed on object event %{event}."
msgstr ""
#: includes/class/class.LSldapObject.php:3172
#: includes/class/class.LSldapObject.php:3183
msgid ""
"LSldapObject : Some configuration data of the object type %{obj} are missing "
"to generate the DN of the new object."
msgstr ""
#: includes/class/class.LSldapObject.php:3175
#: includes/class/class.LSldapObject.php:3186
msgid ""
"LSldapObject : The attibute %{attr} of the object is not yet defined. Can't "
"generate DN."
msgstr ""
#: includes/class/class.LSldapObject.php:3178
#: includes/class/class.LSldapObject.php:3189
msgid "LSldapObject : Without DN, the object could not be changed."
msgstr ""
#: includes/class/class.LSldapObject.php:3181
#: includes/class/class.LSldapObject.php:3192
msgid ""
"LSldapObject : The attribute %{attr_depend} depending on the attribute "
"%{attr} doesn't exist."
msgstr ""
#: includes/class/class.LSldapObject.php:3184
#: includes/class/class.LSldapObject.php:3195
msgid "LSldapObject : Error during deleting the object %{objectname}."
msgstr ""
#: includes/class/class.LSldapObject.php:3188
#: includes/class/class.LSldapObject.php:3199
msgid ""
"LSldapObject : Error during actions to be executed before renaming the objet."
msgstr ""
#: includes/class/class.LSldapObject.php:3191
#: includes/class/class.LSldapObject.php:3202
msgid ""
"LSldapObject : Error during actions to be executed after renaming the objet."
msgstr ""
#: includes/class/class.LSldapObject.php:3195
#: includes/class/class.LSldapObject.php:3206
msgid ""
"LSldapObject : Error during actions to be executed before deleting the objet."
msgstr ""
#: includes/class/class.LSldapObject.php:3198
#: includes/class/class.LSldapObject.php:3209
msgid ""
"LSldapObject : Error during actions to be executed after deleting the objet."
msgstr ""
#: includes/class/class.LSldapObject.php:3202
#: includes/class/class.LSldapObject.php:3213
msgid ""
"LSldapObject : Error during the actions to be executed before creating the "
"object."
msgstr ""
#: includes/class/class.LSldapObject.php:3205
#: includes/class/class.LSldapObject.php:3216
msgid ""
"LSldapObject : Error during the actions to be executed after creating the "
"object. It was created anyway."
msgstr ""
#: includes/class/class.LSldapObject.php:3209
#: includes/class/class.LSldapObject.php:3220
msgid ""
"LSldapObject : The function %{func} to be executed before creating the "
"object doesn't exist."
msgstr ""
#: includes/class/class.LSldapObject.php:3212
#: includes/class/class.LSldapObject.php:3223
msgid ""
"LSldapObject : Error executing the function %{func} to be execute after "
"deleting the object."
msgstr ""
#: includes/class/class.LSldapObject.php:3215
#: includes/class/class.LSldapObject.php:3226
msgid ""
"LSldapObject : The function %{func} to be executed after deleting the object "
"doesn't exist."
msgstr ""
#: includes/class/class.LSldapObject.php:3218
#: includes/class/class.LSldapObject.php:3229
msgid ""
"LSldapObject : Error executing the function %{func} to be execute after "
"creating the object."
msgstr ""
#: includes/class/class.LSldapObject.php:3222
#: includes/class/class.LSldapObject.php:3233
msgid ""
"LSldapObject : %{func} function, to be executed on object event %{event}, "
"doesn't exist."
msgstr ""
#: includes/class/class.LSldapObject.php:3225
#: includes/class/class.LSldapObject.php:3236
msgid ""
"LSldapObject : Error during the execution of %{func} function on object "
"event %{event}."
msgstr ""
#: includes/class/class.LSldapObject.php:3229
#: includes/class/class.LSldapObject.php:3240
msgid ""
"LSldapObject : %{meth} method, to be executed on object event %{event}, "
"doesn't exist."
msgstr ""
#: includes/class/class.LSldapObject.php:3232
#: includes/class/class.LSldapObject.php:3243
msgid ""
"LSldapObject : Error during execution of %{meth} method on object event "
"%{event}."
msgstr ""
#: includes/class/class.LSldapObject.php:3235
#: includes/class/class.LSldapObject.php:3246
msgid "LSldapObject : Error during generate LDAP filter for %{LSobject}."
msgstr ""
#: includes/class/class.LSldapObject.php:3239
#: includes/class/class.LSldapObject.php:3250
msgid ""
"LSldapObject : Error during execution of the custom action %{customAction} "
"on %{objectname}."
msgstr ""
#: includes/class/class.LSldapObject.php:3243
#: includes/class/class.LSldapObject.php:3254
msgid "LSldapObject : Fail to retrieve container DN."
msgstr ""
#: includes/class/class.LSldapObject.php:3246
#: includes/class/class.LSldapObject.php:3257
msgid ""
"LSldapObject : The function %{func} to generate container DN is not callable."
msgstr ""
#: includes/class/class.LSldapObject.php:3249
#: includes/class/class.LSldapObject.php:3260
msgid "LSldapObject : Error during generating container DN : %{error}"
msgstr ""
#: includes/class/class.LSldapObject.php:3252
#: includes/class/class.LSldapObject.php:3263
msgid ""
"LSldapObject : An LDAP object with the same DN as generated for this new one "
"already exists. Please verify your configuration."
msgstr ""
#: includes/class/class.LSldapObject.php:3257
#: includes/class/class.LSldapObject.php:3268
msgid ""
"LSrelation : Some parameters are missing in the call of methods to handle "
"standard relations (Method : %{meth})."
@ -1516,86 +1659,98 @@ msgid ""
"(begining by '/' caracter)."
msgstr ""
#: includes/class/class.LSldap.php:713
#: includes/class/class.LSldap.php:815
msgid "The password expired"
msgstr ""
#: includes/class/class.LSldap.php:714
#: includes/class/class.LSldap.php:816
msgid "The account is locked"
msgstr ""
#: includes/class/class.LSldap.php:715
#: includes/class/class.LSldap.php:817
msgid "The password was reset and must be changed"
msgstr ""
#: includes/class/class.LSldap.php:716
#: includes/class/class.LSldap.php:818
msgid "It is not possible to modify the password"
msgstr ""
#: includes/class/class.LSldap.php:717
#: includes/class/class.LSldap.php:819
msgid "The old password must be supplied"
msgstr ""
#: includes/class/class.LSldap.php:718
#: includes/class/class.LSldap.php:820
msgid "The password does not meet the quality requirements"
msgstr ""
#: includes/class/class.LSldap.php:719
#: includes/class/class.LSldap.php:821
msgid "The password is too short"
msgstr ""
#: includes/class/class.LSldap.php:720
#: includes/class/class.LSldap.php:822
msgid "It is too soon to change the password"
msgstr ""
#: includes/class/class.LSldap.php:721
#: includes/class/class.LSldap.php:823
msgid "This password was recently used and cannot be used again"
msgstr ""
#: includes/class/class.LSldap.php:764
#: includes/class/class.LSldap.php:967
msgid "LSldap: Error during the LDAP server connection (%{msg})."
msgstr ""
#: includes/class/class.LSldap.php:767
#: includes/class/class.LSldap.php:970
msgid "LSldap: Error during the LDAP search (%{msg})."
msgstr ""
#: includes/class/class.LSldap.php:770
#: includes/class/class.LSldap.php:973
msgid "LSldap: Object type unknown."
msgstr ""
#: includes/class/class.LSldap.php:773
#: includes/class/class.LSldap.php:976
msgid "LSldap: Error while fetching the LDAP entry."
msgstr ""
#: includes/class/class.LSldap.php:776
#: includes/class/class.LSldap.php:979
msgid "LSldap: Error while changing the LDAP entry (DN : %{dn})."
msgstr ""
#: includes/class/class.LSldap.php:779
#: includes/class/class.LSldap.php:982
msgid "LSldap: Error while deleting empty attributes."
msgstr ""
#: includes/class/class.LSldap.php:782
#: includes/class/class.LSldap.php:985
msgid "LSldap: Error while changing the DN of the object."
msgstr ""
#: includes/class/class.LSldap.php:785
#: includes/class/class.LSldap.php:988
msgid "LSldap: LDAP server base DN not configured."
msgstr ""
#: includes/class/class.LSldap.php:788
#: includes/class/class.LSldap.php:991
msgid "LSldap: Fail to set authz proxy option on LDAP server connection."
msgstr ""
#: includes/class/class.LSldap.php:791
#: includes/class/class.LSldap.php:994
msgid "LSldap: Error while changing the user password: %{msg}."
msgstr ""
#: includes/class/class.LSldap.php:794
#: includes/class/class.LSldap.php:997
msgid "LSldap: Unknown LDAP error while updating user password"
msgstr ""
#: includes/class/class.LSldap.php:1000
msgid ""
"LSldap: Fail to execute trigger %{callable} on event %{event} : is not "
"callable."
msgstr ""
#: includes/class/class.LSldap.php:1003
msgid ""
"LSldap: Error during the execution of the trigger %{callable} on event "
"%{event}."
msgstr ""
#: includes/class/class.LSformRule_ldapSearchURI.php:59
msgid "Invalid LDAP server URI (%{uri})"
msgstr ""
@ -2403,20 +2558,100 @@ msgstr ""
msgid "Role"
msgstr ""
#: includes/class/class.LScli.php:218
#: includes/class/class.LScli.php:104
#, php-format
msgid ""
"Invalid parameter \"%{parameter}\".\n"
"Usage: %s [-h] [-qdC] command\n"
" -h Show this message\n"
" -q|--quiet Quiet mode: nothing log on console (but keep other "
"logging handler)\n"
" -d|--debug Debug mode (set log level to DEBUG, default: WARNING)\n"
" -v|--verbose Verbose mode (set log level to INFO, default: WARNING)\n"
" --trace Trace mode (set log level to TRACE, default: WARNING)\n"
" -C|--console Log on console with same log level as other handlers "
"(otherwise, log only errors)\n"
" -S|--ldap-server Connect to a specific LDAP server: you could specify a "
"LDAP\n"
" server by its declaration order in configuration "
"(default:\n"
" first one).\n"
" -L|--load-class Load specific class to permit access to its CLI "
"commands\n"
" -A|--load-addons Load specific addon to permit access to its CLI "
"commands\n"
" command Command to run\n"
"\n"
" Available commands:\n"
msgstr ""
#: includes/class/class.LScli.php:136
msgid "Currently no available command is declared."
msgstr ""
#: includes/class/class.LScli.php:197 includes/class/class.LScli.php:468
#, php-format
msgid "Fail to select LDAP server #%s."
msgstr ""
#: includes/class/class.LScli.php:208 includes/class/class.LScli.php:503
#, php-format
msgid "Fail to load class '%s'."
msgstr ""
#: includes/class/class.LScli.php:215 includes/class/class.LScli.php:518
#, php-format
msgid "Fail to load addon '%s'."
msgstr ""
#: includes/class/class.LScli.php:226
#, php-format
msgid ""
"Invalid parameter \"%s\".\n"
"Note: Command's parameter/argument must be place after the command."
msgstr ""
#: includes/class/class.LScli.php:843
#: includes/class/class.LScli.php:261 includes/class/class.LScli.php:488
#: includes/class/class.LScli.php:536
#, php-format
msgid "Fail to select sub DN '%s'."
msgstr ""
#: includes/class/class.LScli.php:271
msgid "Fail to select first LDAP server."
msgstr ""
#: includes/class/class.LScli.php:391
msgid "Are you sure?"
msgstr ""
#: includes/class/class.LScli.php:392
#, php-format
msgid ""
"\n"
"%s Type 'yes' to continue: "
msgstr ""
#: includes/class/class.LScli.php:395 templates/default/import.tpl:26
#: templates/default/import.tpl:32
msgid "yes"
msgstr ""
#: includes/class/class.LScli.php:396
msgid "User cancel\n"
msgstr ""
#: includes/class/class.LScli.php:852
msgid "LScli : The CLI command '%{command}' already exists."
msgstr ""
#: includes/class/class.LScli.php:846
#: includes/class/class.LScli.php:855
msgid "LScli : The CLI command '%{command}' handler is not callable."
msgstr ""
#: includes/class/class.LScli.php:864
msgid "Handle BASH completion"
msgstr ""
#: includes/class/class.LSioFormatCSV.php:294
msgid "LSioFormatCSV: function fputcsv is not available."
msgstr ""
@ -2797,7 +3032,7 @@ msgstr ""
msgid "Nb / page :"
msgstr ""
#: templates/default/showObjectAccessLogs.tpl:70
#: templates/default/showObjectAccessLogs.tpl:71
msgid "No access log found for this object."
msgstr ""
@ -2817,7 +3052,7 @@ msgstr ""
msgid "Object classes"
msgstr ""
#: templates/default/showObjectAccessLogs.tpl:31
#: templates/default/showObjectAccessLogs.tpl:30
msgid "Old value(s)"
msgstr ""
@ -2826,7 +3061,7 @@ msgid "Only validate data"
msgstr ""
#: templates/default/showObjectAccessLogs.tpl:11
#: templates/default/showObjectAccessLogs.tpl:29
#: templates/default/showObjectAccessLogs.tpl:28
msgid "Operation"
msgstr ""
@ -2930,18 +3165,14 @@ msgstr ""
msgid "Valid"
msgstr ""
#: templates/default/showObjectAccessLogs.tpl:30
#: templates/default/showObjectAccessLogs.tpl:31
msgid "Value"
msgstr ""
#: templates/default/showObjectAccessLogs.tpl:75
#: templates/default/showObjectAccessLogs.tpl:76
msgid "event(s) found for this object."
msgstr ""
#: templates/default/import.tpl:27 templates/default/import.tpl:33
msgid "no"
msgstr ""
#: templates/default/import.tpl:26 templates/default/import.tpl:32
msgid "yes"
msgstr ""

View file

@ -3,7 +3,7 @@
<h1>{$pagetitle}</h1>
{include file='ls:LSview_actions.tpl'}
<table class='LStable'>
<table class='LStable objectAccessLogs'>
<thead>
<tr>
<th>{tr msg="Date"}</th>
@ -22,23 +22,23 @@
<td class="center">{$log.result}{if $log.message} <img class='LStips' src="{img name='help'}" alt="?" title='{$log.message|escape:quotes}'/>{/if}</td>
<td>
{if $log.mods}
<table style='margin: auto'>
<table class="mods">
<thead>
<tr>
<th>{tr msg="Attribute"}</th>
<th>{tr msg="Operation"}</th>
<th>{tr msg="Value"}</th>
<th>{tr msg="Old value(s)"}</th>
<th class="col-op">{tr msg="Operation"}</th>
<th class="col-attr">{tr msg="Attribute"}</th>
<th class="col-value">{tr msg="Old value(s)"}</th>
<th class="col-value">{tr msg="Value"}</th>
</tr>
</thead>
<tbody>
{foreach $log.mods as $attr => $info}
<tr>
<td class="center" {if count($info.changes)>1}rowspan={$info.changes|count}{/if}>{$attr}</td>
<td class="center">{$info.changes.0.op|escape:htmlall}</td>
<td>{$info.changes.0.value|escape:htmlall}</td>
<td {if count($info.changes)>1}rowspan={$info.changes|count}{/if}>
<td class="col-op center" {if count($info.changes)>1}rowspan={$info.changes|count}{/if}>{$info.changes.0.op|escape:htmlall}</td>
<td class="col-attr center" {if count($info.changes)>1}rowspan={$info.changes|count}{/if}>{$attr}</td>
<td class="col-value" {if count($info.changes)>1}rowspan={$info.changes|count}{/if}>
{if $info.old_values}
<div class="copyable copyable-no-btn">
{if count($info.old_values) == 1}
{$info.old_values[0]|escape:'htmlall'}
{else}
@ -48,14 +48,15 @@
{/foreach}
</ul>
{/if}
</div>
{/if}
</td>
<td class="col-value"><div class="copyable copyable-no-btn">{$info.changes.0.value|escape:htmlall}</div></td>
</tr>
{if count($info.changes) > 1}
{section name=change loop=$info.changes step=1 start=1}
<tr>
<td>{$info.changes[change].op|escape:htmlall}</td>
<td>{$info.changes[change].value|escape:htmlall}</td>
<td class="col-value"><div class="copyable copyable-no-btn">{$info.changes[change].value|escape:htmlall}</div></td>
</tr>
{/section}
{/if}