| 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__ |