Filename | /var/www/foswikidev/core/lib/Foswiki/Contrib/JsonRpcContrib/Request.pm |
Statements | Executed 19 statements in 1.07ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 15µs | 28µs | BEGIN@19 | Foswiki::Contrib::JsonRpcContrib::Request::
1 | 1 | 1 | 11µs | 15µs | BEGIN@20 | Foswiki::Contrib::JsonRpcContrib::Request::
1 | 1 | 1 | 10µs | 52µs | BEGIN@28 | Foswiki::Contrib::JsonRpcContrib::Request::
1 | 1 | 1 | 8µs | 103µs | BEGIN@25 | Foswiki::Contrib::JsonRpcContrib::Request::
1 | 1 | 1 | 4µs | 4µs | BEGIN@24 | Foswiki::Contrib::JsonRpcContrib::Request::
1 | 1 | 1 | 4µs | 4µs | BEGIN@26 | Foswiki::Contrib::JsonRpcContrib::Request::
1 | 1 | 1 | 4µs | 4µs | BEGIN@22 | Foswiki::Contrib::JsonRpcContrib::Request::
1 | 1 | 1 | 4µs | 4µs | BEGIN@23 | Foswiki::Contrib::JsonRpcContrib::Request::
1 | 1 | 1 | 3µs | 3µs | BEGIN@27 | Foswiki::Contrib::JsonRpcContrib::Request::
0 | 0 | 0 | 0s | 0s | id | Foswiki::Contrib::JsonRpcContrib::Request::
0 | 0 | 0 | 0s | 0s | initFromString | Foswiki::Contrib::JsonRpcContrib::Request::
0 | 0 | 0 | 0s | 0s | json | Foswiki::Contrib::JsonRpcContrib::Request::
0 | 0 | 0 | 0s | 0s | method | Foswiki::Contrib::JsonRpcContrib::Request::
0 | 0 | 0 | 0s | 0s | namespace | Foswiki::Contrib::JsonRpcContrib::Request::
0 | 0 | 0 | 0s | 0s | new | Foswiki::Contrib::JsonRpcContrib::Request::
0 | 0 | 0 | 0s | 0s | param | Foswiki::Contrib::JsonRpcContrib::Request::
0 | 0 | 0 | 0s | 0s | params | Foswiki::Contrib::JsonRpcContrib::Request::
0 | 0 | 0 | 0s | 0s | toSiteCharSet | Foswiki::Contrib::JsonRpcContrib::Request::
0 | 0 | 0 | 0s | 0s | version | Foswiki::Contrib::JsonRpcContrib::Request::
0 | 0 | 0 | 0s | 0s | writeDebug | Foswiki::Contrib::JsonRpcContrib::Request::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # JSON-RPC for Foswiki | ||||
2 | # | ||||
3 | # Copyright (C) 2011-2015 Michael Daum http://michaeldaumconsulting.com | ||||
4 | # | ||||
5 | # This program is free software; you can redistribute it and/or | ||||
6 | # modify it under the terms of the GNU General Public License | ||||
7 | # as published by the Free Software Foundation; either version 2 | ||||
8 | # of the License, or (at your option) any later version. For | ||||
9 | # more details read LICENSE in the root of this distribution. | ||||
10 | # | ||||
11 | # This program is distributed in the hope that it will be useful, | ||||
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
14 | # | ||||
15 | # As per the GPL, removal of this notice is prohibited. | ||||
16 | |||||
17 | package Foswiki::Contrib::JsonRpcContrib::Request; | ||||
18 | |||||
19 | 2 | 27µs | 2 | 40µs | # spent 28µs (15+12) within Foswiki::Contrib::JsonRpcContrib::Request::BEGIN@19 which was called:
# once (15µs+12µs) by Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@25 at line 19 # spent 28µs making 1 call to Foswiki::Contrib::JsonRpcContrib::Request::BEGIN@19
# spent 12µs making 1 call to strict::import |
20 | 2 | 24µs | 2 | 19µs | # spent 15µs (11+4) within Foswiki::Contrib::JsonRpcContrib::Request::BEGIN@20 which was called:
# once (11µs+4µs) by Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@25 at line 20 # spent 15µs making 1 call to Foswiki::Contrib::JsonRpcContrib::Request::BEGIN@20
# spent 4µs making 1 call to warnings::import |
21 | |||||
22 | 2 | 19µs | 1 | 4µs | # spent 4µs within Foswiki::Contrib::JsonRpcContrib::Request::BEGIN@22 which was called:
# once (4µs+0s) by Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@25 at line 22 # spent 4µs making 1 call to Foswiki::Contrib::JsonRpcContrib::Request::BEGIN@22 |
23 | 2 | 27µs | 1 | 4µs | # spent 4µs within Foswiki::Contrib::JsonRpcContrib::Request::BEGIN@23 which was called:
# once (4µs+0s) by Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@25 at line 23 # spent 4µs making 1 call to Foswiki::Contrib::JsonRpcContrib::Request::BEGIN@23 |
24 | 2 | 23µs | 1 | 4µs | # spent 4µs within Foswiki::Contrib::JsonRpcContrib::Request::BEGIN@24 which was called:
# once (4µs+0s) by Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@25 at line 24 # spent 4µs making 1 call to Foswiki::Contrib::JsonRpcContrib::Request::BEGIN@24 |
25 | 2 | 27µs | 2 | 197µs | # spent 103µs (8+94) within Foswiki::Contrib::JsonRpcContrib::Request::BEGIN@25 which was called:
# once (8µs+94µs) by Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@25 at line 25 # spent 103µs making 1 call to Foswiki::Contrib::JsonRpcContrib::Request::BEGIN@25
# spent 94µs making 1 call to Error::import |
26 | 2 | 21µs | 1 | 4µs | # spent 4µs within Foswiki::Contrib::JsonRpcContrib::Request::BEGIN@26 which was called:
# once (4µs+0s) by Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@25 at line 26 # spent 4µs making 1 call to Foswiki::Contrib::JsonRpcContrib::Request::BEGIN@26 |
27 | 2 | 22µs | 1 | 3µs | # spent 3µs within Foswiki::Contrib::JsonRpcContrib::Request::BEGIN@27 which was called:
# once (3µs+0s) by Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@25 at line 27 # spent 3µs making 1 call to Foswiki::Contrib::JsonRpcContrib::Request::BEGIN@27 |
28 | 2 | 879µs | 2 | 94µs | # spent 52µs (10+42) within Foswiki::Contrib::JsonRpcContrib::Request::BEGIN@28 which was called:
# once (10µs+42µs) by Foswiki::Contrib::JsonRpcContrib::Server::BEGIN@25 at line 28 # spent 52µs making 1 call to Foswiki::Contrib::JsonRpcContrib::Request::BEGIN@28
# spent 42µs making 1 call to constant::import |
29 | |||||
30 | ############################################################################### | ||||
31 | sub new { | ||||
32 | my ( $class, $session ) = @_; | ||||
33 | |||||
34 | my $request = $session->{request}; | ||||
35 | |||||
36 | my $this = bless( {}, $class ); | ||||
37 | |||||
38 | # get json-rpc request object | ||||
39 | my $data = $request->param('POSTDATA'); | ||||
40 | if ($data) { | ||||
41 | $data = toSiteCharSet($data); | ||||
42 | } | ||||
43 | else { | ||||
44 | |||||
45 | # minimal setup | ||||
46 | $data = '{"jsonrpc":"2.0"}'; | ||||
47 | } | ||||
48 | writeDebug("data=$data") if TRACE; | ||||
49 | $this->initFromString($data); | ||||
50 | |||||
51 | # get namespace from path info, maybe separate a REST-like method as well | ||||
52 | my $namespace = $request->pathInfo(); | ||||
53 | my $method; | ||||
54 | if ( $namespace =~ /^\/?([^\/]+)(?:\/(.*))?$/ ) { | ||||
55 | $namespace = $1; | ||||
56 | $method = $2; | ||||
57 | } | ||||
58 | $this->namespace($namespace); | ||||
59 | writeDebug("namespace=$namespace") if TRACE; | ||||
60 | |||||
61 | # override json-rpc params using url params | ||||
62 | foreach my $key ( $request->multi_param() ) { | ||||
63 | next if $key =~ /^(POSTDATA|method|id|jsonrpc)$/; # these are different | ||||
64 | my @vals = map( toSiteCharSet($_), $request->multi_param($key) ); | ||||
65 | if ( scalar(@vals) == 1 ) { | ||||
66 | $this->param( $key => $vals[0] ) | ||||
67 | ; # set json-rpc params using url params | ||||
68 | } | ||||
69 | else { | ||||
70 | $this->param( $key => \@vals ) | ||||
71 | ; # set json-rpc params using url params | ||||
72 | } | ||||
73 | } | ||||
74 | |||||
75 | # copy id from url params to json-rpc request if required | ||||
76 | my $id = $request->param('id') || $this->id(); | ||||
77 | $this->id($id) if defined $id; | ||||
78 | |||||
79 | # copy method to json-rpc request | ||||
80 | $method = $request->param('method') if defined $request->param("method"); | ||||
81 | $this->method($method) if defined $method; | ||||
82 | |||||
83 | # check that this is a http POST | ||||
84 | my $httpMethod = $request->method() || "jsonrpc"; | ||||
85 | |||||
86 | throw Foswiki::Contrib::JsonRpcContrib::Error( -32600, | ||||
87 | "Method must be POST" ) | ||||
88 | unless $httpMethod =~ /post|jsonrpc/i; | ||||
89 | |||||
90 | # some basic checks if this is a proper json-rpc 2.0 request | ||||
91 | |||||
92 | # must have a version tag | ||||
93 | if ( ( $this->version() || '' ) ne "2.0" ) { | ||||
94 | throw Foswiki::Contrib::JsonRpcContrib::Error( -32600, | ||||
95 | "Invalid JSON-RPC request - must be jsonrpc: '2.0'" ); | ||||
96 | } | ||||
97 | |||||
98 | # must have a method | ||||
99 | throw Foswiki::Contrib::JsonRpcContrib::Error( -32600, | ||||
100 | "Invalid JSON-RPC request - no method" ) | ||||
101 | unless defined $this->method(); | ||||
102 | |||||
103 | writeDebug( "method=" . $this->method() ) if TRACE; | ||||
104 | |||||
105 | # must not have any other keys other than these | ||||
106 | foreach my $key ( keys %{ $this->{data} } ) { | ||||
107 | throw Foswiki::Contrib::JsonRpcContrib::Error( -32600, | ||||
108 | "Invalid JSON-RPC request - unknown key $key" ) | ||||
109 | unless $key =~ /^(jsonrpc|method|params|id)$/; | ||||
110 | } | ||||
111 | |||||
112 | return $this; | ||||
113 | } | ||||
114 | |||||
115 | ############################################################################## | ||||
116 | sub initFromString { | ||||
117 | my ( $this, $data ) = @_; | ||||
118 | |||||
119 | # parse json-rpc request | ||||
120 | eval { $this->{data} = $this->json->decode($data); }; | ||||
121 | |||||
122 | if ($@) { | ||||
123 | my $error = $@; | ||||
124 | $error =~ s/,? +at.*$//s; | ||||
125 | throw Foswiki::Contrib::JsonRpcContrib::Error( -32700, | ||||
126 | "Parse error - invalid json-rpc request: $error" ); | ||||
127 | } | ||||
128 | |||||
129 | $this->{data}{params} ||= {}; | ||||
130 | |||||
131 | return $this->{data}; | ||||
132 | } | ||||
133 | |||||
134 | ############################################################################## | ||||
135 | sub version { | ||||
136 | my ( $this, $value ) = @_; | ||||
137 | |||||
138 | $this->{data}{jsonrpc} = $value if defined $value; | ||||
139 | return $this->{data}{jsonrpc}; | ||||
140 | } | ||||
141 | |||||
142 | ############################################################################## | ||||
143 | sub id { | ||||
144 | my ( $this, $value ) = @_; | ||||
145 | |||||
146 | $this->{data}{id} = $value if defined $value; | ||||
147 | return $this->{data}{id}; | ||||
148 | } | ||||
149 | |||||
150 | ############################################################################## | ||||
151 | sub param { | ||||
152 | my ( $this, $key, $value ) = @_; | ||||
153 | |||||
154 | return unless $key; | ||||
155 | |||||
156 | $this->{data}{params}{$key} = $value if defined $value; | ||||
157 | return $this->{data}{params}{$key}; | ||||
158 | } | ||||
159 | |||||
160 | ############################################################################## | ||||
161 | sub params { | ||||
162 | return $_[0]->{data}{params}; | ||||
163 | } | ||||
164 | |||||
165 | ############################################################################## | ||||
166 | sub method { | ||||
167 | my ( $this, $value ) = @_; | ||||
168 | |||||
169 | $this->{data}{method} = $value if defined $value; | ||||
170 | return $this->{data}{method}; | ||||
171 | } | ||||
172 | |||||
173 | ############################################################################## | ||||
174 | sub namespace { | ||||
175 | my ( $this, $value ) = @_; | ||||
176 | |||||
177 | $this->{namespace} = $value if defined $value; | ||||
178 | return $this->{namespace}; | ||||
179 | } | ||||
180 | |||||
181 | ############################################################################## | ||||
182 | sub json { | ||||
183 | my $this = shift; | ||||
184 | |||||
185 | unless ( defined $this->{json} ) { | ||||
186 | $this->{json} = new JSON; | ||||
187 | } | ||||
188 | |||||
189 | return $this->{json}; | ||||
190 | } | ||||
191 | |||||
192 | ################################################################################ | ||||
193 | # static | ||||
194 | sub writeDebug { | ||||
195 | Foswiki::Func::writeDebug("- JsonRpcContrib::Request - $_[0]"); | ||||
196 | } | ||||
197 | |||||
198 | ############################################################################### | ||||
199 | sub toSiteCharSet { | ||||
200 | my $string = shift; | ||||
201 | |||||
202 | return $string unless $string; | ||||
203 | |||||
204 | # Convert to unicode if the core supports it | ||||
205 | return $string if $Foswiki::UNICODE; | ||||
206 | |||||
207 | return $string | ||||
208 | if ( $Foswiki::cfg{Site}{CharSet} =~ /^utf-?8/i ); | ||||
209 | |||||
210 | # If the site charset is not utf-8, need to convert it | ||||
211 | return Encode::encode( | ||||
212 | $Foswiki::cfg{Site}{CharSet}, | ||||
213 | Encode::decode_utf8($string), | ||||
214 | Encode::FB_PERLQQ | ||||
215 | ); | ||||
216 | } | ||||
217 | |||||
218 | 1 | 2µs | 1; |