LEMONLDAP::NG : i18n in Manager syntax error check

environments/ppa-mbqj77/deployments/1
Xavier Guimard 18 years ago
parent 0873d646c1
commit b666dff5ab
  1. 14
      build/lemonldap-ng/doc/install-fr.html
  2. 13
      build/lemonldap-ng/doc/install.html
  3. 17
      modules/lemonldap-ng-manager/MANIFEST
  4. 62
      modules/lemonldap-ng-manager/lib/Lemonldap/NG/Manager.pm
  5. 276
      modules/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/_i18n.pm
  6. 0
      modules/lemonldap-ng-manager/t/01-Manager-Conf.t
  7. 0
      modules/lemonldap-ng-manager/t/02-Manager-Conf-File.t
  8. 0
      modules/lemonldap-ng-manager/t/03-Manager-Conf-DBI.t
  9. 0
      modules/lemonldap-ng-manager/t/04-Manager-Conf-SOAP.t
  10. 0
      modules/lemonldap-ng-manager/t/10-Manager.t
  11. 24
      modules/lemonldap-ng-manager/t/20-Manager-i18n.t
  12. 0
      modules/lemonldap-ng-manager/t/21-Manager-i18n-en.t
  13. 0
      modules/lemonldap-ng-manager/t/22-Manager-i18n-fr.t
  14. 0
      modules/lemonldap-ng-manager/t/50-Manager-SOAPServer.t

@ -110,6 +110,20 @@ $ sudo dpkg -i ../lemonldap-ng*.deb
</pre>
</div>
<p class="paragraph"></p>Vous pouvez &eacute;galement utiliser le
repository Debian:
<p class="paragraph"></p>
<div class="code">
<pre>
deb <span class="nobr"><a href=
"http://lemonldap.objectweb.org/NG/debian">http://lemonldap.objectweb.org/NG/debian</a></span> testing/
deb-src <span class="nobr"><a href=
"http://lemonldap.objectweb.org/NG/debian">http://lemonldap.objectweb.org/NG/debian</a></span> testing/
</pre>
</div>
<h3 class="heading-1-1"><span id=
"HCONFIGURATIONDEL27EXEMPLE">CONFIGURATION DE L'EXEMPLE</span></h3>

@ -104,6 +104,19 @@ $ sudo dpkg -i ../lemonldap-ng*.deb
</pre>
</div>
<p class="paragraph"></p>You can also use the Debian repository :
<p class="paragraph"></p>
<div class="code">
<pre>
deb <span class="nobr"><a href=
"http://lemonldap.objectweb.org/NG/debian">http://lemonldap.objectweb.org/NG/debian</a></span> testing/
deb-src <span class="nobr"><a href=
"http://lemonldap.objectweb.org/NG/debian">http://lemonldap.objectweb.org/NG/debian</a></span> testing/
</pre>
</div>
<h3 class="heading-1-1"><span id="HEXAMPLECONFIGURATION">EXAMPLE
CONFIGURATION</span></h3>

@ -69,12 +69,13 @@ MANIFEST
META.yml Module meta-data (added by MakeMaker)
README
scripts/lmConfig_File2MySQL
t/Lemonldap-NG-Manager-Conf-DBI.t
t/Lemonldap-NG-Manager-Conf-File.t
t/Lemonldap-NG-Manager-Conf-SOAP.t
t/Lemonldap-NG-Manager-Conf.t
t/Lemonldap-NG-Manager-SOAPServer.t
t/Lemonldap-NG-Manager.t
t/Lemonldap-NG-Manager_en.t
t/Lemonldap-NG-Manager_fr.t
t/01-Manager-Conf.t
t/02-Manager-Conf-File.t
t/03-Manager-Conf-DBI.t
t/04-Manager-Conf-SOAP.t
t/10-Manager.t
t/20-Manager-i18n.t
t/21-Manager-i18n-en.t
t/22-Manager-i18n-fr.t
t/50-Manager-SOAPServer.t
TODO

@ -428,26 +428,22 @@ sub checkConf {
# Check cookie name
unless( $config->{cookieName} =~ /^\w+$/ ) {
$result = 0;
$response->error('"' . $config->{cookieName} . '" is not a valid cookie Name')
$response->error('"' . $config->{cookieName} . '" ' . &txt_isNotAValidCookieName );
}
# Check domain name
unless( $config->{domain} =~ /^\w[\w\.\-]*\w$/ ) {
$result = 0;
$response->error('"' . $config->{domain} . '" is not a valid domain name');
$response->error('"' . $config->{domain} . '" ' . &txt_isNotAValidCookieName );
}
# Load variables
foreach(keys %{ $config->{exportedVars} }) {
# Reserved words
if( $_ eq 'groups' ) {
$response->error( "\"$_\" is not authorized in attribute names. Change it!" );
$result = 0;
}
if( $_ !~ /^\w+$/ ) {
$response->error("\"$_\" is not a valid attribute name");
if( $_ eq 'groups' or $_ !~ /^\w+$/ ) {
$response->error( "\"$_\" " . &txt_isNotAValidAttributeName );
$result = 0;
}
if( $config->{exportedVars}->{$_} !~ /^\w+$/ ) {
$response->error("\"$config->{exportedVars}->{$_}\" is not a valid LDAP attribute");
$response->error("\"$config->{exportedVars}->{$_}\" " . &txt_isNotAValidLDAPAttributeName );
$result = 0;
}
$expr .= "my \$$_ = '1';";
@ -458,55 +454,51 @@ sub checkConf {
$safe->reval( $expr );
if ( $@ ) {
$result = 0;
$response->error("Unknown errors in exported attributes ($@)");
$response->error( &txt_unknownErrorInVars . " ($@)");
}
while( my($k, $v) = each( %{ $config->{macros} } ) ) {
# Reserved words
if( $k eq 'groups' ) {
$response->error("\"$k\" is not authorized in macro names. Change it!");
$result = 0;
}
if( $k !~ /^[a-zA-Z]\w*$/ ) {
$response->error("$k is not a valid macro name");
if( $k eq 'groups' or $k !~ /^[a-zA-Z]\w*$/ ) {
$response->error("\"$k\" " . &txt_isNotAValidMacroName );
$result = 0;
}
if( $v =~ /(?<=[^=<\?])=(?!=)/ ) {
$response->warning("Macro $k contains an assignment ('='). Possible confusion with '=='.");
$response->warning( &txt_macro . " $k " . &txt_containsAnAssignment );
}
# Test macro values;
$expr .= "my \$$k = $v;";
}
# Test macro values;
$safe->reval( $expr );
if( $@ ) {
$response->error("Error in macro syntax: $@");
$result = 0;
$safe->reval( $expr );
if( $@ ) {
$response->error( &txt_macro . " $k : " . &txt_syntaxError . " : $@");
$result = 0;
}
}
# TODO: check module name
# Check whatToTrace
unless ( $config->{whatToTrace} =~ /^\$?[a-zA-Z]\w*$/ ) {
$response->error("whatToTrace parameter can contain only an exported attribute or a macro");
$response->error( &txt_invalidWhatToTrace );
$result = 0;
}
# Test groups
$expr .= 'my $groups;';
while( my($k,$v) = each( %{ $config->{groups} } ) ) {
if( $k !~ /^[\w-]+$/ ) {
$response->error("\"$k\" is not a valid group name");
$response->error("\"$k\" " . &txt_isNotAValidGroupName );
$result = 0;
}
if( $v =~ /(?<=[^=<\?])=(?!=)/ ) {
$response->warning("Group $k contains an assignment ('='). Possible confusion with '=='.");
$response->warning( &txt_group . " $k " . &txt_containsAnAssignment );
}
$safe->reval( $expr . "\$groups = '$k' if($v);");
if( $@ ) {
$response->error("Syntax error in group \"$k\": $@");
$response->error( &txt_group . " $k " . &txt_syntaxError );
$result = 0;
}
}
# Test rules
while( my($vh, $rules) = each( %{ $config->{locationRules} } ) ) {
unless( $vh =~ /^\w[-\w\.]*$/ ) {
$response->error("\"$vh\" is not a valid virtual host name");
$response->error("\"$vh\" " . &txt_isNotAValidVirtualHostName );
$result = 0;
}
while( my($reg, $v) = each( %{ $rules } ) ) {
@ -514,17 +506,17 @@ sub checkConf {
$reg =~ s/#/\\#/g;
$safe->reval( $expr . "my \$r = qr#$reg#;" );
if( $@ ) {
$response->error("Syntax error in regexp ($vh -> $reg)");
$response->error( &txt_rule . " $vh -> \"$reg\" : " . &txt_syntaxError );
$result = 0;
}
}
unless( $v eq 'deny' or $v eq 'accept' ) {
if( $v =~ /(?<=[^=<\?])=(?!=)/ ) {
$response->warning("Rule $vh -> $reg contains an assignment ('='). Possible confusion with '=='.");
$response->warning( &txt_rule . " $vh -> \"$reg\" : " . &txt_containsAnAssignment );
}
$safe->reval( $expr . "my \$r=1 if($v);");
if( $@ ) {
$response->error("Syntax error in expression ($vh -> $reg)");
$response->error( &txt_rule . " $vh -> \"$reg\" : " . &txt_syntaxError );
$result = 0;
}
}
@ -533,20 +525,20 @@ sub checkConf {
# Test exported headers
while( my($vh, $headers) = each( %{ $config->{exportedHeaders} } ) ) {
unless( $vh =~ /^\w[-\w\.]*$/ ) {
$response->error("\"$vh\" is not a valid virtual host name");
$response->error("\"$vh\" " . &txt_isNotAValidVirtualHostName );
$result = 0;
}
while( my($header, $v) = each( %{ $headers } ) ) {
unless( $header =~ /^[\w][-\w]*$/ ) {
$response->error("\"$header\" is not a valid HTTP header name ($vh)");
$response->error("\"$header\" ($vh) " . &txt_isNotAValidHTTPHeaderName );
$result = 0;
}
if( $v =~ /(?<=[^=<\?])=(?!=)/ ) {
$response->warning("Header $vh -> $header contains an assignment ('='). Possible confusion with '=='.");
$response->warning(&txt_header . " $vh -> $header " . &txt_containsAnAssignment );
}
$safe->reval( $expr . "my \$r = $v;" );
if( $@ ) {
$response->error("Syntax error in header expression ($vh -> $header)");
$response->error(&txt_header . " $vh -> $header " . &txt_syntaxError );
$result = 0;
}
}

@ -2,7 +2,7 @@ package Lemonldap::NG::Manager::_i18n;
use AutoLoader qw(AUTOLOAD);
use UNIVERSAL qw(can);
our $VERSION = '0.2';
our $VERSION = '0.3';
sub import {
my ($caller_package) = caller;
@ -32,134 +32,160 @@ __END__
=pod
=cut
sub fr {
sub en {
return {
configuration => 'Configuration',
exportedVars => 'Attributs LDAP &agrave; exporter',
generalParameters => 'Param&egrave;tres g&eacute;n&eacute;raux',
ldapParameters => 'Param&egrave;tres LDAP',
sessionStorage => 'Stockage des sessions',
globalStorageOptions => 'Param&egrave;tres du module Apache::Session',
authParams => "Param&egrave;tres d'authentification",
userGroups => "Groupes d'utilisateurs",
macros => "Macros",
virtualHosts => "H&ocirc;tes virtuels",
authenticationType => "Type d'authentification",
securedCookie => 'Cookie s&eacute;curis&eacute; (SSL)',
domain => 'Domaine',
cookieName => 'Nom du cookie',
apacheSessionModule => 'Module Apache::Session',
ldapServer => 'Serveur LDAP',
ldapPort => 'Port du serveur LDAP',
ldapBase => 'Base de recherche LDAP',
managerDn => 'Compte de connexion LDAP',
managerPassword => 'Mot de passe LDAP',
httpHeaders => 'En-t&ecirc;tes HTTP',
locationRules => 'R&egrave;gles',
# Attention: ici, &eacute; ne sera pas interprété par Firefox (msgBox)
newVirtualHost => 'Nouvel hote virtuel',
newMacro => 'Nouvelle macro',
newGroup => 'Nouveau groupe',
newVar => 'Nouvelle variable',
newRule => 'Nouvelle r&egrave;gle',
newHeader => 'Nouvel en-t&ecirc;te',
newGSOpt => 'Nouvelle option',
saveConf => 'Sauvegarder',
deleteNode => 'Supprimer',
unableToSave => 'Votre navigateur ne supporte pas les objets XMLHTTPRequest: sauvegarde impossible.',
confSaved => 'Configuration sauvegard&eacute;e sous le num&eacute;ro',
saveFailure => '&Eacute;chec de la sauvegarde',
unknownError => 'Erreur inconnue',
waitingResult => 'En attente...',
configurationWasChanged => "configuration modifi&eacute;e depuis que vous l'avez t&eacute;l&eacute;charg&eacute;e",
configLoaded => 'Configuration charg&eacute;e',
warningConfNotApplied => "Vous devez recharger les agents pour que la configuration sauvegard&eacute;e soit appliqu&eacute;e",
applyConf => 'Appliquer',
canNotReadApplyConfFile => 'Configuration non appliqu&eacute;e: impossible de lire le fichier de configuration',
invalidLine => 'Ligne invalide',
error => 'Erreur',
result => 'R&eacute;sultat',
changesAppliedLater => "Les changements seront effectifs d'ici 10 minutes. Utilisez \"apachectl reload\" sur les serveurs concern&eacute;s pour forcer la prise en compte imm&eacute;diate",
prevConf => 'Pr&eacute;c&eacute;dente',
nextConf => 'Suivante',
lastConf => 'Derni&egrave;re',
deleteVirtualHost => "Supprimer l'h&ocirc;te virtuel",
# Attention: ici, &Ecirc; ne sera pas interprété par Firefox (msgBox)
areYouSure => 'Etes vous sur ?',
syntaxError => 'Erreur de syntaxe, configuration refus&eacute;e. Consultez les journaux du serveur web.',
whatToTrace => "Donn&eacute;e &agrave; inscrire dans les journaux d'Apache",
deleteConf => 'Effacer',
confirmDeleteConf => "Vous allez effacer cette configuration. Confirmez-vous ?",
configurationDeleted => 'Configuration &eacute;ffac&eacute;e',
configurationNotDeleted => 'Configuration non &eacute;ffac&eacute;e',
invalidVirtualHostName => "Nom de d'hôte virtuel incorrect",
checkLogs => "Consultez les journaux d'Apache",
apacheSessionModule => "Apache::Session module",
applyConf => "Apply",
areYouSure => "Are you sure ?",
authParams => "Authentication Parameters",
authenticationType => "Authentifition Type",
canNotReadApplyConfFile => "Configuration not applied: cannot read configuration file",
changesAppliedLater => 'Changes will be effective within 10 minutes. Use "apachectl reload" on concerned servers for immediate reloading',
checkLogs => "Check Apache logs",
confSaved => "Configuration saved with number",
configLoaded => "Configuration loaded",
configuration => "Configuration",
configurationDeleted => "Configuration deleted",
configurationNotDeleted => "Configuration not deleted",
configurationWasChanged => "Configuration has been changed since you got it",
confirmDeleteConf => "You're going to delete configuration. Do you confirm ?",
cookieName => "Cookie Name",
containsAnAssignment => 'contains an assignment ("="). Possible confusion with "==".',
deleteConf => "Delete",
deleteNode => "Delete",
deleteVirtualHost => "Delete virtual host",
domain => "Domain",
error => "Error",
exportedVars => "Exported Variables",
generalParameters => "General Parameters",
globalStorageOptions => "Session Storage Parameters",
group => "Group",
header => "Header",
httpHeaders => "HTTP Headers",
invalidLine => "Invalid Line",
invalidVirtualHostName => "Invalid virtual host name",
invalidWhatToTrace => "Data to use in Apache's logs can contain only an exported attribute or a macro",
isNotAValidAttributeName => "is not a valid attribute name",
isNotAValidCookieName => "is not a valid cookie name",
isNotAValidDomainName => "is not a valid domain name",
isNotAValidGroupName => "is not a valid group name",
isNotAValidHTTPHeaderName => "is not a valid HTTP header name",
isNotAValidLDAPAttributeName => "is not a valid LDAP attribute name",
isNotAValidMacroName => "is not a valid macro name",
isNotAValidVirtualHostName => "is not a valid virtual host name",
lastConf => "Last",
ldapBase => "LDAP Search Base",
ldapParameters => "LDAP Parameters",
ldapPort => "LDAP Server Port",
ldapServer => "LDAP Server",
locationRules => "Rules",
macro => "Macro",
macros => "Macros",
managerDn => "LDAP Account",
managerPassword => "LDAP Password",
newGSOpt => "New Option",
newGroup => "New Group",
newHeader => "New Header",
newMacro => "New Macro",
newRule => "New Rule",
newVar => "New Variable",
newVirtualHost => "New Virtual Host",
nextConf => "Next",
prevConf => "Previous",
result => "Result",
rule => "Rule",
rules => "Rules",
saveConf => "Save",
saveFailure => "Save failure",
securedCookie => "Secured Cookie (SSL)",
sessionStorage => "Session Storage",
syntaxError => "Syntax error",
unableToSave => "Your browser does not support XMLHTTPRequest objects: fail to save.",
unknownError => "Unknown error",
unknownErrorInVars => "Unknown error in exported attributes",
userGroups => "User Groups",
virtualHosts => "Virtual Hosts",
waitingResult => "Waiting result...",
warningConfNotApplied => "You have to reload handlers to take the saved configuration in account",
whatToTrace => "Attribute to use in Apache's logs",
};
}
sub en {
sub fr {
return {
configuration => 'Configuration',
exportedVars => 'Exported Variables',
generalParameters => 'General Parameters',
ldapParameters => 'LDAP Parameters',
sessionStorage => 'Session Storage',
globalStorageOptions => 'Session Storage Parameters',
authParams => "Authentication Parameters",
userGroups => "User Groups",
macros => "Macros",
virtualHosts => "Virtual Hosts",
authenticationType => "Authentifition Type",
securedCookie => 'Secured Cookie (SSL)',
domain => 'Domain',
cookieName => 'Cookie Name',
apacheSessionModule => 'Apache::Session module',
ldapServer => 'LDAP Server',
ldapPort => 'LDAP Server Port',
ldapBase => 'LDAP Search Base',
managerDn => 'LDAP Account',
managerPassword => 'LDAP Password',
httpHeaders => 'HTTP Headers',
locationRules => 'Rules',
newVirtualHost => 'New Virtual Host',
newMacro => 'New Macro',
newGroup => 'New Group',
newVar => 'New Variable',
newRule => 'New Rule',
newHeader => 'New Header',
newGSOpt => 'New Option',
saveConf => 'Save',
deleteNode => 'Delete',
rules => 'Rules',
unableToSave => 'Your browser does not support XMLHTTPRequest objects: fail to save.',
confSaved => 'Configuration saved with number',
saveFailure => 'Save failure',
unknownError => 'Unknown error',
waitingResult => 'Waiting result...',
configurationWasChanged => 'Configuration has been changed since you got it',
configLoaded => 'Configuration loaded',
warningConfNotApplied => 'You have to reload handlers to take the saved configuration in account',
applyConf => 'Apply',
canNotReadApplyConfFile => 'Configuration not applied: cannot read configuration file',
invalidLine => 'Invalid Line',
error => 'Error',
result => 'Result',
changesAppliedLater => 'Changes will be effective within 10 minutes. Use "apachectl reload" on concerned servers for immediate reloading',
prevConf => 'Previous',
nextConf => 'Next',
lastConf => 'Last',
deleteVirtualHost => 'Delete virtual host',
areYouSure => 'Are you sure ?',
syntaxError => 'Syntax error, configuration refused. See web server logs for more.',
whatToTrace => "Attribute to use in Apache's logs",
deleteConf => 'Delete',
confirmDeleteConf => "You're going to delete configuration. Do you confirm ?",
configurationDeleted => 'Configuration deleted',
configurationNotDeleted => 'Configuration not deleted',
invalidVirtualHostName => 'Invalid virtual host name',
checkLogs => 'Check Apache logs',
apacheSessionModule => "Module Apache::Session",
applyConf => "Appliquer",
areYouSure => "Etes vous sur ?",
authParams => "Param&egrave;tres d'authentification",
authenticationType => "Type d'authentification",
canNotReadApplyConfFile => "Configuration non appliqu&eacute;e: impossible de lire le fichier de configuration",
changesAppliedLater => "Les changements seront effectifs d'ici 10 minutes. Utilisez \"apachectl reload\" sur les serveurs concern&eacute;s pour forcer la prise en compte imm&eacute;diate",
checkLogs => "Consultez les journaux d'Apache",
confSaved => "Configuration sauvegard&eacute;e sous le num&eacute;ro",
configLoaded => "Configuration charg&eacute;e",
configuration => "Configuration",
configurationDeleted => "Configuration &eacute;ffac&eacute;e",
configurationNotDeleted => "Configuration non &eacute;ffac&eacute;e",
configurationWasChanged => "configuration modifi&eacute;e depuis que vous l'avez t&eacute;l&eacute;charg&eacute;e",
confirmDeleteConf => "Vous allez effacer cette configuration. Confirmez-vous ?",
cookieName => "Nom du cookie",
containsAnAssignment => 'contient une affectation ("="). Confusion possible avec "==".',
deleteConf => "Effacer",
deleteNode => "Supprimer",
deleteVirtualHost => "Supprimer l'h&ocirc;te virtuel",
domain => "Domaine",
error => "Erreur",
exportedVars => "Attributs LDAP &agrave; exporter",
generalParameters => "Param&egrave;tres g&eacute;n&eacute;raux",
globalStorageOptions => "Param&egrave;tres du module Apache::Session",
group => "Groupe",
header => "En-t&ecirc;te",
httpHeaders => "En-t&ecirc;tes HTTP",
invalidLine => "Ligne invalide",
invalidVirtualHostName => "Nom de d'hôte virtuel incorrect",
invalidWhatToTrace => "La donn&eacute;e &agrave; inscrire dans les journaux ne peut contenir qu'un attribut exporté ou une macro",
isNotAValidAttributeName => "n'est pas un nom d'attribut valide",
isNotAValidCookieName => "n'est pas un nom de cookie valide",
isNotAValidDomainName => "n'est pas un nom de domaine valide",
isNotAValidGroupName => "n'est pas un nom de groupe valide",
isNotAValidHTTPHeaderName => "n'est pas un nom d'en-t&ecirc;te HTTP valide",
isNotAValidLDAPAttributeName => "is not a valid LDAP attribute name",
isNotAValidMacroName => "n'est pas un nom de macro valide",
isNotAValidVirtualHostName => "n'est pas un nom d'h&ocirc;te virtuel valide",
lastConf => "Derni&egrave;re",
ldapBase => "Base de recherche LDAP",
ldapParameters => "Param&egrave;tres LDAP",
ldapPort => "Port du serveur LDAP",
ldapServer => "Serveur LDAP",
locationRules => "R&egrave;gles",
macro => "Macro",
macros => "Macros",
managerDn => "Compte de connexion LDAP",
managerPassword => "Mot de passe LDAP",
newGSOpt => "Nouvelle option",
newGroup => "Nouveau groupe",
newHeader => "Nouvel en-t&ecirc;te",
newMacro => "Nouvelle macro",
newRule => "Nouvelle r&egrave;gle",
newVar => "Nouvelle variable",
newVirtualHost => "Nouvel hote virtuel",
nextConf => "Suivante",
prevConf => "Pr&eacute;c&eacute;dente",
result => "R&eacute;sultat",
rule => "R&egrave;gle",
rules => "R&egrave;gles",
saveConf => "Sauvegarder",
saveFailure => "&Eacute;chec de la sauvegarde",
securedCookie => "Cookie s&eacute;curis&eacute; (SSL)",
sessionStorage => "Stockage des sessions",
syntaxError => "Erreur de syntaxe",
unableToSave => "Votre navigateur ne supporte pas les objets XMLHTTPRequest: sauvegarde impossible.",
unknownError => "Erreur inconnue",
unknownErrorInVars => "Erreur inconnue dans les attributs export&eacute;s",
userGroups => "Groupes d'utilisateurs",
virtualHosts => "H&ocirc;tes virtuels",
waitingResult => "En attente...",
warningConfNotApplied => "Vous devez recharger les agents pour que la configuration sauvegard&eacute;e soit appliqu&eacute;e",
whatToTrace => "Donn&eacute;e &agrave; inscrire dans les journaux d'Apache",
};
}

@ -0,0 +1,24 @@
use Test::More tests => 2;
BEGIN { use_ok('Lemonldap::NG::Manager::_i18n') }
ok ( &compare ( "en", "fr" ) );
sub compare {
my ( $l1, $l2 ) = @_;
$r1 = &{"Lemonldap::NG::Manager::_i18n::" . $l1};
$r2 = &{"Lemonldap::NG::Manager::_i18n::" . $l2};
my $r = 1;
foreach ( keys %$r1 ) {
unless( $r2->{$_} ) {
print STDERR "$_ is present in $l1 but miss in $l2";
$r=0;
}
}
foreach ( keys %$r2 ) {
unless( $r1->{$_} ) {
print STDERR "$_ is present in $l2 but miss in $l1";
$r=0;
}
}
return $r;
}
Loading…
Cancel
Save