diff --git a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf.pm b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf.pm
index abb4744e1..8f01267a2 100644
--- a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf.pm
+++ b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf.pm
@@ -397,47 +397,60 @@ sub getDBConf {
return $conf;
}
+sub _launch {
+ my $self = shift;
+ my $sub = shift;
+ my $res;
+ eval {
+ local $SIG{ALRM} = sub { die "TIMEOUT\n" };
+ alarm ($self->{confTimeout} || 10);
+ $res = &{ $self->{type} . "::$sub" }( $self, @_ );
+ alarm 0;
+ };
+ $msg .= $@ if $@;
+ return $res;
+}
+
## @method boolean prereq()
# Call prereq() from the $self->{type} package.
# @return True if succeed
sub prereq {
- return &{ $_[0]->{type} . '::prereq' }(@_);
+ return shift->_launch( 'prereq', @_ );
}
## @method @ available()
# Call available() from the $self->{type} package.
# @return list of available configuration numbers
sub available {
- return &{ $_[0]->{type} . '::available' }(@_);
+ return shift->_launch( 'available', @_ );
}
## @method int lastCfg()
# Call lastCfg() from the $self->{type} package.
# @return Number of the last configuration available
sub lastCfg {
- my $result = &{ $_[0]->{type} . '::lastCfg' }(@_) || "0";
- return $result;
+ return shift->_launch( 'lastCfg', @_ ) || 0;
}
## @method boolean lock()
# Call lock() from the $self->{type} package.
# @return True if succeed
sub lock {
- return &{ $_[0]->{type} . '::lock' }(@_);
+ return shift->_launch( 'lock', @_ );
}
## @method boolean isLocked()
# Call isLocked() from the $self->{type} package.
# @return True if database is locked
sub isLocked {
- return &{ $_[0]->{type} . '::isLocked' }(@_);
+ return shift->_launch( 'isLocked', @_ );
}
## @method boolean unlock()
# Call unlock() from the $self->{type} package.
# @return True if succeed
sub unlock {
- return &{ $_[0]->{type} . '::unlock' }(@_);
+ return shift->_launch( 'unlock', @_ );
}
## @method int store(hashRef conf)
@@ -445,14 +458,14 @@ sub unlock {
# @param $conf Lemondlap configuration serialized
# @return Number of new configuration stored if succeed, 0 else.
sub store {
- return &{ $_[0]->{type} . '::store' }(@_);
+ return shift->_launch( 'store', @_ );
}
## @method load(int cfgNum, arrayRef fields)
# Call load() from the $self->{type} package.
# @return Lemonldap::NG Configuration hashRef if succeed, 0 else.
sub load {
- return &{ $_[0]->{type} . '::load' }(@_);
+ return shift->_launch( 'load', @_ );
}
## @method boolean delete(int cfgNum)
@@ -463,7 +476,7 @@ sub delete {
my ( $self, $c ) = @_;
my @a = $self->available();
if ( grep( /^$c$/, @a ) ) {
- return &{ $self->{type} . '::delete' }( $self, $c );
+ return $self->_launch( 'delete', $self, $c );
}
else {
return 0;
@@ -471,7 +484,7 @@ sub delete {
}
sub logError {
- return &{ $_[0]->{type} . '::logError' }(@_);
+ return shift->_launch( 'logError', @_ );
}
1;
diff --git a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Session.pm b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Session.pm
index b7b40bc92..b7b8ac901 100644
--- a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Session.pm
+++ b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Session.pm
@@ -82,6 +82,8 @@ has 'error' => (
has info => ( is => 'rw' );
+has timeout => ( is => 'rw', default => 5 );
+
sub BUILD {
my ($self) = @_;
@@ -93,7 +95,9 @@ sub BUILD {
# Register options for common Apache::Session module
my $moduleOptions = $self->storageModuleOptions || {};
- my %options = (
+ $self->timeout( delete $moduleOptions->{timeout} )
+ if $moduleOptions->{timeout};
+ my %options = (
%$moduleOptions,
backend => $self->storageModule,
localStorage => $self->cacheModule,
@@ -158,10 +162,12 @@ sub BUILD {
sub _tie_session {
my $self = $_[0];
my $options = $_[1] || {};
-
my %h;
eval {
+ local $SIG{ALRM} = sub { die "TIMEOUT\n" };
+ alarm $self->timeout;
+
# SOAP/REST session module must be directly tied
if ( $self->storageModule =~ /^Lemonldap::NG::Common::Apache::Session/ )
{
@@ -172,8 +178,9 @@ sub _tie_session {
tie %h, 'Lemonldap::NG::Common::Apache::Session', $self->id,
{ %{ $self->options }, %$options };
}
- };
+ alarm 0;
+ };
if ( $@ or not tied(%h) ) {
my $msg = "Session cannot be tied";
$msg .= ": $@" if $@;
diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/Fail.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/Fail.pm
new file mode 100644
index 000000000..52f3d1314
--- /dev/null
+++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/Fail.pm
@@ -0,0 +1,11 @@
+package Lemonldap::NG::Handler::Lib::Fail;
+
+use base Lemonldap::NG::Handler::Main;
+
+sub run {
+ return $_[0]->SERVER_ERROR;
+}
+
+our $VERSION = '2.0.6';
+
+1;
diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/PSGI.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/PSGI.pm
index 43b12899e..f1f2bf42a 100644
--- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/PSGI.pm
+++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Lib/PSGI.pm
@@ -21,7 +21,7 @@ sub init {
return 0;
}
unless ( $self->api->checkConf($self)
- or $self->{protection} eq 'none' )
+ or ( $self->{protection} and $self->{protection} eq 'none' ) )
{
$self->error(
"Unable to protect this server ($Lemonldap::NG::Common::Conf::msg)"
@@ -127,7 +127,8 @@ sub _authAndTrace {
$type = $tmp . $type;
Lemonldap::NG::Handler::Main->buildAndLoadType($type);
my ( $res, $session ) = $type->run( $req, $self->{rule} );
- $self->portal( $type->tsv->{portal}->() );
+ eval { $self->portal( $type->tsv->{portal}->() ) };
+ $self->logger->warn($@) if $@;
$req->userData($session) if ($session);
if ( $res < 300 ) {
@@ -145,7 +146,7 @@ sub _authAndTrace {
return [ $res, [ $req->spliceHdrs ], [] ];
}
else {
- my $s = $type->tsv->{portal}->() . "/lmerror/$res";
+ my $s = ( $self->portal ? $self->portal . "/lmerror/$res" : '' );
$s =
'
Redirection'
. qq{}
diff --git a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Run.pm b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Run.pm
index 1976606b6..e8e91599b 100644
--- a/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Run.pm
+++ b/lemonldap-ng-handler/lib/Lemonldap/NG/Handler/Main/Run.pm
@@ -83,8 +83,11 @@ sub checkType {
my ( $class, $req ) = @_;
if ( time() - $class->lastCheck > $class->checkTime ) {
- die("$class: No configuration found")
- unless ( $class->checkConf );
+ unless ( $class->checkConf ) {
+ $class->logger->error("$class: No configuration found");
+ $req->data->{noTry} = 1;
+ return 'Fail';
+ }
}
my $vhost = $class->resolveAlias($req);
return ( defined $class->tsv->{type}->{$vhost} )
diff --git a/lemonldap-ng-manager/site/coffee/sessions.coffee b/lemonldap-ng-manager/site/coffee/sessions.coffee
index 4608dc5f2..1ccd08866 100644
--- a/lemonldap-ng-manager/site/coffee/sessions.coffee
+++ b/lemonldap-ng-manager/site/coffee/sessions.coffee
@@ -60,6 +60,16 @@ schemes =
(t,v,q) ->
q.replace(/\&groupBy.*$/, '') + "&ipAddr=#{v}"
]
+ _session_uid: [
+ # First level: display 1 letter
+ (t,v) ->
+ "groupBy=substr(#{t},1)"
+ # Second level (if no overScheme), display usernames
+ (t,v) ->
+ "#{t}=#{v}*&groupBy=#{t}"
+ (t,v) ->
+ "#{t}=#{v}"
+ ]
# When number of children nodes exceeds "max" value and if "overScheme."
# is available and does not return "null", a level is added. See
@@ -86,6 +96,12 @@ overScheme =
"#{t}=#{v}*&groupBy=substr(#{t},#{(10+level+over)})"
else
null
+ _session_uid: (t,v,level,over) ->
+ console.log 'overSchema => level', level, 'over', over
+ if level == 1 and v.length > over
+ "#{t}=#{v}*&groupBy=substr(#{t},#{(level+over+1)})"
+ else
+ null
hiddenAttributes = '_password'
diff --git a/lemonldap-ng-manager/site/htdocs/static/js/sessions.js b/lemonldap-ng-manager/site/htdocs/static/js/sessions.js
index 51b9120e1..f4f5a6c3d 100644
--- a/lemonldap-ng-manager/site/htdocs/static/js/sessions.js
+++ b/lemonldap-ng-manager/site/htdocs/static/js/sessions.js
@@ -1,4 +1,4 @@
-// Generated by CoffeeScript 1.12.8
+// Generated by CoffeeScript 1.12.7
/*
* Sessions explorer
@@ -69,6 +69,15 @@
}, function(t, v, q) {
return q.replace(/\&groupBy.*$/, '') + ("&ipAddr=" + v);
}
+ ],
+ _session_uid: [
+ function(t, v) {
+ return "groupBy=substr(" + t + ",1)";
+ }, function(t, v) {
+ return t + "=" + v + "*&groupBy=" + t;
+ }, function(t, v) {
+ return t + "=" + v;
+ }
]
};
@@ -96,6 +105,14 @@
} else {
return null;
}
+ },
+ _session_uid: function(t, v, level, over) {
+ console.log('overSchema => level', level, 'over', over);
+ if (level === 1 && v.length > over) {
+ return t + "=" + v + "*&groupBy=substr(" + t + "," + (level + over + 1) + ")";
+ } else {
+ return null;
+ }
}
};
diff --git a/lemonldap-ng-manager/site/htdocs/static/js/sessions.min.js b/lemonldap-ng-manager/site/htdocs/static/js/sessions.min.js
index f6e4233cc..7c3208eb7 100644
--- a/lemonldap-ng-manager/site/htdocs/static/js/sessions.min.js
+++ b/lemonldap-ng-manager/site/htdocs/static/js/sessions.min.js
@@ -1 +1 @@
-(function(){var M,s,h,f;f={_whatToTrace:[function(e,t){return"groupBy=substr("+e+",1)"},function(e,t){return e+"="+t+"*&groupBy="+e},function(e,t){return e+"="+t}],ipAddr:[function(e,t){return"groupBy=net("+e+",16,1)"},function(e,t){return t.match(/:/)||(t+="."),e+"="+t+"*&groupBy=net("+e+",32,2)"},function(e,t){return t.match(/:/)||(t+="."),e+"="+t+"*&groupBy=net("+e+",48,3)"},function(e,t){return t.match(/:/)||(t+="."),e+"="+t+"*&groupBy=net("+e+",128,4)"},function(e,t){return e+"="+t+"&groupBy=_whatToTrace"},function(e,t,n){return n.replace(/\&groupBy.*$/,"")+"&_whatToTrace="+t}],_startTime:[function(e,t){return"groupBy=substr("+e+",8)"},function(e,t){return e+"="+t+"*&groupBy=substr("+e+",10)"},function(e,t){return e+"="+t+"*&groupBy=substr("+e+",11)"},function(e,t){return e+"="+t+"*&groupBy=substr("+e+",12)"},function(e,t){return e+"="+t+"*&groupBy=_whatToTrace"},function(e,t,n){return console.log(e),console.log(t),console.log(n),n.replace(/\&groupBy.*$/,"")+"&_whatToTrace="+t}],doubleIp:[function(e,t){return e},function(e,t){return"_whatToTrace="+t+"&groupBy=ipAddr"},function(e,t,n){return n.replace(/\&groupBy.*$/,"")+"&ipAddr="+t}]},h={_whatToTrace:function(e,t,n,o){return console.log("overSchema => level",n,"over",o),1===n&&t.length>o?e+"="+t+"*&groupBy=substr("+e+","+(n+o+1)+")":null},ipAddr:function(e,t,n,o){return console.log("overSchema => level",n,"over",o),0 level",n,"over",o),3t.title?1:e.title real attribute"),D.push(u)):C.push(u);return R=C.concat(D),P.push({title:"__attributesAndMacros__",nodes:R}),{_utime:k,id:c,nodes:P}},t=(H.currentScope=e).$modelValue.session,o.get(scriptname+"sessions/"+g+"/"+t).then(function(e){return H.currentSession=n(e.data)}),H.showT=!1},H.localeDate=function(e){return new Date(1e3*e).toLocaleString()},H.isValid=function(e,t){var n,o,r;return r=i.path(),o=Date.now()/1e3,console.log("Path",r),console.log("Session epoch",e),console.log("Current date",o),console.log("Session TTL",sessionTTL),n=o-e level",n,"over",o),1===n&&t.length>o?e+"="+t+"*&groupBy=substr("+e+","+(n+o+1)+")":null},ipAddr:function(e,t,n,o){return console.log("overSchema => level",n,"over",o),0 level",n,"over",o),3 level",n,"over",o),1===n&&t.length>o?e+"="+t+"*&groupBy=substr("+e+","+(n+o+1)+")":null}},M={dateTitle:["_utime","_startTime","_updateTime","_lastAuthnUTime","_lastSeen"],connectionTitle:["ipAddr","_timezone","_url"],authenticationTitle:["_session_id","_user","_password","authenticationLevel"],modulesTitle:["_auth","_userDB","_passwordDB","_issuerDB","_authChoice","_authMulti","_userDBMulti"],saml:["_idp","_idpConfKey","_samlToken","_lassoSessionDump","_lassoIdentityDump"],groups:["groups","hGroups"],ldap:["dn"],BrowserID:["_browserIdAnswer","_browserIdAnswerRaw"],OpenIDConnect:["_oidc_id_token","_oidc_OP","_oidc_access_token"],sfaTitle:["_2fDevices"],oidcConsents:["_oidcConsents"]},s={session:[{title:"deleteSession",icon:"trash"}],home:[]},angular.module("llngSessionsExplorer",["ui.tree","ui.bootstrap","llApp"]).controller("SessionsExplorerCtrl",["$scope","$translator","$location","$q","$http",function(H,t,i,e,o){var d,n,r,g;return H.links=links,H.menulinks=menulinks,H.staticPrefix=staticPrefix,H.scriptname=scriptname,H.formPrefix=formPrefix,H.impPrefix=impPrefix,H.sessionTTL=sessionTTL,H.availableLanguages=availableLanguages,H.waiting=!0,H.showM=!1,H.showT=!0,H.data=[],H.currentScope=null,H.currentSession=null,H.menu=s,H.translateP=t.translateP,H.translate=t.translate,H.translateTitle=function(e){return t.translateField(e,"title")},g="global",H.menuClick=function(e){if(e.popup)window.open(e.popup);else switch(e.action||(e.action=e.title),typeof e.action){case"function":e.action(H.currentNode,H);break;case"string":H[e.action]();break;default:console.log(typeof e.action)}return H.showM=!1},H.deleteOIDCConsent=function(e,t){return angular.element(".data-"+t).remove(),H.waiting=!0,o.delete(scriptname+"sessions/OIDCConsent/"+g+"/"+H.currentSession.id+"?rp="+e+"&epoch="+t).then(function(e){return H.waiting=!1},function(e){return H.waiting=!1}),H.showT=!1},H.deleteSession=function(){return H.waiting=!0,o.delete(scriptname+"sessions/"+g+"/"+H.currentSession.id).then(function(e){return H.currentSession=null,H.currentScope.remove(),H.waiting=!1},function(e){return H.currentSession=null,H.currentScope.remove(),H.waiting=!1})},H.stoggle=function(e){var t;return 0===(t=e.$modelValue).nodes.length&&H.updateTree(t.value,t.nodes,t.level,t.over,t.query,t.count),e.toggle()},H.displaySession=function(e){var t,n;return n=function(s){var e,t,n,o,r,i,u,a,l,c,p,d,g,h,f,_,m,T,y,w,v,S,$,B,b,D,L,A,P,x,C,I,k,O,R,E;for(g in e=function(e,t){var n,o,r,i;for(n in r=[],o=new RegExp(e),s)i=s[n],n.match(o)&&i&&(r.push({title:n,value:i}),delete s[n]);if(0t.title?1:e.title real attribute"),D.push(u)):C.push(u);return R=C.concat(D),P.push({title:"__attributesAndMacros__",nodes:R}),{_utime:k,id:c,nodes:P}},t=(H.currentScope=e).$modelValue.session,o.get(scriptname+"sessions/"+g+"/"+t).then(function(e){return H.currentSession=n(e.data)}),H.showT=!1},H.localeDate=function(e){return new Date(1e3*e).toLocaleString()},H.isValid=function(e,t){var n,o,r;return r=i.path(),o=Date.now()/1e3,console.log("Path",r),console.log("Session epoch",e),console.log("Current date",o),console.log("Session TTL",sessionTTL),n=o-enew( {
+ confFailure => 1,
+ ini => {
+ configStorage => {
+ type => 'Timeout',
+ dirName => 't',
+ confTimeout => 1,
+ },
+ logLevel => 'error',
+ useSafeJail => 1,
+ globalStorage => 'Apache::Session::Timeout',
+ globalStorageOptions => {
+ Directory => $tmpDir,
+ LockDirectory => "$tmpDir/lock",
+ timeout => 1,
+ },
+ }
+ }
+);
+
+diag "Waiting";
+ok( !$client->{p}->init( $client->ini ) );
+ok( $client->app( $client->{p}->run ) );
+ok(
+ $res = $client->_post(
+ '/',
+ IO::String->new('user=dwho&password=dwho'),
+ length => 23,
+ ),
+ 'Auth query'
+);
+ok( $res->[0] == 500 );
+count(4);
+clean_sessions();
+
+done_testing( count() );
diff --git a/lemonldap-ng-portal/t/03-SessionTimeout.t b/lemonldap-ng-portal/t/03-SessionTimeout.t
new file mode 100644
index 000000000..6b3a1c34d
--- /dev/null
+++ b/lemonldap-ng-portal/t/03-SessionTimeout.t
@@ -0,0 +1,41 @@
+use Test::More;
+use strict;
+use IO::String;
+use lib 't/lib';
+
+require 't/test-lib.pm';
+
+my $res;
+
+my $client = LLNG::Manager::Test->new(
+ {
+ ini => {
+ logLevel => 'error',
+ useSafeJail => 1,
+ globalStorage => 'Apache::Session::Timeout',
+ globalStorageOptions => {
+ Directory => 't/sessions',
+ LockDirectory => 't/sessions/lock',
+ timeout => 1,
+ },
+ }
+ }
+);
+
+# Try to authenticate with good password
+# --------------------------------------
+diag 'Waiting';
+ok(
+ $res = $client->_post(
+ '/',
+ IO::String->new('user=dwho&password=dwho'),
+ length => 23,
+ ),
+ 'Auth query'
+);
+count(1);
+expectReject( $res, 401, 8 );
+
+clean_sessions();
+
+done_testing( count() );
diff --git a/lemonldap-ng-portal/t/lib/Apache/Session/Timeout.pm b/lemonldap-ng-portal/t/lib/Apache/Session/Timeout.pm
new file mode 100644
index 000000000..7c161f8a0
--- /dev/null
+++ b/lemonldap-ng-portal/t/lib/Apache/Session/Timeout.pm
@@ -0,0 +1,14 @@
+package Apache::Session::Timeout;
+
+use strict;
+use Apache::Session::File;
+
+our @ISA = ('Apache::Session::File');
+
+sub populate {
+ my $self = shift;
+ sleep 6;
+ return $self->SUPER::populate(@_);
+}
+
+1;
diff --git a/lemonldap-ng-portal/t/lib/Lemonldap/NG/Common/Conf/Backends/Timeout.pm b/lemonldap-ng-portal/t/lib/Lemonldap/NG/Common/Conf/Backends/Timeout.pm
new file mode 100644
index 000000000..516e558ec
--- /dev/null
+++ b/lemonldap-ng-portal/t/lib/Lemonldap/NG/Common/Conf/Backends/Timeout.pm
@@ -0,0 +1,17 @@
+package Lemonldap::NG::Common::Conf::Backends::Timeout;
+
+use Lemonldap::NG::Common::Conf::Backends::File;
+our @ISA = ('Lemonldap::NG::Common::Conf::Backends::File');
+
+sub load {
+ my $self = shift;
+ sleep 5;
+ return $self->SUPER::load(@_);
+}
+
+sub AUTOLOAD {
+ $AUTOLOAD =~ s/Lemonldap::NG::Common::Conf::Backends::Timeout:://;
+ return &{"Lemonldap::NG::Common::Conf::Backends::File::$AUTOLOAD"}(@_);
+}
+
+1;
diff --git a/lemonldap-ng-portal/t/test-lib.pm b/lemonldap-ng-portal/t/test-lib.pm
index 77d556113..92b3dddf2 100644
--- a/lemonldap-ng-portal/t/test-lib.pm
+++ b/lemonldap-ng-portal/t/test-lib.pm
@@ -140,7 +140,8 @@ sub count_sessions {
sub getCache {
require Cache::FileCache;
- return Cache::FileCache->new( {
+ return Cache::FileCache->new(
+ {
namespace => 'lemonldap-ng-session',
cache_root => $tmpDir,
cache_depth => 0,
@@ -562,6 +563,8 @@ has p => ( is => 'rw' );
=cut
+has confFailure => ( is => 'rw' );
+
has ini => (
is => 'rw',
lazy => 1,
@@ -573,27 +576,30 @@ has ini => (
}
$self->{ini} = $ini;
main::ok( $self->{p} = $self->class->new(), 'Portal object' );
- main::ok( $self->{p}->init($ini), 'Init' );
- main::ok( $self->{app} = $self->{p}->run(), 'Portal app' );
- main::count(3);
- no warnings 'redefine';
- eval
+ main::count(1);
+ unless ( $self->confFailure ) {
+ main::ok( $self->{p}->init($ini), 'Init' );
+ main::ok( $self->{app} = $self->{p}->run(), 'Portal app' );
+ main::count(2);
+ no warnings 'redefine';
+ eval
'sub Lemonldap::NG::Common::Logger::Std::error {return $_[0]->warn($_[1])}';
- $Lemonldap::NG::Portal::UserDB::Demo::demoAccounts{french} = {
- uid => 'french',
- cn => 'Frédéric Accents',
- mail => 'fa@badwolf.org',
- };
- $Lemonldap::NG::Portal::UserDB::Demo::demoAccounts{davros} = {
- uid => 'davros',
- cn => 'Bad Guy',
- mail => 'davros@badguy.org',
- };
- $Lemonldap::NG::Portal::UserDB::Demo::demoAccounts{russian} = {
- uid => 'russian',
- cn => 'Русский',
- mail => 'ru@badwolf.org',
- };
+ $Lemonldap::NG::Portal::UserDB::Demo::demoAccounts{french} = {
+ uid => 'french',
+ cn => 'Frédéric Accents',
+ mail => 'fa@badwolf.org',
+ };
+ $Lemonldap::NG::Portal::UserDB::Demo::demoAccounts{davros} = {
+ uid => 'davros',
+ cn => 'Bad Guy',
+ mail => 'davros@badguy.org',
+ };
+ $Lemonldap::NG::Portal::UserDB::Demo::demoAccounts{russian} = {
+ uid => 'russian',
+ cn => 'Русский',
+ mail => 'ru@badwolf.org',
+ };
+ }
$self;
}
);
@@ -677,7 +683,8 @@ to test content I<(to launch a C for example)>.
sub _get {
my ( $self, $path, %args ) = @_;
- my $res = $self->app->( {
+ my $res = $self->app->(
+ {
'HTTP_ACCEPT' => $args{accept}
|| 'application/json, text/plain, */*',
'HTTP_ACCEPT_LANGUAGE' => 'fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3',
@@ -729,7 +736,8 @@ sub _post {
my ( $self, $path, $body, %args ) = @_;
die "$body must be a IO::Handle"
unless ( ref($body) and $body->can('read') );
- my $res = $self->app->( {
+ my $res = $self->app->(
+ {
'HTTP_ACCEPT' => $args{accept}
|| 'application/json, text/plain, */*',
'HTTP_ACCEPT_LANGUAGE' => 'fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3',
diff --git a/scripts/parameters-for-wiki.pl b/scripts/parameters-for-wiki.pl
index 905042c8b..5c2bc9df5 100755
--- a/scripts/parameters-for-wiki.pl
+++ b/scripts/parameters-for-wiki.pl
@@ -64,6 +64,7 @@ print <