line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Dancer2 plugin for easy create restfull web services |
2
|
|
|
|
|
|
|
# Provides Routes for authentication, persistent session data |
3
|
|
|
|
|
|
|
# It can handle the formats : JSON , XML , YAML, PERL , HUMAN |
4
|
|
|
|
|
|
|
# |
5
|
|
|
|
|
|
|
# Quick diffences between plugin and Dancer2 core |
6
|
|
|
|
|
|
|
# |
7
|
|
|
|
|
|
|
# main plugin |
8
|
|
|
|
|
|
|
# ------------------------------------------------------------- |
9
|
|
|
|
|
|
|
# Dancer2 method $plugin->app->DancerMethod |
10
|
|
|
|
|
|
|
# setting('Key') or config->{Key} $plugin->config->{key} , $plugin->app->{name}, $plugin->{app}->{name}, |
11
|
|
|
|
|
|
|
# |
12
|
|
|
|
|
|
|
# change setting : $plugin->{app}->{config}->{SomeSetting} = 'foo'; |
13
|
|
|
|
|
|
|
# |
14
|
|
|
|
|
|
|
# example of start command |
15
|
|
|
|
|
|
|
# |
16
|
|
|
|
|
|
|
# sudo -u joe /usr/bin/site_perl/plackup --host 0.0.0.0 --port 65535 --server Starman --workers=10 -a /opt/TestService/bin/app.psgi --Reload /opt/TestService/lib,/opt/TestService/config.yml,/usr/share/perl5/site_perl/Dancer2/Plugin |
17
|
|
|
|
|
|
|
# |
18
|
|
|
|
|
|
|
# George Mpouras |
19
|
|
|
|
|
|
|
# george.mpouras@yandex.com |
20
|
|
|
|
|
|
|
# 25 Sep 2016 , Athens - Greece |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
package Dancer2::Plugin::WebService; |
26
|
1
|
|
|
1
|
|
45638
|
use Dancer2::Plugin; |
|
1
|
|
|
|
|
198966
|
|
|
1
|
|
|
|
|
5
|
|
27
|
1
|
|
|
1
|
|
24940
|
use Storable; |
|
1
|
|
|
|
|
2337
|
|
|
1
|
|
|
|
|
2844
|
|
28
|
|
|
|
|
|
|
our $VERSION = '3.009'; |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
if ($^O =~ /(?i)MSWin/) {warn "Sorry windows operating system is not supported\n"; exit 1} |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# Make available the following functions to applications |
34
|
|
|
|
|
|
|
plugin_keywords qw/ |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
get_data_user |
37
|
|
|
|
|
|
|
set_data_user |
38
|
|
|
|
|
|
|
del_data_user |
39
|
|
|
|
|
|
|
get_data_session |
40
|
|
|
|
|
|
|
set_data_session |
41
|
|
|
|
|
|
|
del_data_session |
42
|
|
|
|
|
|
|
RestReply |
43
|
|
|
|
|
|
|
/; |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# Change rw properties later like $plugin->SomeProperty('new value'); |
47
|
|
|
|
|
|
|
has dir_root => (is=>'ro', default=> sub{ ($_=$_[0]->{app}->{config}->{appdir}) =~s/\/*$//; if (-d $_) { $_ } else { warn "Could not define root directory\n"; exit 1 }}); |
48
|
|
|
|
|
|
|
has formats => (is=>'ro', default=> sub{{ json => 'application/json', xml => 'text/xml', yaml => 'text/x-yaml', perl => 'text/html', human => 'text/html' }}); |
49
|
|
|
|
|
|
|
has formats_regex => (is=>'ro', default=> sub{ $_=join '|', sort keys %{ $_[0]->formats }; $_ = qr/^($_)$/; $_ }); |
50
|
|
|
|
|
|
|
has ClientIP => (is=>'rw', default=> ''); |
51
|
|
|
|
|
|
|
has route_name => (is=>'rw', default=> ''); |
52
|
|
|
|
|
|
|
has error => (is=>'rw', default=> 0); |
53
|
|
|
|
|
|
|
has errormessage => (is=>'rw', default=> 'ok'); |
54
|
|
|
|
|
|
|
has data_user => (is=>'rw', default=> sub{ {} }); # hash holding the data user send to us at "data_from" |
55
|
|
|
|
|
|
|
has data_from => (is=>'rw', default=> ''); # string of user data |
56
|
|
|
|
|
|
|
has data_to => (is=>'rw', default=> ''); # string of user data rebuilded |
57
|
|
|
|
|
|
|
has Authentication_method=> (is=>'rw', default=> ''); |
58
|
|
|
|
|
|
|
has auth_member_of => (is=>'rw', default=> sub{ [] }); |
59
|
|
|
|
|
|
|
has auth_result => (is=>'rw', default=> 0); |
60
|
|
|
|
|
|
|
has auth_message => (is=>'rw', default=> ''); |
61
|
|
|
|
|
|
|
has from => (is=>'rw', from_config=>'Default format', default=> sub{ 'json' }); |
62
|
|
|
|
|
|
|
has to => (is=>'rw', default=> sub{ $_[0]->from }); |
63
|
|
|
|
|
|
|
has sudo => (is=>'ro', from_config=>'Command sudo', default=> sub{ '/usr/bin/sudo' }); |
64
|
|
|
|
|
|
|
has rm => (is=>'ro', from_config=>'Command rm', default=> sub{ '/usr/bin/rm' }); |
65
|
|
|
|
|
|
|
has groups => (is=>'ro', from_config=>'User must belong to one or more of the groups', default=> sub{ [] }); |
66
|
|
|
|
|
|
|
has Session_idle_timout => (is=>'ro', from_config=>'Session idle timout', default=> sub{ 3600 } ); |
67
|
|
|
|
|
|
|
has rules => (is=>'ro', from_config=>'Allowed hosts',default=> sub{ ['127.*', '192.168.*', '10.*', '172.16.*'] }); |
68
|
|
|
|
|
|
|
has rules_compiled => (is=>'ro', default=> sub {my $array = [@{$_[0]->rules}]; for (@{$array}) { s/([^?*]+)/\Q$1\E/g; s|\?|.|g; s|\*+|.*?|g; $_ = qr/^$_$/i } $array}); |
69
|
|
|
|
|
|
|
has dir_session => (is=>'ro', default=> sub {$_ = exists $_[0]->{app}->{config}->{plugins}->{WebService}->{'Session directory'} ? $_[0]->{app}->{config}->{plugins}->{WebService}->{'Session directory'} : $_[0]->dir_root .'/sessions'; $_ .= "/$_[0]->{app}->{config}->{appname}" if $_ !~/$_[0]->{app}->{config}->{appname}$/; $_}); |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
sub BUILD |
75
|
|
|
|
|
|
|
{ |
76
|
0
|
|
|
0
|
0
|
|
my $plugin = shift; |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# Define the built in Routes |
79
|
0
|
|
|
|
|
|
$plugin->config->{Routes}->{info} = 'public'; |
80
|
0
|
|
|
|
|
|
$plugin->config->{Routes}->{login} = 'public'; |
81
|
0
|
|
|
|
|
|
$plugin->config->{Routes}->{logout} = 'private'; |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
# Default Dancer2 settings |
84
|
0
|
|
|
|
|
|
$plugin->{app}->{config}->{content_type}= 'application/json'; |
85
|
0
|
0
|
|
|
|
|
$plugin->{app}->{config}->{charset} = 'utf-8' if $plugin->{app}->{config}->{charset} eq ''; |
86
|
0
|
|
0
|
|
|
|
$plugin->{app}->{config}->{encoding} //= 'UTF-8'; |
87
|
0
|
|
0
|
|
|
|
$plugin->{app}->{config}->{show_errors} //= 1; |
88
|
0
|
|
0
|
|
|
|
$plugin->{app}->{config}->{auto_page} //= 0; |
89
|
0
|
|
0
|
|
|
|
$plugin->{app}->{config}->{traces} //= 0; |
90
|
0
|
|
0
|
|
|
|
$plugin->{app}->{config}->{layout} //= 'main'; |
91
|
0
|
|
0
|
|
|
|
$plugin->{app}->{config}->{behind_proxy}//= 0; |
92
|
0
|
|
0
|
|
|
|
$plugin->{app}->{config}->{plugins}->{WebService}->{'Default format'} //= 'json'; |
93
|
0
|
|
0
|
|
|
|
$plugin->{app}->{config}->{plugins}->{WebService}->{'Command sudo'} //= '/usr/bin/sudo'; |
94
|
0
|
|
0
|
|
|
|
$plugin->{app}->{config}->{plugins}->{WebService}->{'Command rm'} //= '/usr/bin/rm'; |
95
|
0
|
|
0
|
|
|
|
$plugin->{app}->{config}->{plugins}->{WebService}->{'Owner'} //= 'Joe Lunchbucket'; |
96
|
0
|
|
0
|
|
|
|
$plugin->{app}->{config}->{plugins}->{WebService}->{'Session idle timout'}//= 3600; |
97
|
|
|
|
|
|
|
|
98
|
0
|
0
|
|
|
|
|
__MKDIR($plugin->dir_session) or die 'Could not create the session directory '.$plugin->dir_session." because $!\n"; |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
# Find the active authentication method |
101
|
0
|
|
|
|
|
|
(my $module_dir =__FILE__) =~s/\/(?>[^\/]+)$//; |
102
|
0
|
0
|
|
|
|
|
unless (-d $module_dir) {warn "Sorry could not define the Dancer2::Plugin::WebService installation directory\n"; exit 1} |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
103
|
0
|
|
|
|
|
|
print STDOUT "Application name : $plugin->{app}->{config}->{appname}\n"; |
104
|
0
|
|
|
|
|
|
print STDOUT "Application version : $plugin->{app}->{config}->{plugins}->{WebService}->{Version}\n"; |
105
|
0
|
|
|
|
|
|
print STDOUT "Run as user : ". (getpwuid($>))[0] ."\n"; |
106
|
0
|
|
|
|
|
|
print STDOUT "Started at : ". scalar(localtime $^T) ."\n"; |
107
|
0
|
|
|
|
|
|
print STDOUT "Process identifier : $$\n"; |
108
|
0
|
|
|
|
|
|
print STDOUT "WebService version : $VERSION\n"; |
109
|
0
|
|
|
|
|
|
print STDOUT "Module dir : $module_dir\n"; |
110
|
|
|
|
|
|
|
|
111
|
0
|
|
|
|
|
|
foreach (keys %{$plugin->config->{'Authentication method'}} ) { |
|
0
|
|
|
|
|
|
|
112
|
0
|
0
|
|
|
|
|
next unless $plugin->config->{'Authentication method'}->{$_}->{Active} =~/(?i)yes/; |
113
|
0
|
|
|
|
|
|
$plugin->config->{'Authentication method'}->{$_}->{Command} =~s/^MODULE_INSTALL_DIR/$module_dir/; |
114
|
0
|
0
|
|
|
|
|
if ( ! -f $plugin->config->{'Authentication method'}->{$_}->{Command} ) { warn 'Sorry, could not found the external authorization utility : "'. $plugin->config->{'Authentication method'}->{$_}->{Command} ."\"\n"; exit 1 } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
115
|
0
|
0
|
|
|
|
|
if ( ! -x $plugin->config->{'Authentication method'}->{$_}->{Command} ) { warn 'Sorry, the external authorization utility "'. $plugin->config->{'Authentication method'}->{$_}->{Command} .'" is not executable from user '.getpwuid($>) ."\n"; exit 1 } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
116
|
0
|
|
|
|
|
|
$plugin->Authentication_method($_); |
117
|
0
|
|
|
|
|
|
print STDOUT "Authorization method : $_\n"; |
118
|
0
|
|
|
|
|
|
print STDOUT 'Authorization command: ', $plugin->config->{'Authentication method'}->{$_}->{Command} ,"\n"; |
119
|
|
|
|
|
|
|
last |
120
|
0
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
|
122
|
0
|
0
|
|
|
|
|
if ('' eq $plugin->Authentication_method) { |
123
|
0
|
|
|
|
|
|
warn "\nCould not found any active authentication method, please check your configuration to activate at least one, and try again.\n"; |
124
|
0
|
|
|
|
|
|
exit 1 |
125
|
|
|
|
|
|
|
} |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
# Search for stored sessions |
128
|
0
|
|
|
|
|
|
$_ = $plugin->dir_session; |
129
|
0
|
|
|
|
|
|
print STDOUT "Session idle time out: ". $plugin->Session_idle_timout ."\n"; |
130
|
0
|
|
|
|
|
|
print STDOUT "Ssession storage dir : $_\n"; |
131
|
0
|
0
|
|
|
|
|
opendir __SESSIONDIR, $_ or die "Could not list session directory $_ because $!\n"; |
132
|
|
|
|
|
|
|
|
133
|
0
|
|
|
|
|
|
foreach my $session (grep ! /^\.+$/, readdir __SESSIONDIR) { |
134
|
0
|
0
|
|
|
|
|
if (-f "$_/$session") {unlink "$_/$session"; next} |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
|
136
|
0
|
0
|
0
|
|
|
|
if ((-f "$_/$session/__clientip") && (-f "$_/$session/__lastaccess") && (-f "$_/$session/__logintime") && (-f "$_/$session/__user")) { |
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
137
|
0
|
|
|
|
|
|
my $lastaccess = ${ Storable::retrieve "$_/$session/__lastaccess" }; |
|
0
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
|
139
|
0
|
0
|
|
|
|
|
if ( time - $lastaccess > $plugin->config->{'Session idle timout'} ) { |
140
|
0
|
|
|
|
|
|
print STDOUT "Delete expired session: $session\n"; |
141
|
0
|
|
|
|
|
|
system $plugin->rm, '--recursive', '--force', "$_/$session" |
142
|
|
|
|
|
|
|
} |
143
|
|
|
|
|
|
|
else { |
144
|
|
|
|
|
|
|
# Session is not expired update the __lastaccess and read the rest properties |
145
|
0
|
|
|
|
|
|
print STDOUT "Found stored session : $session\n"; |
146
|
0
|
0
|
|
|
|
|
Storable::lock_store(\ time, "$_/$session/__lastaccess") or die "Could not store at session $session the property __lastaccess because $!\n" |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
else { |
150
|
0
|
|
|
|
|
|
print STDERR "Delete corrupt session: $session\n"; |
151
|
0
|
|
|
|
|
|
system $plugin->rm, '--recursive', '--force', "$_/$session" |
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
0
|
|
|
|
|
|
closedir __SESSIONDIR; |
156
|
|
|
|
|
|
|
#print STDERR "\n", Data::Dumper::Dumper( $plugin->from ) ,"\n\n"; |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# to reset the any posted or user data |
160
|
0
|
|
|
0
|
|
|
$plugin->app->add_hook( Dancer2::Core::Hook->new(name => 'after', code => sub { $plugin->data_user({}) }) ); |
|
0
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
# |
163
|
|
|
|
|
|
|
$plugin->app->add_hook( Dancer2::Core::Hook->new(name => 'before', code => sub |
164
|
|
|
|
|
|
|
{ |
165
|
0
|
|
0
|
0
|
|
|
$_ = (values %{ $plugin->app->request->params('route') })[0] // ''; |
|
0
|
|
|
|
|
|
|
166
|
0
|
|
|
|
|
|
$plugin->app->request->path =~/^\/*(.+?)\/*$_$/; |
167
|
0
|
|
|
|
|
|
$plugin->route_name($^N); |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
|
170
|
0
|
0
|
|
|
|
|
$plugin->config->{Routes}->{ $plugin->route_name } = 'public' unless exists $plugin->config->{Routes}->{ $plugin->route_name }; # If a route is not defined at the configuration file we will considered it as public |
171
|
0
|
|
0
|
|
|
|
$plugin->from($plugin->app->request->query_parameters->{from} // $plugin->config->{'Default format'}); |
172
|
0
|
|
0
|
|
|
|
$plugin->to( $plugin->app->request->query_parameters->{to} // $plugin->from); |
173
|
0
|
0
|
|
|
|
|
if ( $plugin->from !~ $plugin->formats_regex ) { $plugin->error(20); $plugin->errormessage('property from '.$plugin->from.' is not one of the supported : '. join(', ',keys %{$plugin->formats})); $plugin->to('json'); $plugin->app->halt( $plugin->RestReply ) } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
174
|
0
|
0
|
|
|
|
|
if ( $plugin->to !~ $plugin->formats_regex ) { $plugin->error(21); $plugin->errormessage('property to '. $plugin->to. ' is not one of the supported : '. join(', ',keys %{$plugin->formats})); $plugin->to('json'); $plugin->app->halt( $plugin->RestReply ) } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
|
176
|
0
|
|
|
|
|
|
$plugin->app->request->header('Content-Type'=> $plugin->formats->{$plugin->to}); # add header |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
# Parse user's posted/sent data |
179
|
0
|
0
|
|
|
|
|
if ( $plugin->app->request->body ) { |
180
|
0
|
|
|
|
|
|
$plugin->data_from( $plugin->app->request->body ); |
181
|
0
|
|
|
|
|
|
my $hash = $plugin->__CONVERT_STRING_TO_HASHREF; |
182
|
|
|
|
|
|
|
|
183
|
0
|
0
|
|
|
|
|
if ( $plugin->error ) { |
184
|
0
|
|
|
|
|
|
$plugin->to('json'); |
185
|
0
|
|
|
|
|
|
$plugin->dump_user_properties( { error=>$plugin->error, errormessage=>$plugin->errormessage, description=>'Data conversion error from '.$plugin->from.' to '.$plugin->to } ); |
186
|
0
|
|
|
|
|
|
$plugin->data_user( {} ); |
187
|
0
|
0
|
|
|
|
|
die "DataStructure internal error : ". $plugin->errormessage."\n" if $plugin->error; |
188
|
0
|
|
|
|
|
|
$plugin->app->halt( $plugin->data_to ) |
189
|
|
|
|
|
|
|
} |
190
|
|
|
|
|
|
|
|
191
|
0
|
|
|
|
|
|
$plugin->data_user($hash) |
192
|
|
|
|
|
|
|
} |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
# Setup the remote IP address, even if the web service is running from a reverse proxy |
195
|
0
|
0
|
|
|
|
|
$plugin->ClientIP( defined $plugin->app->request->env->{HTTP_X_REAL_IP} ? $plugin->app->request->env->{HTTP_X_REAL_IP} : defined $plugin->app->request->address ? $plugin->app->request->address : '127.0.0.1' ); |
|
|
0
|
|
|
|
|
|
196
|
|
|
|
|
|
|
|
197
|
0
|
0
|
|
|
|
|
return if 'public' eq $plugin->config->{Routes}->{ $plugin->route_name }; |
198
|
|
|
|
|
|
|
# If the code gets to this line, we are sure, we are dealing with a private protected route |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
# Check if the session is valid, or it is expired due to inactivity |
201
|
|
|
|
|
|
|
# If the session is not expired update the __lastaccess |
202
|
0
|
0
|
|
|
|
|
unless (exists $plugin->data_user->{SessionID}) { $plugin->error(2); $plugin->errormessage('You must login for using the private route '.$plugin->route_name); $plugin->data_user({description=>'Get SessionID via login route'}); $plugin->app->halt( $plugin->RestReply ) } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
203
|
0
|
|
|
|
|
|
$_ = $plugin->dir_session.'/'.$plugin->data_user->{SessionID}; |
204
|
0
|
0
|
|
|
|
|
unless (-d $_) { $plugin->error(3); $plugin->errormessage('invalid or expired SessionID '.$plugin->data_user->{SessionID}); $plugin->data_user({description=>'Get a valid SessionID via login route'}); $plugin->app->halt( $plugin->RestReply ) } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
205
|
0
|
|
|
|
|
|
my $lastaccess = ${ Storable::retrieve "$_/__lastaccess" }; |
|
0
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
|
207
|
0
|
0
|
|
|
|
|
if ( time - $lastaccess > $plugin->config->{'Session idle timout'} ) { |
208
|
0
|
|
|
|
|
|
$plugin->error(4); |
209
|
0
|
|
|
|
|
|
$plugin->errormessage('Session '.$plugin->data_user->{SessionID}.' expired because its idle time '.(time - $lastaccess).' secs is more than the allowed '.$plugin->config->{'Session idle timout'}.' secs'); |
210
|
0
|
|
|
|
|
|
system $plugin->rm, '--recursive', '--force', $_; |
211
|
0
|
|
|
|
|
|
$plugin->app->halt( $plugin->RestReply ) |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
else { |
214
|
0
|
|
|
|
|
|
Storable::lock_store(\ time, "$_/__lastaccess") |
215
|
|
|
|
|
|
|
} |
216
|
0
|
|
|
|
|
|
})); |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
# Built in route /info |
223
|
0
|
|
|
0
|
|
|
$plugin->app->add_route( regexp=> '/info', method=> 'get', code=> sub { $_[0]->forward('/info/version') } ); |
|
0
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
# Built in route /info/:what |
227
|
|
|
|
|
|
|
$plugin->app->add_route( |
228
|
|
|
|
|
|
|
method => 'get', |
229
|
|
|
|
|
|
|
regexp => '/info/:what', |
230
|
|
|
|
|
|
|
code => sub { |
231
|
0
|
|
|
0
|
|
|
my $app= shift; |
232
|
|
|
|
|
|
|
|
233
|
0
|
0
|
|
|
|
|
if ( $app->request->param('what') =~/(?i)v/ ) { |
|
|
0
|
|
|
|
|
|
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
$plugin->RestReply( |
236
|
|
|
|
|
|
|
Name => $plugin->app->{name}, |
237
|
|
|
|
|
|
|
Owner => $plugin->{app}->{config}->{plugins}->{WebService}->{Owner}, |
238
|
0
|
0
|
|
|
|
|
Os => eval{ $_='Posix'; if (open FILE, '/etc/issue') { ($_= )=~s/\v*$//m; close FILE} $_ }, |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
'Service uptime secs' => time - $^T, |
240
|
|
|
|
|
|
|
'Server date time' => scalar localtime time, |
241
|
|
|
|
|
|
|
Version => { |
242
|
|
|
|
|
|
|
Application => $plugin->{app}->{config}->{plugins}->{WebService}->{Version}, |
243
|
|
|
|
|
|
|
Dancer => $Dancer2::VERSION, |
244
|
|
|
|
|
|
|
Perl => $], |
245
|
0
|
|
|
|
|
|
'Linux kernel' => eval{$_ = qx/uname -r/; chomp $_; $_}, |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
'WebService' => $VERSION |
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
) |
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
elsif ( $app->request->param('what') =~/(?i)cl/ ) { |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
$plugin->RestReply( |
253
|
|
|
|
|
|
|
'Client address' => $plugin->ClientIP, |
254
|
|
|
|
|
|
|
'Client port' => $plugin->app->request->env->{REMOTE_PORT}, |
255
|
0
|
|
|
|
|
|
'Agent' => $plugin->app->request->agent, |
256
|
|
|
|
|
|
|
'Is secure' => $plugin->app->request->secure, |
257
|
|
|
|
|
|
|
'Protocol' => $plugin->app->request->protocol, |
258
|
|
|
|
|
|
|
'Http method' => $plugin->app->request->method, |
259
|
|
|
|
|
|
|
'Header accept' => $plugin->app->request->header('accept'), |
260
|
|
|
|
|
|
|
'Parameters url' => join(' ', $plugin->app->request->params('query')), |
261
|
|
|
|
|
|
|
'Parameters route' => join(' ', $plugin->app->request->params('route')), |
262
|
|
|
|
|
|
|
'Parameters body' => join(' ', $plugin->app->request->params('body')) ) |
263
|
|
|
|
|
|
|
} |
264
|
|
|
|
|
|
|
else { |
265
|
0
|
|
|
|
|
|
$plugin->RestReply(error=>5, errormessage=>'Not existing internal route \''.$app->request->param('what').'\' Please choose one of : version, about, client') |
266
|
|
|
|
|
|
|
} |
267
|
0
|
|
|
|
|
|
} ); |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
# logout and delete the session |
271
|
|
|
|
|
|
|
$plugin->app->add_route( |
272
|
|
|
|
|
|
|
method => $_, |
273
|
|
|
|
|
|
|
regexp => '/logout', |
274
|
|
|
|
|
|
|
code => sub |
275
|
|
|
|
|
|
|
{ |
276
|
0
|
|
|
0
|
|
|
my $app = shift; |
277
|
0
|
|
|
|
|
|
$plugin->error(0); |
278
|
0
|
|
|
|
|
|
$plugin->errormessage('logged out from session '. $plugin->data_user->{SessionID} ); |
279
|
0
|
|
|
|
|
|
$plugin->__Delete_session; |
280
|
0
|
|
|
|
|
|
$plugin->RestReply |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
|
283
|
0
|
|
|
|
|
|
) foreach 'get', 'post'; |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
# curl -X GET --data '{"user":"Joe", "password":"MySecret" }' 'localhost:3000/login?from=json;to=json' |
289
|
|
|
|
|
|
|
# |
290
|
|
|
|
|
|
|
# Authenticate users using external custom scripts or commands |
291
|
|
|
|
|
|
|
# using the appropriate shell script you can easily have your |
292
|
|
|
|
|
|
|
# LDAP, kerberus, Active Directory, SQL, or what ever mechanism you want |
293
|
|
|
|
|
|
|
# Feel free to write your own scripts and define them at config.yml |
294
|
|
|
|
|
|
|
# |
295
|
|
|
|
|
|
|
# The external custom shell authorization scripts/commands receives three arguments |
296
|
|
|
|
|
|
|
# |
297
|
|
|
|
|
|
|
# 1) user (as hex string) |
298
|
|
|
|
|
|
|
# 2) password (as hex string) |
299
|
|
|
|
|
|
|
# 3) comma delimited groups that the user should belong at least to one of them |
300
|
|
|
|
|
|
|
# |
301
|
|
|
|
|
|
|
# we convert the user, pass arguments to hex strings to avoid shell attacks. |
302
|
|
|
|
|
|
|
# Remember at linux the maximum length of a shell command is getconf ARG_MAX |
303
|
|
|
|
|
|
|
# |
304
|
|
|
|
|
|
|
# The result is stored at |
305
|
|
|
|
|
|
|
# |
306
|
|
|
|
|
|
|
# $plugin->auth_result 1 for successful login, or 0 fail |
307
|
|
|
|
|
|
|
# $plugin->auth_message the reason why the login was failed e.g "user do not exist" |
308
|
|
|
|
|
|
|
# $plugin->auth_member_of In case of successful login, the groups that the user belongs (from the ones we have specify) |
309
|
|
|
|
|
|
|
# |
310
|
|
|
|
|
|
|
$plugin->app->add_route( |
311
|
|
|
|
|
|
|
method => $_, |
312
|
|
|
|
|
|
|
regexp => '/login', |
313
|
|
|
|
|
|
|
code => sub |
314
|
|
|
|
|
|
|
{ |
315
|
0
|
|
|
0
|
|
|
my $app = shift; |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
# Check client IP address against the access rules |
318
|
0
|
|
|
|
|
|
$plugin->error(13); |
319
|
0
|
|
|
|
|
|
for (my $i=0; $i<@{ $plugin->rules_compiled }; $i++) |
|
0
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
{ |
321
|
0
|
0
|
|
|
|
|
if ( $plugin->ClientIP =~ $plugin->rules_compiled->[$i] ) { |
322
|
0
|
|
|
|
|
|
$plugin->error(0); |
323
|
0
|
|
|
|
|
|
$plugin->errormessage('ok'); |
324
|
0
|
|
|
|
|
|
$plugin->data_user->{'IP access'} = 'Match client IP '. $plugin->ClientIP .' from rule '. $plugin->rules->[$i]; |
325
|
|
|
|
|
|
|
last |
326
|
0
|
|
|
|
|
|
} |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
|
329
|
0
|
0
|
|
|
|
|
if ( $plugin->error ) { |
330
|
0
|
|
|
|
|
|
$plugin->errormessage('Client IP address '. $plugin->ClientIP .' is not allowed from any IP access rule'); |
331
|
0
|
|
|
|
|
|
$plugin->app->halt( $plugin->RestReply('user') ) |
332
|
|
|
|
|
|
|
} |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
# Check the input parameters |
335
|
0
|
0
|
|
|
|
|
foreach ('user','password') {unless (exists $plugin->data_user->{$_}) { $plugin->error(6); $plugin->errormessage("Login failed, you did not pass the $_"); $plugin->app->halt( $plugin->RestReply ) }} |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
336
|
0
|
0
|
|
|
|
|
if ( $plugin->data_user->{user} =~ /^\s*$/ ) { $plugin->error(7); $plugin->errormessage("Login failed because the user is blank"); $plugin->app->halt( $plugin->RestReply ) } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
337
|
0
|
0
|
|
|
|
|
if ( $plugin->data_user->{password} eq '' ) { $plugin->error(8); $plugin->errormessage("Login failed because the password is blank"); $plugin->app->halt( $plugin->RestReply('user') ) } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
338
|
0
|
0
|
|
|
|
|
if ( 0 == @{$plugin->groups } ) { $plugin->error(9); $plugin->errormessage("Login failed because the required group list is empty"); $plugin->app->halt( $plugin->RestReply('user') ) } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
|
340
|
0
|
|
|
|
|
|
$plugin->auth_result(0); |
341
|
0
|
|
|
|
|
|
$plugin->auth_message('Unknown authentication error'); |
342
|
0
|
|
|
|
|
|
$plugin->auth_member_of([]); |
343
|
|
|
|
|
|
|
|
344
|
0
|
|
|
|
|
|
my $user = unpack 'H*', $plugin->data_user->{user}; |
345
|
0
|
|
|
|
|
|
my $password = unpack 'H*', $plugin->data_user->{password}; |
346
|
0
|
|
|
|
|
|
my $groups = join ',', @{$plugin->groups}; |
|
0
|
|
|
|
|
|
|
347
|
0
|
|
|
|
|
|
my $command = $plugin->config->{'Authentication method'}->{$plugin->Authentication_method}->{'Command'}; |
348
|
0
|
|
|
|
|
|
my @output = (); |
349
|
0
|
|
|
|
|
|
$command = "\Q$command\E $user $password \Q$groups\E"; |
350
|
0
|
0
|
|
|
|
|
$command = $plugin->sudo ." $command" if $plugin->config->{'Authentication method'}->{$plugin->Authentication_method}->{'Use sudo'} =~/(?i)y/; |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
#print "arguments after pack: $user $password $groups\n"; |
353
|
|
|
|
|
|
|
#print STDERR "\n*", $command ,"*\n\n"; |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
# Execute the external authorization utility and capture its 3 lines output at @output array |
356
|
0
|
0
|
|
|
|
|
open SHELL, '-|', "$command 2> /dev/null" or die "Could run auth shell command \"$command\" because \"$?\"\n"; |
357
|
0
|
|
|
|
|
|
while () { s/^\s*(.*?)\s*$/$1/; push @output, $_ } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
358
|
0
|
|
|
|
|
|
close SHELL; |
359
|
|
|
|
|
|
|
|
360
|
0
|
|
|
|
|
|
$plugin->auth_result( $output[0]); |
361
|
0
|
|
|
|
|
|
$plugin->auth_message($output[1]); |
362
|
0
|
0
|
|
|
|
|
$plugin->auth_member_of( [ split /,/, $output[2] ] ) if $plugin->auth_result; |
363
|
|
|
|
|
|
|
|
364
|
0
|
0
|
|
|
|
|
if ($plugin->auth_result) { |
365
|
0
|
0
|
|
|
|
|
$plugin->auth_message('ok') if $plugin->auth_message eq ''; |
366
|
0
|
0
|
|
|
|
|
$plugin->auth_member_of(['emptylist']) unless @{ $plugin->auth_member_of } |
|
0
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
else { |
369
|
0
|
0
|
|
|
|
|
$plugin->auth_message('Unknown authentication error') if $plugin->auth_message eq ''; |
370
|
0
|
|
|
|
|
|
$plugin->auth_member_of([]) |
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
|
373
|
0
|
0
|
|
|
|
|
$plugin->error( $plugin->auth_result == 0 ? 10 : 0 ); |
374
|
0
|
|
|
|
|
|
$plugin->errormessage( $plugin->auth_message ); |
375
|
0
|
0
|
|
|
|
|
$plugin->app->halt( $plugin->RestReply('user') ) if $plugin->error; |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
# User authenticated successfully, now we must create his permanent session |
378
|
|
|
|
|
|
|
# and store there some built in properties |
379
|
0
|
|
|
|
|
|
my $SessionID = ''; $SessionID .= sprintf("%08x", int rand 800_000_000) for 1..4; |
|
0
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
|
381
|
0
|
0
|
|
|
|
|
if (-e $plugin->dir_session ."/$SessionID") { |
382
|
0
|
|
|
|
|
|
my $i=1; |
383
|
0
|
|
|
|
|
|
while ( -e $plugin->dir_session ."/$i.$SessionID" ) {$i++} |
|
0
|
|
|
|
|
|
|
384
|
0
|
|
|
|
|
|
$SessionID = "$i.$SessionID" |
385
|
|
|
|
|
|
|
} |
386
|
|
|
|
|
|
|
|
387
|
0
|
0
|
|
|
|
|
unless (mkdir $plugin->dir_session ."/$SessionID") { |
388
|
0
|
|
|
|
|
|
$plugin->error(12); |
389
|
0
|
|
|
|
|
|
$plugin->errormessage("Login failed . Could not create session directory $SessionID because $!"); |
390
|
0
|
|
|
|
|
|
$plugin->app->halt( $plugin->RestReply('user') ) |
391
|
|
|
|
|
|
|
} |
392
|
|
|
|
|
|
|
|
393
|
0
|
|
|
|
|
|
$plugin->data_user->{SessionID} = $SessionID; |
394
|
0
|
|
|
|
|
|
$plugin->set_data_session('__clientip'=> $plugin->ClientIP, '__lastaccess'=> time, '__logintime'=> time, '__user'=> $plugin->data_user->{user}); |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
$plugin->RestReply( |
397
|
|
|
|
|
|
|
'IP access' => $plugin->data_user->{'IP access'}, |
398
|
|
|
|
|
|
|
'user' => $plugin->data_user->{user}, |
399
|
|
|
|
|
|
|
'SessionID' => $SessionID, |
400
|
0
|
|
|
|
|
|
'Max idle seconds' => $plugin->config->{'Session idle timout'}, |
401
|
|
|
|
|
|
|
'auth_message' => $plugin->auth_message, |
402
|
|
|
|
|
|
|
'auth_member_of' => $plugin->auth_member_of ) |
403
|
|
|
|
|
|
|
} |
404
|
|
|
|
|
|
|
|
405
|
0
|
|
|
|
|
|
)foreach 'get', 'post'; |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
#print STDERR "\n*". Data::Dumper::Dumper( $plugin ) ."*\n\n"; |
409
|
|
|
|
|
|
|
#print STDERR "\n*". $plugin->config->{Routes} ."*\n\n"; |
410
|
|
|
|
|
|
|
} |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
|
414
|
1
|
|
|
1
|
|
560
|
use JSON::XS; |
|
1
|
|
|
|
|
2363
|
|
|
1
|
|
|
|
|
97
|
|
415
|
|
|
|
|
|
|
my $obj_json = JSON::XS->new; |
416
|
|
|
|
|
|
|
$obj_json->utf8(1); |
417
|
|
|
|
|
|
|
$obj_json->max_depth(1024); |
418
|
|
|
|
|
|
|
$obj_json->indent(1); |
419
|
|
|
|
|
|
|
$obj_json->pretty(1); |
420
|
|
|
|
|
|
|
$obj_json->space_before(0); |
421
|
|
|
|
|
|
|
$obj_json->space_after(0); |
422
|
|
|
|
|
|
|
$obj_json->max_size(0); |
423
|
|
|
|
|
|
|
$obj_json->relaxed(0); |
424
|
|
|
|
|
|
|
$obj_json->shrink(0); |
425
|
|
|
|
|
|
|
$obj_json->allow_tags(1); |
426
|
|
|
|
|
|
|
$obj_json->allow_nonref(0); |
427
|
|
|
|
|
|
|
$obj_json->allow_unknown(0); |
428
|
|
|
|
|
|
|
$obj_json->allow_blessed(1); |
429
|
|
|
|
|
|
|
$obj_json->convert_blessed(1); |
430
|
|
|
|
|
|
|
|
431
|
1
|
|
|
1
|
|
484
|
use XML::Hash::XS; |
|
1
|
|
|
|
|
659
|
|
|
1
|
|
|
|
|
65
|
|
432
|
|
|
|
|
|
|
$XML::Hash::XS::root='Data'; |
433
|
|
|
|
|
|
|
$XML::Hash::XS::utf8=1; |
434
|
|
|
|
|
|
|
$XML::Hash::XS::encoding='utf8'; |
435
|
|
|
|
|
|
|
$XML::Hash::XS::xml_decl=0; |
436
|
|
|
|
|
|
|
$XML::Hash::XS::indent=2; |
437
|
|
|
|
|
|
|
$XML::Hash::XS::canonical=1; |
438
|
|
|
|
|
|
|
$XML::Hash::XS::doc=0; |
439
|
|
|
|
|
|
|
$XML::Hash::XS::version='1.1'; |
440
|
|
|
|
|
|
|
|
441
|
1
|
|
|
1
|
|
357
|
use YAML::XS; |
|
1
|
|
|
|
|
1769
|
|
|
1
|
|
|
|
|
48
|
|
442
|
|
|
|
|
|
|
$YAML::XS::QuoteNumericStrings=1; |
443
|
|
|
|
|
|
|
|
444
|
1
|
|
|
1
|
|
497
|
use Data::Dumper; |
|
1
|
|
|
|
|
4804
|
|
|
1
|
|
|
|
|
2255
|
|
445
|
|
|
|
|
|
|
$Data::Dumper::Terse=1; |
446
|
|
|
|
|
|
|
$Data::Dumper::Purity=1; |
447
|
|
|
|
|
|
|
$Data::Dumper::Indent=2; |
448
|
|
|
|
|
|
|
$Data::Dumper::Deepcopy=1; |
449
|
|
|
|
|
|
|
$Data::Dumper::Trailingcomma=0; |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
# This is my custom Perl Data Structures recursive walker |
453
|
|
|
|
|
|
|
# it is usefull when you want to view a Complex data structure at human format |
454
|
|
|
|
|
|
|
my %Handler; |
455
|
|
|
|
|
|
|
%Handler = |
456
|
|
|
|
|
|
|
( |
457
|
|
|
|
|
|
|
SCALAR => sub { $Handler{WALKER}->(${$_[0]}, $_[1], @{$_[2]} )}, |
458
|
|
|
|
|
|
|
ARRAY => sub { $Handler{WALKER}->($_, $_[1], @{$_[2]}) for @{$_[0]} }, |
459
|
|
|
|
|
|
|
HASH => sub { $Handler{WALKER}->($_[0]->{$_}, $_[1], @{$_[2]}, $_) for sort keys %{$_[0]} }, |
460
|
|
|
|
|
|
|
'' => sub { $_[1]->($_[0], @{$_[2]}) }, |
461
|
|
|
|
|
|
|
WALKER => sub { my $data = shift; $Handler{ref $data}->($data, shift, \@_) } |
462
|
|
|
|
|
|
|
); |
463
|
|
|
|
|
|
|
|
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
# Convert a string ( data_from ) to a Perl hash reference |
470
|
|
|
|
|
|
|
# as the $obj->{from} defines : json, xml, yaml, perl, human |
471
|
|
|
|
|
|
|
# |
472
|
|
|
|
|
|
|
sub __CONVERT_STRING_TO_HASHREF |
473
|
|
|
|
|
|
|
{ |
474
|
0
|
|
|
0
|
|
|
my $obj = $_[0]; |
475
|
0
|
|
|
|
|
|
@{$obj}{qw/error errormessage/}=(0,'ok'); |
|
0
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
|
477
|
0
|
0
|
0
|
|
|
|
if (( ! defined $obj->{data_from} ) || ( $obj->{data_from} =~/^\s*$/ )) { |
478
|
0
|
|
|
|
|
|
@{$obj}{qw/error errormessage/} = (1, "There are not any data to convert at property data_from"); |
|
0
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
return {} |
480
|
0
|
|
|
|
|
|
} |
481
|
|
|
|
|
|
|
|
482
|
0
|
|
|
|
|
|
my $hash={}; |
483
|
|
|
|
|
|
|
|
484
|
0
|
|
|
|
|
|
eval { |
485
|
0
|
0
|
|
|
|
|
if ( $obj->{from} eq 'json' ) { $hash = JSON::XS::decode_json $obj->{data_from} } |
|
0
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
486
|
0
|
|
|
|
|
|
elsif ( $obj->{from} eq 'xml' ) { $hash = XML::Hash::XS::xml2hash $obj->{data_from} } |
487
|
0
|
|
|
|
|
|
elsif ( $obj->{from} eq 'yaml' ) { $hash = YAML::XS::Load $obj->{data_from} } |
488
|
0
|
|
|
|
|
|
elsif ( $obj->{from} eq 'perl' ) { $hash = eval $obj->{data_from} } |
489
|
0
|
|
|
|
|
|
elsif ( $obj->{from} eq 'human') { my $arrayref; |
490
|
|
|
|
|
|
|
|
491
|
0
|
|
|
|
|
|
while ( $obj->{data_from} =~/(.*)$/gm ) { |
492
|
0
|
|
|
|
|
|
my @array = split /\s*(?:\,| |\t|-->|==>|=>|->|=|;|\|)+\s*/, $1; |
493
|
0
|
0
|
|
|
|
|
next unless @array; |
494
|
|
|
|
|
|
|
|
495
|
0
|
0
|
|
|
|
|
if (@array % 2 == 0) { |
496
|
0
|
|
|
|
|
|
push @{$arrayref}, { @array } |
|
0
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
} |
498
|
|
|
|
|
|
|
else { |
499
|
0
|
|
|
|
|
|
push @{$arrayref}, { shift @array => [ @array ] } |
|
0
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
} |
501
|
|
|
|
|
|
|
} |
502
|
|
|
|
|
|
|
|
503
|
0
|
0
|
|
|
|
|
$hash = 1==scalar @{$arrayref} ? $arrayref->[0] : { 'Data' => $arrayref } |
|
0
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
} |
505
|
|
|
|
|
|
|
}; |
506
|
|
|
|
|
|
|
|
507
|
0
|
0
|
|
|
|
|
if ($@) { |
508
|
0
|
|
|
|
|
|
$hash={}; |
509
|
0
|
|
|
|
|
|
$obj->{error}=1; |
510
|
0
|
|
|
|
|
|
($obj->{errormessage}="The data parsing as $obj->{from} failed. Are you sure your data are at $obj->{from} format ? The low level error is : $@") =~s/[\v\h]+/ /g |
511
|
|
|
|
|
|
|
} |
512
|
|
|
|
|
|
|
$hash |
513
|
0
|
|
|
|
|
|
} |
514
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
# Convert hash reference $_[0] to text and store it at $obj->{data_to} |
518
|
|
|
|
|
|
|
# format of "data_to" is depended from "to" : json xml yaml perl human |
519
|
|
|
|
|
|
|
# |
520
|
|
|
|
|
|
|
# __CONVERT_HASHREF_TO_STRING( $hash_reference ) |
521
|
|
|
|
|
|
|
# print $obj->{error} ? "ERROR : $obj->{errormessage}" : $obj->{data_to}; |
522
|
|
|
|
|
|
|
# |
523
|
|
|
|
|
|
|
sub __CONVERT_HASHREF_TO_STRING |
524
|
|
|
|
|
|
|
{ |
525
|
0
|
|
|
0
|
|
|
my $obj=shift; |
526
|
0
|
|
|
|
|
|
@{$obj}{qw/error errormessage/}=(0,'ok'); |
|
0
|
|
|
|
|
|
|
527
|
0
|
|
|
|
|
|
$obj->{data_to}=''; |
528
|
|
|
|
|
|
|
|
529
|
0
|
|
|
|
|
|
eval { |
530
|
0
|
0
|
|
|
|
|
if ($obj->{to} eq 'json' ) { $obj->{data_to} = $obj_json->encode($_[0]) } |
|
0
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
531
|
0
|
|
|
|
|
|
elsif ($obj->{to} eq 'xml' ) { $obj->{data_to} = XML::Hash::XS::hash2xml $_[0] } |
532
|
0
|
|
|
|
|
|
elsif ($obj->{to} eq 'yaml' ) { $obj->{data_to} = YAML::XS::Dump $_[0] } |
533
|
0
|
|
|
|
|
|
elsif ($obj->{to} eq 'perl' ) { $obj->{data_to} = Data::Dumper::Dumper $_[0] } |
534
|
0
|
|
|
0
|
|
|
elsif ($obj->{to} eq 'human') { $Handler{WALKER}->($_[0], sub {my $val=shift; $val =~s/^\s*(.*?)\s*$/$1/; $obj->{data_to} .= join('.', @_) ." = $val\n"}) } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
535
|
|
|
|
|
|
|
}; |
536
|
|
|
|
|
|
|
|
537
|
0
|
0
|
|
|
|
|
if ($@) { |
538
|
0
|
|
|
|
|
|
@{$obj}{qw/data_to error errormessage/}=('', 1, "The encoding of data hash to $obj->{to} failed. The low level error is : $@"); |
|
0
|
|
|
|
|
|
|
539
|
0
|
|
|
|
|
|
$obj->{errormessage} =~s/[\v\h]+/ /g |
540
|
|
|
|
|
|
|
} |
541
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
$obj->{data_to} |
543
|
0
|
|
|
|
|
|
} |
544
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
# Returns a reply as: json, xml, yaml, perl or human |
551
|
|
|
|
|
|
|
# It always include the error and errormessage |
552
|
|
|
|
|
|
|
# |
553
|
|
|
|
|
|
|
# RestReply error and errormessage |
554
|
|
|
|
|
|
|
# RestReply(k1 => 'v1', ...) specific key/values |
555
|
|
|
|
|
|
|
# RestReply('DATA_USER_SEND') send data |
556
|
|
|
|
|
|
|
# RestReply('DATA_USER_ALL') send data and defined key/value by the user |
557
|
|
|
|
|
|
|
# |
558
|
|
|
|
|
|
|
sub RestReply |
559
|
|
|
|
|
|
|
{ |
560
|
0
|
|
|
0
|
1
|
|
my $plugin = shift; |
561
|
|
|
|
|
|
|
|
562
|
0
|
0
|
|
|
|
|
if (@_) { |
563
|
|
|
|
|
|
|
|
564
|
0
|
0
|
|
|
|
|
if (1 == @_) { |
565
|
|
|
|
|
|
|
|
566
|
0
|
0
|
0
|
|
|
|
if (('DATA_USER_SEND' eq $_[0]) || ('DATA_USER_ALL' eq $_[0])) { |
567
|
0
|
|
|
|
|
|
$plugin->dump_user_properties($_[0]) |
568
|
|
|
|
|
|
|
} |
569
|
|
|
|
|
|
|
else { |
570
|
0
|
0
|
|
|
|
|
$plugin->dump_user_properties({ error=> $plugin->error, errormessage=> $plugin->errormessage, $_[0]=> exists $plugin->data_user->{$_[0]} ? $plugin->data_user->{$_[0]} : 'NOT EXISTING USER DATA' }) |
571
|
|
|
|
|
|
|
} |
572
|
|
|
|
|
|
|
} |
573
|
|
|
|
|
|
|
else { |
574
|
|
|
|
|
|
|
# This the normal operation |
575
|
0
|
|
|
|
|
|
$plugin->dump_user_properties( {error=> $plugin->error, errormessage=> $plugin->errormessage, @_} ) |
576
|
|
|
|
|
|
|
} |
577
|
|
|
|
|
|
|
} |
578
|
|
|
|
|
|
|
else { |
579
|
|
|
|
|
|
|
# if no argument passed then we return only error, errormessage and if exists description |
580
|
0
|
0
|
|
|
|
|
$plugin->dump_user_properties({ error=>$plugin->error, errormessage=>$plugin->errormessage, exists $plugin->data_user->{description} ? ( 'description' , $plugin->data_user->{description} ) : () }) |
581
|
|
|
|
|
|
|
} |
582
|
|
|
|
|
|
|
|
583
|
0
|
0
|
|
|
|
|
if ( $plugin->error ) { |
584
|
0
|
|
|
|
|
|
$plugin->to('json'); |
585
|
0
|
|
|
|
|
|
$plugin->dump_user_properties( { error=>$plugin->error, errormessage=>$plugin->errormessage, description=>'Data conversion error from '.$plugin->from.' to '.$plugin->to } ); |
586
|
0
|
|
|
|
|
|
$plugin->data_user( {} ); |
587
|
0
|
0
|
|
|
|
|
die "DataStructure internal error : ". $plugin->errormessage."\n" if $plugin->error; |
588
|
0
|
|
|
|
|
|
$plugin->app->halt( $plugin->data_to ) |
589
|
|
|
|
|
|
|
} |
590
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
$plugin->data_to |
592
|
0
|
|
|
|
|
|
} |
593
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
|
595
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
# $plugin->dump_user_properties( { k1 => 'v1', ... } ); # specific key/values |
599
|
|
|
|
|
|
|
# $plugin->dump_user_properties( 'DATA_USER_SEND' ); # send data |
600
|
|
|
|
|
|
|
# $plugin->dump_user_properties( 'DATA_USER_ALL' ); # send data and defined key/value by the user |
601
|
|
|
|
|
|
|
# |
602
|
|
|
|
|
|
|
# Answer is a string formatted as $plugin->to( json|yaml|xml|perl|human) |
603
|
|
|
|
|
|
|
# and stored at $plugin->data_to |
604
|
|
|
|
|
|
|
# |
605
|
|
|
|
|
|
|
sub dump_user_properties |
606
|
|
|
|
|
|
|
{ |
607
|
0
|
|
|
0
|
0
|
|
my $plugin = shift; |
608
|
0
|
|
|
|
|
|
my $hash = {}; |
609
|
0
|
|
|
|
|
|
$plugin->data_to(''); |
610
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
# specific user data |
612
|
0
|
0
|
|
|
|
|
if ('HASH' eq ref $_[0]) |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
613
|
|
|
|
|
|
|
{ |
614
|
0
|
|
|
|
|
|
$plugin->__CONVERT_HASHREF_TO_STRING($_[0]) |
615
|
|
|
|
|
|
|
} |
616
|
|
|
|
|
|
|
|
617
|
|
|
|
|
|
|
# user data (all) |
618
|
|
|
|
|
|
|
elsif ('DATA_USER_ALL' eq $_[0]) |
619
|
|
|
|
|
|
|
{ |
620
|
0
|
|
|
|
|
|
$hash->{error} = $plugin->error; |
621
|
0
|
|
|
|
|
|
$hash->{errormessage} = $plugin->errormessage; |
622
|
0
|
|
|
|
|
|
map { $hash->{$_} = $plugin->data_user->{$_} } keys %{ $plugin->data_user }; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
623
|
0
|
|
|
|
|
|
$plugin->__CONVERT_HASHREF_TO_STRING($hash) |
624
|
|
|
|
|
|
|
} |
625
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
# only the send data |
627
|
|
|
|
|
|
|
elsif ('DATA_USER_SEND' eq $_[0]) |
628
|
|
|
|
|
|
|
{ |
629
|
0
|
0
|
|
|
|
|
if ($plugin->from eq $plugin->to) |
630
|
|
|
|
|
|
|
{ |
631
|
0
|
|
|
|
|
|
$_= $plugin->data_from; |
632
|
0
|
|
|
|
|
|
s/^\s*(.*?)\s*$/$1/s; |
633
|
0
|
|
|
|
|
|
$plugin->data_to($_) |
634
|
|
|
|
|
|
|
} |
635
|
|
|
|
|
|
|
else |
636
|
|
|
|
|
|
|
{ |
637
|
0
|
|
|
|
|
|
$hash = $plugin->__CONVERT_STRING_TO_HASHREF; # whatever exists in $plugin->data_from in any format make it hash |
638
|
0
|
|
|
|
|
|
$plugin->__CONVERT_HASHREF_TO_STRING($hash) |
639
|
|
|
|
|
|
|
} |
640
|
|
|
|
|
|
|
} |
641
|
|
|
|
|
|
|
|
642
|
|
|
|
|
|
|
$plugin->data_to |
643
|
0
|
|
|
|
|
|
} |
644
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
# Create nested directories like the mdkir -p ... |
647
|
|
|
|
|
|
|
# |
648
|
|
|
|
|
|
|
sub __MKDIR { |
649
|
0
|
|
|
0
|
|
|
my @Mkdir = split /(?:\\|\/)+/, $_[0]; |
650
|
0
|
0
|
|
|
|
|
return $_[0] unless @Mkdir; |
651
|
0
|
0
|
0
|
|
|
|
splice(@Mkdir, 0, 2, "/$Mkdir[1]") if (($Mkdir[0] eq '') && (scalar @Mkdir > 0)); |
652
|
0
|
|
|
|
|
|
my $i; |
653
|
|
|
|
|
|
|
|
654
|
0
|
|
|
|
|
|
for($i=$#Mkdir; $i>=0; $i--) { |
655
|
0
|
0
|
|
|
|
|
last if -d join '/', @Mkdir[0..$i] |
656
|
|
|
|
|
|
|
} |
657
|
|
|
|
|
|
|
|
658
|
0
|
|
|
|
|
|
for(my $j=$i+1; $j<=$#Mkdir; $j++) { |
659
|
0
|
0
|
|
|
|
|
mkdir join('/', @Mkdir[0 .. $j]) or return undef |
660
|
|
|
|
|
|
|
} |
661
|
0
|
|
|
|
|
|
$_[0] |
662
|
|
|
|
|
|
|
} |
663
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
# Delete session directory and property |
666
|
|
|
|
|
|
|
# |
667
|
|
|
|
|
|
|
sub __Delete_session { |
668
|
0
|
|
|
0
|
|
|
my $plugin = shift; |
669
|
0
|
|
|
|
|
|
my $dir = $plugin->dir_session.'/'.$plugin->data_user->{SessionID}; |
670
|
|
|
|
|
|
|
|
671
|
0
|
0
|
|
|
|
|
if (-d $dir) { |
672
|
0
|
|
|
|
|
|
my $exit_code = system $plugin->rm, '--recursive', '--force', $dir; |
673
|
0
|
0
|
|
|
|
|
if ($exit_code) { $plugin->error(11); $plugin->errormessage('Could not delete session '. $plugin->data_user->{SessionID} ." because $!") } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
} |
675
|
|
|
|
|
|
|
} |
676
|
|
|
|
|
|
|
|
677
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
# Returns the posted or sent data |
679
|
|
|
|
|
|
|
# |
680
|
|
|
|
|
|
|
# my ($var1, $var2) = get_data_user('k1', 'k2'); # returns the selected keys |
681
|
|
|
|
|
|
|
# my %hash = get_data_user(); # returns all data as hash |
682
|
|
|
|
|
|
|
# |
683
|
|
|
|
|
|
|
sub get_data_user |
684
|
|
|
|
|
|
|
{ |
685
|
0
|
|
|
0
|
1
|
|
my $plugin = shift; |
686
|
|
|
|
|
|
|
|
687
|
0
|
0
|
|
|
|
|
if (@_) { |
688
|
0
|
0
|
|
|
|
|
map {exists $plugin->data_user->{$_} ? $plugin->data_user->{$_} : 'NOT EXISTING USER DATA'} @_ |
|
0
|
|
|
|
|
|
|
689
|
|
|
|
|
|
|
} |
690
|
|
|
|
|
|
|
else { |
691
|
0
|
|
|
|
|
|
%{ $plugin->data_user } |
|
0
|
|
|
|
|
|
|
692
|
|
|
|
|
|
|
} |
693
|
|
|
|
|
|
|
} |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
|
696
|
|
|
|
|
|
|
|
697
|
|
|
|
|
|
|
# Set new user data as if they were sent or posted |
698
|
|
|
|
|
|
|
# It returns the data like the get_user_data |
699
|
|
|
|
|
|
|
# |
700
|
|
|
|
|
|
|
# my %data = set_data_user( new1 => 'foo1', new2 => 'foo2' ); # return the keys |
701
|
|
|
|
|
|
|
# my %data = set_data_user( { new1 => 'foo1', new2 => 'foo2' } ); # return the keys |
702
|
|
|
|
|
|
|
# |
703
|
|
|
|
|
|
|
sub set_data_user |
704
|
|
|
|
|
|
|
{ |
705
|
0
|
|
|
0
|
1
|
|
my $plugin = shift; |
706
|
0
|
|
|
|
|
|
my @keys; |
707
|
|
|
|
|
|
|
|
708
|
0
|
0
|
|
|
|
|
if (@_) |
709
|
|
|
|
|
|
|
{ |
710
|
0
|
0
|
0
|
|
|
|
if (( 1 == @_ ) && ( 'HASH' eq ref $_[0] )) { @_ = %{ $_[0] } } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
|
712
|
0
|
|
|
|
|
|
for (my($i,$j)=(0,1); $i < scalar(@_) - (scalar(@_) % 2); $i+=2,$j+=2) |
713
|
|
|
|
|
|
|
{ |
714
|
0
|
|
|
|
|
|
push @keys, $_[$i]; |
715
|
0
|
|
|
|
|
|
$plugin->data_user->{$_[$i]} = $_[$j] |
716
|
|
|
|
|
|
|
} |
717
|
|
|
|
|
|
|
|
718
|
0
|
|
|
|
|
|
%{ $plugin->data_user }{ @keys } |
|
0
|
|
|
|
|
|
|
719
|
|
|
|
|
|
|
} |
720
|
|
|
|
|
|
|
} |
721
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
|
723
|
|
|
|
|
|
|
# Delete user data |
724
|
|
|
|
|
|
|
# |
725
|
|
|
|
|
|
|
# del_data_user( 'k1', 'k2', ... ); # delete only the selected keys |
726
|
|
|
|
|
|
|
# del_data_user(); # delete all keys |
727
|
|
|
|
|
|
|
# |
728
|
|
|
|
|
|
|
sub del_data_user |
729
|
|
|
|
|
|
|
{ |
730
|
0
|
|
|
0
|
1
|
|
my $plugin = shift; |
731
|
|
|
|
|
|
|
|
732
|
0
|
0
|
|
|
|
|
if (@_) { |
733
|
|
|
|
|
|
|
|
734
|
0
|
|
|
|
|
|
foreach (@_) { |
735
|
0
|
0
|
|
|
|
|
delete $plugin->data_user->{$_} if exists $plugin->data_user->{$_} |
736
|
|
|
|
|
|
|
} |
737
|
|
|
|
|
|
|
} |
738
|
|
|
|
|
|
|
else { |
739
|
0
|
|
|
|
|
|
$plugin->data_user({}) |
740
|
|
|
|
|
|
|
} |
741
|
|
|
|
|
|
|
} |
742
|
|
|
|
|
|
|
|
743
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
|
745
|
|
|
|
|
|
|
# Retrieves stored session data |
746
|
|
|
|
|
|
|
# |
747
|
|
|
|
|
|
|
# my %data = get_data_session( 'k1', 'k2', ... ); # return only the selected keys |
748
|
|
|
|
|
|
|
# my %data = get_data_session(); # returs all keys |
749
|
|
|
|
|
|
|
# |
750
|
|
|
|
|
|
|
sub get_data_session |
751
|
|
|
|
|
|
|
{ |
752
|
0
|
|
|
0
|
1
|
|
my $plugin = shift; |
753
|
0
|
0
|
|
|
|
|
unless ( exists $plugin->data_user->{SessionID} ) { $plugin->error(2); $plugin->errormessage('You must login for using persistent session data'); $plugin->data_user({description=>'Get SessionID via login route'}); $plugin->app->halt( $plugin->RestReply ) } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
754
|
0
|
|
|
|
|
|
my $id = $plugin->data_user->{SessionID}; |
755
|
0
|
|
|
|
|
|
my $dir = $plugin->dir_session."/$id"; |
756
|
0
|
0
|
|
|
|
|
unless (-d $dir) { $plugin->error(3); $plugin->errormessage("Invalid or expired SessionID $id"); $plugin->data_user({description=>'Get a valid SessionID via login route'}); $plugin->app->halt( $plugin->RestReply ) } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
757
|
|
|
|
|
|
|
|
758
|
0
|
|
|
|
|
|
my %hash; |
759
|
|
|
|
|
|
|
|
760
|
0
|
0
|
|
|
|
|
if (@_) |
761
|
|
|
|
|
|
|
{ |
762
|
0
|
|
|
|
|
|
foreach (@_) |
763
|
|
|
|
|
|
|
{ |
764
|
0
|
0
|
|
|
|
|
if ( ! -f "$dir/$_" ) { $hash{$_} = "NOT EXISTING SESSION RECORD $_"; next } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
765
|
|
|
|
|
|
|
|
766
|
0
|
0
|
|
|
|
|
if ( $hash{$_} = Storable::retrieve "$dir/$_" ) |
767
|
|
|
|
|
|
|
{ |
768
|
0
|
0
|
|
|
|
|
$hash{$_} = ${ $hash{$_} } if 'SCALAR' eq ref $hash{$_} |
|
0
|
|
|
|
|
|
|
769
|
|
|
|
|
|
|
} |
770
|
|
|
|
|
|
|
else |
771
|
|
|
|
|
|
|
{ |
772
|
0
|
|
|
|
|
|
$plugin->error(1); |
773
|
0
|
|
|
|
|
|
$plugin->errormessage("Could not retrieve from session $id the property $_ because $!"); |
774
|
0
|
|
|
|
|
|
$plugin->app->halt( $plugin->RestReply('error') ) |
775
|
|
|
|
|
|
|
} |
776
|
|
|
|
|
|
|
} |
777
|
|
|
|
|
|
|
|
778
|
0
|
|
|
|
|
|
map { $hash{$_} } @_ |
|
0
|
|
|
|
|
|
|
779
|
|
|
|
|
|
|
} |
780
|
|
|
|
|
|
|
else |
781
|
|
|
|
|
|
|
{ |
782
|
0
|
|
|
|
|
|
opendir __SESSIONDIR, $dir; |
783
|
|
|
|
|
|
|
|
784
|
0
|
|
|
|
|
|
foreach (grep ! /^\.+$/, readdir __SESSIONDIR) |
785
|
|
|
|
|
|
|
{ |
786
|
0
|
0
|
|
|
|
|
next if -d "$dir/$_"; |
787
|
|
|
|
|
|
|
|
788
|
0
|
0
|
|
|
|
|
if ( $hash{$_} = Storable::retrieve "$dir/$_" ) |
789
|
|
|
|
|
|
|
{ |
790
|
0
|
0
|
|
|
|
|
$hash{$_} = ${ $hash{$_} } if 'SCALAR' eq ref $hash{$_} |
|
0
|
|
|
|
|
|
|
791
|
|
|
|
|
|
|
} |
792
|
|
|
|
|
|
|
else |
793
|
|
|
|
|
|
|
{ |
794
|
0
|
|
|
|
|
|
$plugin->error(1); |
795
|
0
|
|
|
|
|
|
$plugin->errormessage("Could not retrieve from session $id the property $_ because $!"); |
796
|
0
|
|
|
|
|
|
$plugin->app->halt( $plugin->RestReply() ) |
797
|
|
|
|
|
|
|
} |
798
|
|
|
|
|
|
|
} |
799
|
|
|
|
|
|
|
|
800
|
0
|
|
|
|
|
|
closedir __SESSIONDIR; |
801
|
0
|
|
|
|
|
|
%hash |
802
|
|
|
|
|
|
|
} |
803
|
|
|
|
|
|
|
} |
804
|
|
|
|
|
|
|
|
805
|
|
|
|
|
|
|
|
806
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
# Set and store session data |
809
|
|
|
|
|
|
|
# Session data are not volatile like the user data. |
810
|
|
|
|
|
|
|
# They are persistent between requests |
811
|
|
|
|
|
|
|
# |
812
|
|
|
|
|
|
|
# set_data_session( new1 => 'foo1', new2 => 'foo2' ); |
813
|
|
|
|
|
|
|
# set_data_session( { new1 => 'foo1', new2 => 'foo2' } ); |
814
|
|
|
|
|
|
|
# |
815
|
|
|
|
|
|
|
sub set_data_session |
816
|
|
|
|
|
|
|
{ |
817
|
0
|
|
|
0
|
1
|
|
my $plugin = shift; |
818
|
0
|
0
|
|
|
|
|
unless ( exists $plugin->data_user->{SessionID} ) { $plugin->error(2); $plugin->errormessage('You must login for using persistent session data'); $plugin->data_user({description=>'Get SessionID via login route'}); $plugin->app->halt( $plugin->RestReply ) } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
819
|
0
|
|
|
|
|
|
my $id = $plugin->data_user->{SessionID}; |
820
|
0
|
|
|
|
|
|
my $dir = $plugin->dir_session."/$id"; |
821
|
0
|
0
|
|
|
|
|
unless (-d $dir) { $plugin->error(3); $plugin->errormessage("Invalid or expired SessionID $id"); $plugin->data_user({description=>'Get a valid SessionID via login route'}); $plugin->app->halt( $plugin->RestReply ) } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
822
|
|
|
|
|
|
|
|
823
|
0
|
0
|
0
|
|
|
|
if (( 1 == @_ ) && ( 'HASH' eq ref $_[0] )) { @_ = %{ $_[0] } } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
824
|
|
|
|
|
|
|
|
825
|
0
|
|
|
|
|
|
for (my($i,$j)=(0,1); $i < scalar(@_) - (scalar(@_) % 2); $i+=2,$j+=2) |
826
|
|
|
|
|
|
|
{ |
827
|
0
|
|
|
|
|
|
my $data = $_[$j]; |
828
|
0
|
0
|
|
|
|
|
$data = \ "$data" unless ref $data; |
829
|
|
|
|
|
|
|
|
830
|
0
|
0
|
|
|
|
|
unless ( Storable::lock_store $data, "$dir/$_[$i]" ) |
831
|
|
|
|
|
|
|
{ |
832
|
0
|
|
|
|
|
|
$plugin->error(1); |
833
|
0
|
|
|
|
|
|
$plugin->errormessage("Could not store at session $id the property $_[$i] because $!"); |
834
|
0
|
|
|
|
|
|
$plugin->app->halt( $plugin->RestReply ) |
835
|
|
|
|
|
|
|
} |
836
|
|
|
|
|
|
|
} |
837
|
|
|
|
|
|
|
} |
838
|
|
|
|
|
|
|
|
839
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
|
841
|
|
|
|
|
|
|
|
842
|
|
|
|
|
|
|
# Delete session data (not sessions) |
843
|
|
|
|
|
|
|
# It never deletes the built in records : __lastaccess, __logintime, __clientip, __user |
844
|
|
|
|
|
|
|
# |
845
|
|
|
|
|
|
|
# del_data_session( 'k1', 'k2', ... ); # delete only the selected keys |
846
|
|
|
|
|
|
|
# del_data_session(); # delete all keys |
847
|
|
|
|
|
|
|
# |
848
|
|
|
|
|
|
|
sub del_data_session |
849
|
|
|
|
|
|
|
{ |
850
|
0
|
|
|
0
|
1
|
|
my $plugin = shift; |
851
|
0
|
0
|
|
|
|
|
unless (exists $plugin->data_user->{SessionID}) { $plugin->error(2); $plugin->errormessage('You must login for using persistent session data'); $plugin->data_user({description=>'Get SessionID via login route'}); $plugin->app->halt( $plugin->RestReply ) } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
852
|
|
|
|
|
|
|
|
853
|
0
|
|
|
|
|
|
my $dir = $plugin->dir_session.'/'.$plugin->data_user->{SessionID}; |
854
|
0
|
0
|
|
|
|
|
unless (-d $dir) { $plugin->error(3); $plugin->errormessage('invalid or expired SessionID '.$plugin->data_user->{SessionID}); $plugin->data_user({description=>'Get a valid SessionID via login route'}); $plugin->app->halt( $plugin->RestReply ) } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
855
|
|
|
|
|
|
|
|
856
|
0
|
0
|
|
|
|
|
if (@_) { |
857
|
|
|
|
|
|
|
|
858
|
0
|
|
|
|
|
|
foreach (@_) { |
859
|
0
|
0
|
|
|
|
|
next if /^__logintime|__lastaccess|__user|__clientip$/; |
860
|
0
|
0
|
|
|
|
|
next unless -f "$dir/$_"; |
861
|
0
|
0
|
|
|
|
|
unless (unlink "$dir/$_") { $plugin->error(5); $plugin->errormessage('Could not delete from session '.$plugin->data_user->{SessionID}." the record $_ because $!"); $plugin->app->halt( $plugin->RestReply ) } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
} |
863
|
|
|
|
|
|
|
} |
864
|
|
|
|
|
|
|
else { |
865
|
0
|
|
|
|
|
|
opendir __SESSIONDIR, $dir; |
866
|
|
|
|
|
|
|
|
867
|
0
|
|
|
|
|
|
foreach (grep ! /^\.+$/, readdir __SESSIONDIR) { |
868
|
0
|
0
|
|
|
|
|
next if /^__logintime|__lastaccess|__user|__clientip$/; |
869
|
0
|
0
|
|
|
|
|
next unless -f "$dir/$_"; |
870
|
0
|
0
|
|
|
|
|
unless (unlink "$dir/$_") { $plugin->error(5); $plugin->errormessage('Could not delete from session '.$plugin->data_user->{SessionID}." the record $_ because $!"); $plugin->app->halt( $plugin->RestReply ) } |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
871
|
|
|
|
|
|
|
} |
872
|
|
|
|
|
|
|
|
873
|
0
|
|
|
|
|
|
closedir __SESSIONDIR |
874
|
|
|
|
|
|
|
} |
875
|
|
|
|
|
|
|
} |
876
|
|
|
|
|
|
|
|
877
|
|
|
|
|
|
|
|
878
|
|
|
|
|
|
|
|
879
|
|
|
|
|
|
|
|
880
|
|
|
|
|
|
|
1; |
881
|
|
|
|
|
|
|
__END__ |