Merge lp:~vierbergenlars/remotecp-panel/rest into lp:~vierbergenlars/remotecp-panel/trunk
- rest
- Merge into trunk
Status: | Work in progress |
---|---|
Proposed branch: | lp:~vierbergenlars/remotecp-panel/rest |
Merge into: | lp:~vierbergenlars/remotecp-panel/trunk |
Diff against target: |
1426 lines (+970/-117) 33 files modified
api/REST/REST.php (+46/-2) api/REST/checks.php (+57/-0) api/REST/dispatcher.php (+190/-0) api/REST/exceptions.php (+22/-1) api/REST/input.php (+31/-0) api/REST/response.php (+4/-0) api/REST_entry.php (+0/-9) api/auth/auth.php (+2/-3) api/auth/authorize.php (+6/-1) api/modules/database.php (+25/-0) api/modules/database/database.a.php (+12/-0) api/modules/database/database.group.a.php (+44/-0) api/modules/database/database.group.a.user.php (+33/-0) api/modules/database/database.group.php (+30/-0) api/modules/database/database.php (+6/-0) api/modules/database/database.settings.php (+58/-0) api/modules/database/database.site.php (+97/-0) api/modules/database/site/database.site.a.php (+49/-0) api/modules/database/site/database.site.subhandler.php (+13/-0) api/modules/database/site/database.site.user.php (+24/-0) api/modules/user.php (+6/-95) api/modules/user/user.a.php (+19/-0) api/modules/user/user.me.php (+30/-0) api/modules/user/user.php (+29/-0) api/modules/user/user.search.php (+9/-0) api/paths.txt (+77/-0) api/request.php (+4/-1) api/responder.php (+29/-1) inc/groups/groups.php (+1/-1) inc/rdb/auth.php (+1/-1) inc/utils/validDomainName.php (+15/-0) licenses/licenses.txt (+1/-0) zz-schemas/schemas.readme.txt (+0/-2) |
To merge this branch: | bzr merge lp:~vierbergenlars/remotecp-panel/rest |
Related bugs: | |
Related blueprints: |
Create a REST api
(Medium)
REST user module
(Medium)
REST database module
(Medium)
REST mail module
(Low)
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Lars Vierbergen | Pending | ||
Review via email: mp+79881@code.launchpad.net |
Commit message
Description of the change
Add REST API for webservices
- 207. By Launchpad Translations on behalf of vierbergenlars
-
Launchpad automatic translations update.
- 208. By Lars Vierbergen
-
Fix authentication timeout with applications demanding all privileges
- 209. By Lars Vierbergen
-
Working on REST database module
- 210. By Lars Vierbergen
-
Work on database API
Make RESTinput::getParts more powerful
Remove auth for GET user info
Add document describing implemented paths
Make api/request.php HTML compliant - 211. By Lars Vierbergen
-
Always chdir back to previous directory after including a file
Add auth::write_db_groups when issuing PUT on database/{ID}/group
Add GET database/{ID}/group/ {GID} method - 212. By Lars Vierbergen
-
Add some prepared checks and exceptions to REST.
Fix PUT database/{}/group - 213. By Lars Vierbergen
-
Add PUT/POST database/
{}/group/ {} (not tested) - 214. By Lars Vierbergen
-
Add GET database/
{ID}/group/ {GID}/{ GUID} (untested) - 215. By Lars Vierbergen
-
Add assure to RESTcheck
RegExpRESTException fixed
RESTresponse now checks wether status exists before polling it
Remove mysqli_result: :free()
Add extra error handling for PHP errors
Test all untested REST changes - 216. By Lars Vierbergen
-
Add system to defer actions to submodules (REST)
Remove schemas - 217. By Lars Vierbergen
-
Added RESTDispatcher class
Added override of dispatcher directory
Added REST::load to load files outside api
Moved submodules to directories
Splitted user.php - 218. By Lars Vierbergen
-
Fix remote database not imported
Fix dispatcher.php override_namespace
Fix RESTinput::getParts not to return empty array value
Let REST::load use global connections
Add POST {ANID}/group/{ GUID}/{ GUID} - 219. By Lars Vierbergen
-
Make RESTcheck automatically throw exceptions if the second parameter is not set or true
Add PHPDoc and URI override to dispatcher.php
Update other files for new structure - 220. By Lars Vierbergen
-
Add decode function to RESTinput
Change ACI 128 to allow deletion of sites
Implement GET database.site endpoint, GET/POST database.settings endpoint
Add new paths.txt
Add is_valid_domain_ name() function (and license) - 221. By Lars Vierbergen
-
Implement PUT database.site and GET database.site.a
- 222. By Lars Vierbergen
-
Add JSON-P as response type
- 223. By Lars Vierbergen
-
Make RESTcheck:
:parameter_ exists accept arrays - 224. By Lars Vierbergen
-
Implement PUT/DELETE database/
{ID}/site/ {SID}
Add database.site.a. user spec - 225. By Lars Vierbergen
-
dispatcher matches full pattern
Move site handlers to a subhandler
Implement GET database/{ID}/site/ {SID}/user/ {GUID}
Add some endpoints - 226. By Lars Vierbergen
-
Update RESTDispatcher to support * for all characters
Incorporate REST_entry.php into responder.php - 227. By Lars Vierbergen
-
Change dispatcher for the subhandler a bit
Forgot an override in database.site.subhandler
Implement POST/DELETE database.site.user - 228. By Lars Vierbergen
-
Reduce function calls (remove 4 calls)
* REST::dispatch takes the handler for ''
* database.site override is for url site/{GUID}
Unmerged revisions
- 228. By Lars Vierbergen
-
Reduce function calls (remove 4 calls)
* REST::dispatch takes the handler for ''
* database.site override is for url site/{GUID} - 227. By Lars Vierbergen
-
Change dispatcher for the subhandler a bit
Forgot an override in database.site.subhandler
Implement POST/DELETE database.site.user - 226. By Lars Vierbergen
-
Update RESTDispatcher to support * for all characters
Incorporate REST_entry.php into responder.php - 225. By Lars Vierbergen
-
dispatcher matches full pattern
Move site handlers to a subhandler
Implement GET database/{ID}/site/ {SID}/user/ {GUID}
Add some endpoints - 224. By Lars Vierbergen
-
Implement PUT/DELETE database/
{ID}/site/ {SID}
Add database.site.a. user spec - 223. By Lars Vierbergen
-
Make RESTcheck:
:parameter_ exists accept arrays - 222. By Lars Vierbergen
-
Add JSON-P as response type
- 221. By Lars Vierbergen
-
Implement PUT database.site and GET database.site.a
- 220. By Lars Vierbergen
-
Add decode function to RESTinput
Change ACI 128 to allow deletion of sites
Implement GET database.site endpoint, GET/POST database.settings endpoint
Add new paths.txt
Add is_valid_domain_ name() function (and license) - 219. By Lars Vierbergen
-
Make RESTcheck automatically throw exceptions if the second parameter is not set or true
Add PHPDoc and URI override to dispatcher.php
Update other files for new structure
Preview Diff
1 | === modified file 'api/REST/REST.php' |
2 | --- api/REST/REST.php 2011-09-22 16:07:24 +0000 |
3 | +++ api/REST/REST.php 2011-12-11 19:47:27 +0000 |
4 | @@ -3,6 +3,8 @@ |
5 | require('input.php'); |
6 | require('output.php'); |
7 | require('response.php'); |
8 | +require('checks.php'); |
9 | +require('dispatcher.php'); |
10 | class REST { |
11 | const get=1; |
12 | const post=2; |
13 | @@ -10,6 +12,7 @@ |
14 | const delete=4; |
15 | const json=1; |
16 | const serialize=2; |
17 | + const jsonp=3; |
18 | static private $reqUrl=''; |
19 | static private $method=self::get; |
20 | static private $datatype=self::json; |
21 | @@ -17,6 +20,7 @@ |
22 | static private $errorString=NULL; |
23 | static private $latest_output_object=NULL; |
24 | static private $latest_input_object=NULL; |
25 | + static private $check_object=NULL; |
26 | /** |
27 | * Initialisation method for the class |
28 | * @throws MethodNotAllowedException |
29 | @@ -32,6 +36,10 @@ |
30 | self::$datatype=self::serialize; |
31 | header('Content-Type: application/x-php-serialized'); |
32 | } |
33 | + elseif(isset($_GET['callback'])) { //JSON-P request |
34 | + self::$datatype=self::jsonp; |
35 | + header('Content-Type: text/javascript'); |
36 | + } |
37 | elseif(strpos(self::$reqUrl, '.json')!==false){ //Request has .json extention |
38 | self::$datatype=self::json; |
39 | header('Content-Type: application/json'); |
40 | @@ -39,7 +47,7 @@ |
41 | elseif(strpos(self::$reqUrl, '.ser')!==false){ //Request has .ser extention |
42 | self::$datatype=self::serialize; |
43 | header('Content-Type: application/x-php-serialized'); |
44 | - } |
45 | + } |
46 | else { |
47 | header('Content-Type: application/json'); |
48 | throw new UnsupportedMediaTypeException('Please provide an Accept header of \'application/json\' or \'application/x-php-serialized\' or add a .json or .ser extention'); |
49 | @@ -101,6 +109,15 @@ |
50 | return new RESTresponse(self::$datatype,$output,self::$statusCode); |
51 | } |
52 | /** |
53 | + * Gives a check object |
54 | + * @return RESTcheck |
55 | + */ |
56 | + static function check() { |
57 | + if(self::$check_object===NULL) |
58 | + self::$check_object=new RESTcheck; |
59 | + return self::$check_object; |
60 | + } |
61 | + /** |
62 | * Prepares an error for sending |
63 | * @param int $statusCode HTTP status code |
64 | * @param string $errorString String explaining the error |
65 | @@ -130,11 +147,38 @@ |
66 | } |
67 | return $retarr; |
68 | } |
69 | + /** |
70 | + * Returns the method used to request the resource |
71 | + * @return int |
72 | + */ |
73 | static function getMethod() { |
74 | return self::$method; |
75 | } |
76 | + /** |
77 | + * Returns the datatype used to request the resource |
78 | + * @return int |
79 | + */ |
80 | static function getDataType() { |
81 | return self::$datatype; |
82 | } |
83 | + /** |
84 | + * Registers a submodule to launch when a specific URI is requested |
85 | + * @param string $uri The URI pattern to launch on |
86 | + * @param string $file The submodule to load |
87 | + * @return RESTDispatcher |
88 | + */ |
89 | + static function dispatch($uri=NULL,$file=NULL) { |
90 | + return new RESTDispatcher($uri, $file); |
91 | + } |
92 | + /** |
93 | + * Load a file from outside the api with the right path |
94 | + * @param string $file The filename to load |
95 | + */ |
96 | + static function load($file) { |
97 | + global $local_connection,$remote_connection; |
98 | + chdir(__DIR__.'/../..'); |
99 | + require $file; |
100 | + chdir(__DIR__.'/..'); |
101 | + } |
102 | } |
103 | -REST::init(); |
104 | \ No newline at end of file |
105 | +REST::init(); |
106 | |
107 | === added file 'api/REST/checks.php' |
108 | --- api/REST/checks.php 1970-01-01 00:00:00 +0000 |
109 | +++ api/REST/checks.php 2011-12-11 19:47:27 +0000 |
110 | @@ -0,0 +1,57 @@ |
111 | +<?php |
112 | +/** |
113 | + * Implements some nice checks for REST modules |
114 | + */ |
115 | +class RESTcheck { |
116 | + /** |
117 | + * Performs a preg_match, throwing an exception if the subject does not match |
118 | + * @param string $pattern The pattern to check for |
119 | + * @param mixed $subject The string to check |
120 | + * @param string $name The name of the subject (parameter name or other) |
121 | + * @param bool $throw Throw an exception if there is no match |
122 | + * @throws RegExpRESTException |
123 | + * @return bool |
124 | + */ |
125 | + function preg_match($pattern,$subject,$name='',$throw=true) { |
126 | + if(preg_match($pattern,$subject)) return true; |
127 | + if($throw) throw new RegExpRESTException($name, $pattern); |
128 | + return false; |
129 | + } |
130 | + /** |
131 | + * Checks if a named parameter exists in this request |
132 | + * @param string|array $name The name of the parameter to check |
133 | + * @param bool $throw Throw an exception if there is no match |
134 | + * @throws MissingParameterRESTException |
135 | + * @return bool |
136 | + */ |
137 | + function parameter_exists($name,$throw=true) { |
138 | + $inputdata=REST::input()->getData(); |
139 | + if(is_string($name)) { |
140 | + if(isset($inputdata[$name])) return true; |
141 | + if($throw) throw new MissingParameterRESTException($name); |
142 | + } |
143 | + if(is_array($name)) { |
144 | + $missing=array(); |
145 | + foreach($name as $param) { |
146 | + if(!isset($inputdata[$param])) $missing[]=$param; |
147 | + } |
148 | + if(count($missing)==0) return true; |
149 | + if($throw) throw new MissingParameterRESTException($missing); |
150 | + } |
151 | + |
152 | + return false; |
153 | + } |
154 | + /** |
155 | + * Checks if something is true |
156 | + * @param bool $test Test wether this is true |
157 | + * @param Exception $throw Throw this object if it is not true |
158 | + * @throws Exception |
159 | + * @return bool |
160 | + */ |
161 | + function assure($test,Exception &$throw=NULL) { |
162 | + if($test) return true; |
163 | + if($throw instanceof Exception) throw $throw; |
164 | + unset($throw); |
165 | + return false; |
166 | + } |
167 | +} |
168 | |
169 | === added file 'api/REST/dispatcher.php' |
170 | --- api/REST/dispatcher.php 1970-01-01 00:00:00 +0000 |
171 | +++ api/REST/dispatcher.php 2011-12-11 19:47:27 +0000 |
172 | @@ -0,0 +1,190 @@ |
173 | +<?php |
174 | +class RESTDispatcher { |
175 | + /** |
176 | + * Current path override |
177 | + * @var string |
178 | + */ |
179 | + private static $root_path='modules'; |
180 | + /** |
181 | + * Al previous path overrides, to allow revert |
182 | + * @var array |
183 | + */ |
184 | + private static $prev_path=array(); |
185 | + /** |
186 | + * Current namespace override |
187 | + * @var string |
188 | + */ |
189 | + private static $root_namespace=''; |
190 | + /** |
191 | + * Al previous namespace overrides, to allow revert |
192 | + * @var array |
193 | + */ |
194 | + private static $prev_namespaces=array(); |
195 | + /** |
196 | + * Current URI override |
197 | + * @var string |
198 | + */ |
199 | + private static $root_uri=''; |
200 | + /** |
201 | + * Al previous URI overrides, to allow revert |
202 | + * @var array |
203 | + */ |
204 | + private static $prev_uri=array(); |
205 | + /** |
206 | + * The file to load |
207 | + * @var string |
208 | + */ |
209 | + private $file=NULL; |
210 | + /** |
211 | + * Something was already dispatched, stop checking |
212 | + * @var bool |
213 | + */ |
214 | + private $kill=false; |
215 | + /** |
216 | + * Assigns a path to a dispatcher file |
217 | + * @param string $uri Path structure |
218 | + * @param string $file File to load |
219 | + * @throws NotImplementedException |
220 | + * @throws MethodNotAllowedException |
221 | + * @return RESTDispatcher |
222 | + */ |
223 | + function __construct($uri,$file) { |
224 | + if($uri===NULL&&$file===NULL||$this->kill) return $this; |
225 | + if($file!='') $ns=self::$root_namespace.'.'; |
226 | + else $ns=self::$root_namespace; |
227 | + $input=REST::input(); |
228 | + $current_uri=$input->getPart(); |
229 | + $uri=self::$root_uri.$uri; |
230 | + if(substr($uri, -1)=='/') $uri=substr($uri,0,-1); //Remove last / from uri |
231 | + $uri=preg_quote($uri,'/'); |
232 | + $search=array('\\{GUID\\}', '\\{ANID\\}', '\\{NID\\}', '\\{ALPHA\\}', '\\{\\}', '\\*'); |
233 | + $replace=array('[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}', '[0-9A-Za-z]+', '[0-9]+', '[A-Za-z]+', '[^\\/]+', '.*'); |
234 | + $pattern=str_replace($search,$replace,$uri).'\\/?'; |
235 | + if(preg_match('/^'.$pattern.'$/', $current_uri)) { |
236 | + $this->file=self::$root_path.'/'.$ns.$file.'.php'; |
237 | + if(!file_exists($this->file)) throw new NotImplementedException('Module '.$ns.$file.' is not available'); |
238 | + $return=$this->launch(); |
239 | + if($return===false) throw new MethodNotAllowedException('Invalid method for "'.$ns.$file.'"'); |
240 | + $this->kill=true; |
241 | + } |
242 | + return $this; |
243 | + } |
244 | + /** |
245 | + * Open the file to be executed, assign right parameters |
246 | + * @return bool The return value of the file, true means OK, false MethodNotAllowedException |
247 | + */ |
248 | + private function launch() { |
249 | + global $local_connection,$remote_connection; |
250 | + return require $this->file; |
251 | + } |
252 | + /** |
253 | + * Set a new namespace. |
254 | + * @param string $new The new namespace. If a dot (.) is prepended, the previous namespace is extended |
255 | + * @return RESTDispatcher |
256 | + */ |
257 | + function override_namespace($new) { |
258 | + if($this->kill) return $this; |
259 | + self::$prev_namespaces[]=self::$root_namespace; |
260 | + if(strpos($new, '.')===0) $new=self::$root_namespace.$new; |
261 | + self::$root_namespace=$new; |
262 | + return $this; |
263 | + } |
264 | + /** |
265 | + * Set a new path to look for files in |
266 | + * @param string $new The new path. If './' is prepended, the previous path is extended |
267 | + * @throws RuntimeException When path is not a directory |
268 | + * @return RESTDispatcher |
269 | + */ |
270 | + function override_path($new) { |
271 | + if($this->kill) return $this; |
272 | + self::$prev_path[]=self::$root_path; |
273 | + if(strpos($new, './')===0) $new=self::$root_path.'/'.$new; |
274 | + if(!is_dir($new)) throw new RuntimeException('The path '.$new.' does not exist'); |
275 | + self::$root_path=$new; |
276 | + return $this; |
277 | + } |
278 | + /** |
279 | + * Set a new uri to put before the give part |
280 | + * @param string $new The new URI. If './' is prepended, the previous URI is extended |
281 | + * @return RESTDispatcher |
282 | + */ |
283 | + function override_uri($new) { |
284 | + if($this->kill) return $this; |
285 | + self::$prev_uri[]=self::$root_uri; |
286 | + if(strpos($new,'./')===0) $new=self::$root_uri.substr($new, 2); |
287 | + self::$root_uri=$new.'/'; |
288 | + return $this; |
289 | + } |
290 | + /** |
291 | + * Overrides namespace, uri and path |
292 | + * @param string $namespace The new namespace |
293 | + * @param string $uri The new URI |
294 | + * @param string $path The new path |
295 | + * @see RESTDispatcher::override_namespace() |
296 | + * @see RESTDispatcher::override_path() |
297 | + * @see RESTDispatcher::override_uri() |
298 | + * @uses override_namespace() |
299 | + * @uses override_path() |
300 | + * @uses override_uri() |
301 | + * @return RESTDispatcher |
302 | + */ |
303 | + function override($namespace=NULL,$uri=NULL,$path=NULL) { |
304 | + if($this->kill) return $this; |
305 | + if(!is_null($namespace)) $this->override_namespace($namespace); |
306 | + if(!is_null($uri)) $this->override_uri($uri); |
307 | + if(!is_null($path)) $this->override_path($path); |
308 | + return $this; |
309 | + } |
310 | + /** |
311 | + * Puts the previous namespace back |
312 | + * @return RESTDispatcher |
313 | + */ |
314 | + function revert_namespace() { |
315 | + if($this->kill) return $this; |
316 | + self::$root_namespace=array_pop(self::$prev_namespaces); |
317 | + return $this; |
318 | + } |
319 | + /** |
320 | + * Puts the previous path back |
321 | + * @return RESTDispatcher |
322 | + */ |
323 | + function revert_path() { |
324 | + if($this->kill) return $this; |
325 | + self::$root_path=array_pop(self::$prev_path); |
326 | + return $this; |
327 | + } |
328 | + /** |
329 | + * Puts the previous URI back |
330 | + * @return RESTDispatcher |
331 | + */ |
332 | + function revert_uri() { |
333 | + if($this->kill) return $this; |
334 | + self::$root_uri=array_pop(self::$prev_uri); |
335 | + return $this; |
336 | + } |
337 | + /** |
338 | + * Assigns a path to a dispatcher file |
339 | + * @uses RESTDispatcher::__construct(); |
340 | + * @param string $uri Path structure |
341 | + * @param string $file File to load |
342 | + * @return RESTDispatcher |
343 | + */ |
344 | + function dispatch($uri,$file) { |
345 | + if($this->kill) return $this; |
346 | + return $this->__construct($uri,$file); |
347 | + } |
348 | + |
349 | + /** |
350 | + * Debug function |
351 | + * @internal |
352 | + */ |
353 | + function debug() { |
354 | + echo 'Path:'.self::$root_path."\r\n"; |
355 | + var_dump(self::$prev_path); |
356 | + echo 'NS:'.self::$root_namespace."\r\n"; |
357 | + var_dump(self::$prev_namespaces); |
358 | + echo 'URI:'.self::$root_uri."\r\n"; |
359 | + var_dump(self::$prev_uri); |
360 | + return $this; |
361 | + } |
362 | +} |
363 | \ No newline at end of file |
364 | |
365 | === modified file 'api/REST/exceptions.php' |
366 | --- api/REST/exceptions.php 2011-09-07 18:23:04 +0000 |
367 | +++ api/REST/exceptions.php 2011-12-11 19:47:27 +0000 |
368 | @@ -1,4 +1,7 @@ |
369 | <?php |
370 | +/** |
371 | + * Exceptions based on HTTP response codes |
372 | + */ |
373 | class HTTPException extends Exception {} |
374 | class BadRequestException extends HTTPException { |
375 | function __construct($message) { |
376 | @@ -94,4 +97,22 @@ |
377 | function __construct($message) { |
378 | parent::__construct($message, 505); |
379 | } |
380 | -} |
381 | \ No newline at end of file |
382 | +} |
383 | +/** |
384 | + * Exceptions based on REST error conditions |
385 | + */ |
386 | +class MissingParameterRESTException extends BadRequestException { |
387 | + function __construct($param_name) { |
388 | + if(!is_array($param_name)) $param_name=array($param_name); |
389 | + $message='Missing required parameters "'. |
390 | + implode('" ,"',$param_name). |
391 | + '"'; |
392 | + parent::__construct($message); |
393 | + } |
394 | +} |
395 | +class RegExpRESTException extends BadRequestException { |
396 | + function __construct($param_name,$regex) { |
397 | + $message='Parameter "'.$param_name.'" should match the regular expression "'.$regex.'"'; |
398 | + parent::__construct($message); |
399 | + } |
400 | +} |
401 | |
402 | === modified file 'api/REST/input.php' |
403 | --- api/REST/input.php 2011-09-22 13:55:20 +0000 |
404 | +++ api/REST/input.php 2011-12-11 19:47:27 +0000 |
405 | @@ -66,6 +66,19 @@ |
406 | return $this->part; |
407 | } |
408 | /** |
409 | + * Gets the action name separated by / in an array if no id is given. |
410 | + * Gets the action name at position $id if an id is given. |
411 | + * @param int $id The position of the action name |
412 | + * @return mixed Array if no id is given, string if an id is given and exists, false if an id is given and does not exist |
413 | + */ |
414 | + function getParts($id=NULL) { |
415 | + $parts=explode('/',$this->part); |
416 | + if(($last=array_pop($parts))!='') array_push($parts, $last); |
417 | + if($id===NULL) return $parts; |
418 | + if(array_key_exists($id, $parts)) return $parts[$id]; |
419 | + return false; |
420 | + } |
421 | + /** |
422 | * Gets the full querystring |
423 | * @return string |
424 | */ |
425 | @@ -79,4 +92,22 @@ |
426 | function getData() { |
427 | return $this->data; |
428 | } |
429 | + /** |
430 | + * Decodes input data according to the data type |
431 | + * @param string $data The data to decode |
432 | + * @return mixed The decoded data |
433 | + * @throws UnexpectedValueException |
434 | + */ |
435 | + function decode($data) { |
436 | + switch(REST::getDataType()) { |
437 | + case REST::json: |
438 | + return json_decode($data,true); |
439 | + break; |
440 | + case REST::serialize: |
441 | + return unserialize($data); |
442 | + break; |
443 | + default: |
444 | + throw new UnexpectedValueException('REST data type should be json or serialize'); |
445 | + } |
446 | + } |
447 | } |
448 | \ No newline at end of file |
449 | |
450 | === modified file 'api/REST/response.php' |
451 | --- api/REST/response.php 2011-09-07 18:23:04 +0000 |
452 | +++ api/REST/response.php 2011-12-11 19:47:27 +0000 |
453 | @@ -16,6 +16,7 @@ |
454 | */ |
455 | function __construct($dataType,RESToutput $output,$statuscode=200) { |
456 | $this->output=$output->getData(); |
457 | + if(isset($this->output['status'])&&$this->output['status']===false) $statuscode=500; //Our status is not good, 500 error |
458 | $this->dataType=$dataType; |
459 | $this->statuscode=$statuscode; |
460 | } |
461 | @@ -27,6 +28,9 @@ |
462 | if($this->dataType==REST::json) { |
463 | echo json_encode($this->output); |
464 | } |
465 | + elseif($this->dataType==REST::jsonp) { |
466 | + echo $_GET['callback'].'('.json_encode($this->output).');'; |
467 | + } |
468 | elseif($this->dataType==REST::serialize) { |
469 | echo serialize($this->output); |
470 | } |
471 | |
472 | === removed file 'api/REST_entry.php' |
473 | --- api/REST_entry.php 2011-09-18 16:51:00 +0000 |
474 | +++ api/REST_entry.php 1970-01-01 00:00:00 +0000 |
475 | @@ -1,9 +0,0 @@ |
476 | -<?php |
477 | -require 'REST/REST.php'; |
478 | -require 'auth/auth.php'; |
479 | -$module=REST::input()->getModule(); |
480 | -if(!file_exists('modules/'.$module.'.php')) { |
481 | - throw new NotFoundException('Module '.$module.' does not exist'); |
482 | -} |
483 | -require 'modules/'.$module.'.php'; |
484 | - |
485 | |
486 | === modified file 'api/auth/auth.php' |
487 | --- api/auth/auth.php 2011-09-22 15:46:09 +0000 |
488 | +++ api/auth/auth.php 2011-12-11 19:47:27 +0000 |
489 | @@ -1,5 +1,4 @@ |
490 | <?php |
491 | -define('__DEBUG__', true); |
492 | $wd=getcwd(); |
493 | chdir(__DIR__.'/../..'); |
494 | require 'inc/controllers.php'; |
495 | @@ -171,7 +170,7 @@ |
496 | if($aci&16) $return[]=$t->_('Send and remove messages'); |
497 | if($aci&32) $return[]=$t->_('Read all data in your databases'); |
498 | if($aci&64) $return[]=$t->_('Add users to groups in your databases'); |
499 | - if($aci&128) $return[]=$t->_('Create sites in your databases'); |
500 | + if($aci&128) $return[]=$t->_('Create and delete sites in your databases'); |
501 | if($aci&256) $return[]=$t->_('Edit sites in your databases'); |
502 | if($aci&512) $return[]=$t->_('Change site administrators and group administrators in your databases'); |
503 | if($aci&1024) $return[]=$t->_('Add users to your databases'); |
504 | @@ -204,5 +203,5 @@ |
505 | elseif($throw_on_failure) throw new UnauthorizedException('You don\'t have the right permissions'); |
506 | return false; |
507 | } |
508 | - |
509 | + |
510 | } |
511 | |
512 | === modified file 'api/auth/authorize.php' |
513 | --- api/auth/authorize.php 2011-09-22 15:46:09 +0000 |
514 | +++ api/auth/authorize.php 2011-12-11 19:47:27 +0000 |
515 | @@ -58,13 +58,18 @@ |
516 | $time=NULL; |
517 | } |
518 | else { |
519 | - $time=$_POST['auth_time_days']*24*60*60+$_POST['auth_time_hours']*60*60+$_POST['auth_time_mins']*60; |
520 | + $time=(int)$_POST['auth_time_days']*24*60*60+(int)$_POST['auth_time_hours']*60*60+(int)$_POST['auth_time_mins']*60; |
521 | + } |
522 | + if(isset($_POST['time'])) { |
523 | + $time=(int)$_POST['time']; |
524 | + if($time=='') $time=NULL; |
525 | } |
526 | if((int)$cred_info['use']&auth::all) { //Warn again about all permissions |
527 | echo '<h1 class="ui-widget-header ui-corner-top" style="margin-bottom: 0">'.$t->_('Are you really sure?').'</h1>'. |
528 | '<div class="ui-widget-content ui-corner-bottom">'. |
529 | $t->_('You are about to give an application <b>ALL</b> permissions (including deleting and creating accounts)'). |
530 | '<form method="POST"><input type="hidden" name="really_sure" value="reallysure">'. |
531 | + '<input type="hidden" name="time" value="'.htmlspecialchars($time).'">'. |
532 | '<input type="submit" class="gui-button ui-priority-primary" name="authorize" value="'.$t->_('Grant all privileges').'">'. |
533 | '<input type="submit" class="gui-button ui-priority-secondary" name="cancel" value="'.$t->_('Cancel').'"></form>'. |
534 | '</div>'; |
535 | |
536 | === added directory 'api/modules/database' |
537 | === added file 'api/modules/database.php' |
538 | --- api/modules/database.php 1970-01-01 00:00:00 +0000 |
539 | +++ api/modules/database.php 2011-12-11 19:47:27 +0000 |
540 | @@ -0,0 +1,25 @@ |
541 | +<?php |
542 | +$input=REST::input(); |
543 | +$method=REST::getMethod(); |
544 | +auth::init(); |
545 | +auth::granted(auth::read_db,true); |
546 | +if(count($input->getParts())>=1){ |
547 | + $_SERVER['PATH_INFO']='/'.$input->getParts(0); |
548 | + REST::load('inc/rdb/rdb.php'); |
549 | +} |
550 | +REST::dispatch('','') |
551 | +->override('database',NULL,'./database') |
552 | + ->override_uri('{ANID}') |
553 | + ->override('.group','./group') |
554 | + ->dispatch('{GUID}/{GUID}', 'a.user') |
555 | + ->dispatch('{GUID}', 'a') |
556 | + ->dispatch('', '') |
557 | + ->revert_namespace()->revert_uri() |
558 | + ->override('.site','./site/{GUID}','./site') |
559 | + ->dispatch('*','subhandler') |
560 | + ->revert_path() |
561 | + ->dispatch('','') |
562 | + ->revert_namespace()->revert_uri() |
563 | + ->dispatch('settings','settings') |
564 | + ->dispatch('', 'a') |
565 | +; |
566 | |
567 | === added file 'api/modules/database/database.a.php' |
568 | --- api/modules/database/database.a.php 1970-01-01 00:00:00 +0000 |
569 | +++ api/modules/database/database.a.php 2011-12-11 19:47:27 +0000 |
570 | @@ -0,0 +1,12 @@ |
571 | +<?php |
572 | +$input=REST::input(); |
573 | +if(REST::getMethod()!==REST::delete) return false; |
574 | +auth::granted(auth::all,true); |
575 | +if(rdb_auth::$level!=9) throw new UnauthorizedException('You need database admin privileges to delete a database'); |
576 | +$q=array(); |
577 | +$q[]=$local_connection->query('DELETE FROM `remote_databases` WHERE `key`=\''.$local_connection->escape_string($input->getPart().'\'')); |
578 | +$q[]=$local_connection->query('DELETE FROM `remote_databases_assignments` WHERE `key`=\''.$local_connection->escape_string($input->getPart().'\'')); |
579 | +if(!array_search(false, $q,true)) REST::output()->setData(array('status'=>true)); |
580 | +else REST::output()->setData(array('status'=>false)); |
581 | +$q[0]->free(); |
582 | +$q[1]->free(); |
583 | |
584 | === added file 'api/modules/database/database.group.a.php' |
585 | --- api/modules/database/database.group.a.php 1970-01-01 00:00:00 +0000 |
586 | +++ api/modules/database/database.group.a.php 2011-12-11 19:47:27 +0000 |
587 | @@ -0,0 +1,44 @@ |
588 | +<?php |
589 | +$input=REST::input(); |
590 | +REST::load('inc/groups/groups.php'); |
591 | +$GID=$input->getParts(2); |
592 | +switch(REST::getMethod()) { |
593 | + case REST::get: |
594 | + $nameq=$remote_connection->query('SELECT * FROM `groups_names` WHERE UPPER(`gid`)="'.strtoupper($GID).'"'); |
595 | + if($nameq->num_rows!=1) throw new NotFoundException('The group with GID '.$GID.' does not exist'); |
596 | + $name=$nameq->fetch_object()->name; |
597 | + $users=array(); |
598 | + $usersq=$remote_connection->query('SELECT * FROM `groups` WHERE UPPER(`gid`)="'.strtoupper($GID).'"'); |
599 | + while($user=$usersq->fetch_assoc()) { |
600 | + $users[]=array('user'=>$user['user'],'administrator'=>(bool)$user['admin']); |
601 | + } |
602 | + REST::output()->setData(array('name'=>$name,'users'=>$users)); |
603 | + break; |
604 | + case REST::put: |
605 | + auth::granted(auth::write_db_groups,true); |
606 | + $data=$input->getData(); |
607 | + REST::check()->parameter_exists('user'); |
608 | + REST::check()->assure(groups::groupExists($GID),new NotFoundException('The group with GID '.$GID.' does not exist')); |
609 | + REST::check()->assure(groups::isGroupAdmin($GID),new ForbiddenException('You are not an administrator of the group with GID '.$GID)); |
610 | + REST::check()->assure(session::userExists($data['user']),new NotFoundException('The user with GUID '.$data['user'].' does not exist')); |
611 | + if(groups::addUser($data['user'], $GID)) { |
612 | + REST::output()->setData(array('status'=>true)); |
613 | + } |
614 | + else { |
615 | + REST::output()->setData(array('status'=>false,'errors'=>JSError::get())); |
616 | + } |
617 | + break; |
618 | + case REST::post: |
619 | + auth::granted(auth::write_db_groups,true); |
620 | + $data=$input->getData(); |
621 | + REST::check()->parameter_exists('name'); |
622 | + REST::check()->preg_match('/^[A-Za-z_0-9\\-\\(\\)]+$/', $data['name'],'name'); |
623 | + REST::check()->assure(groups::groupExists($GID),new NotFoundException('The group with GID '.$GID.' does not exist')); |
624 | + REST::check()->assure(groups::isGroupAdmin($GID),new ForbiddenException('You are not an administrator of the group with GID '.$GID)); |
625 | + $q=$remote_connection->query('UPDATE `groups_names` SET `name`=\''.$data['name'].'\' WHERE UPPER(`GID`)=\''.strtoupper($GID).'\''); |
626 | + if($q) REST::output()->setData(array('status'=>true)); |
627 | + else REST::output()->setData(array('status'=>false)); |
628 | + break; |
629 | + default: |
630 | + return false; |
631 | +} |
632 | \ No newline at end of file |
633 | |
634 | === added file 'api/modules/database/database.group.a.user.php' |
635 | --- api/modules/database/database.group.a.user.php 1970-01-01 00:00:00 +0000 |
636 | +++ api/modules/database/database.group.a.user.php 2011-12-11 19:47:27 +0000 |
637 | @@ -0,0 +1,33 @@ |
638 | +<?php |
639 | +$input=REST::input(); |
640 | +REST::load('inc/groups/groups.php'); |
641 | +$GID=strtoupper($input->getParts(2)); |
642 | +REST::check()->assure(groups::groupExists($GID),new NotFoundException('The group with GID '.$GID.' does not exist')); |
643 | +REST::check()->assure(session::userExists($input->getParts(3)),new NotFoundException('The user with GUID '.$input->getParts(3).' does not exist')); |
644 | +switch(REST::getMethod()) { |
645 | + case REST::get: |
646 | + $q=$remote_connection->query('SELECT * FROM `groups` WHERE UPPER(`gid`)=\''.$GID.'\' AND `user`=\''.$input->getParts(3).'\''); |
647 | + if(!$q) REST::output()->setData(array('status'=>false)); |
648 | + elseif($q->num_rows==1) REST::output()->setData(array('member'=>true)); |
649 | + else REST::output()->setData(array('member'=>false)); |
650 | + break; |
651 | + case REST::post: |
652 | + auth::granted(auth::write_db_groups,true); |
653 | + REST::check()->parameter_exists('administrator'); |
654 | + $data=$input->getData(); |
655 | + REST::check()->assure($data['administrator']==1||$data['administrator']==0,new BadRequestException('The value of the parameter administrator should either be 0 or 1')); |
656 | + REST::check()->assure(groups::isGroupAdmin($GID),new ForbiddenException('You are not an administrator of the group with GID '.$GID)); |
657 | + $c0=$remote_connection->query('SELECT * FROM `groups` WHERE UPPER(`gid`)=\''.$GID.'\' AND `user`=\''.REST::input()->getParts(3).'\''); |
658 | + if(!$c0) { |
659 | + REST::output()->setData(array('status'=>false)); |
660 | + return; |
661 | + } |
662 | + REST::check()->assure($c0->num_rows==1,new NotFoundException('The user with GUID '.$input->getParts(3).' is not a member of group with GID '.$GID)); |
663 | + $q=$remote_connection->query('UPDATE `groups` SET `admin`='.$data['administrator'].' WHERE `user`=\''.$input->getParts(3).'\' AND UPPER(`gid`)=\''.$GID.'\''); |
664 | + if(!$q) REST::output()->setData(array('status'=>false)); |
665 | + else REST::output()->setData(array('status'=>true)); |
666 | + break; |
667 | + default: |
668 | + return false; |
669 | +} |
670 | + |
671 | |
672 | === added file 'api/modules/database/database.group.php' |
673 | --- api/modules/database/database.group.php 1970-01-01 00:00:00 +0000 |
674 | +++ api/modules/database/database.group.php 2011-12-11 19:47:27 +0000 |
675 | @@ -0,0 +1,30 @@ |
676 | +<?php |
677 | +REST::load('inc/groups/groups.php'); |
678 | +switch(REST::getMethod()) { |
679 | + case REST::get: //List my groups |
680 | + $grps=groups::getMyGroups(); |
681 | + foreach($grps as $grp) { |
682 | + $grpnam=groups::getName($grp); |
683 | + REST::output()->appendData(array('gid'=>$grp,'name'=>$grpnam)); |
684 | + } |
685 | + break; |
686 | + case REST::put: //Create new group |
687 | + auth::granted(auth::write_db_groups,true); |
688 | + $data=REST::input()->getData(); |
689 | + REST::check()->parameter_exists('name'); |
690 | + REST::check()->preg_match('/^[a-zA-Z0-9_]+$/', $data['name'],'name'); |
691 | + REST::check()->assure(!groups::groupExists($data['name']),new ConflictException('This groupname is already in use')); |
692 | + $q=array(); |
693 | + REST::load('inc/utils/guid.php'); |
694 | + $uuid=guid(); |
695 | + $q[]=$remote_connection->query('INSERT INTO `groups_names` VALUES(\''.$uuid.'\', \''.$data['name'].'\')'); |
696 | + $q[]=$remote_connection->query('INSERT INTO `groups` VALUES(\''.$uuid.'\',\''.session::$guid.'\',1)'); |
697 | + if(!array_search(false, $q,true)) { |
698 | + REST::output()->setData(array('status'=>true)); |
699 | + REST::success(201); |
700 | + } |
701 | + else REST::output()->setData(array('status'=>false)); |
702 | + break; |
703 | + default: |
704 | + return false; |
705 | +} |
706 | |
707 | === added file 'api/modules/database/database.php' |
708 | --- api/modules/database/database.php 1970-01-01 00:00:00 +0000 |
709 | +++ api/modules/database/database.php 2011-12-11 19:47:27 +0000 |
710 | @@ -0,0 +1,6 @@ |
711 | +<?php |
712 | +if(REST::getMethod()!==REST::get) return false; |
713 | +$q=$local_connection->query('SELECT `key` FROM `remote_databases_assignments` WHERE `user`="'.$local_connection->escape_string(session::$guid).'"'); |
714 | +while($r=$q->fetch_assoc()){ |
715 | + REST::output()->appendData($r['key']); |
716 | +} |
717 | |
718 | === added file 'api/modules/database/database.settings.php' |
719 | --- api/modules/database/database.settings.php 1970-01-01 00:00:00 +0000 |
720 | +++ api/modules/database/database.settings.php 2011-12-11 19:47:27 +0000 |
721 | @@ -0,0 +1,58 @@ |
722 | +<?php |
723 | +REST::load('inc/utils/doubleExplode.php'); |
724 | +switch (REST::getMethod()) { |
725 | + case REST::get: |
726 | + $settings=array(); |
727 | + $settings['title']=$local_connection->query('SELECT `title` FROM `remote_databases` WHERE `key`=\''.$local_connection->escape_string(REST::input()->getParts(0)).'\'') |
728 | + ->fetch_object()->title; |
729 | + $settingsq=$remote_connection->query('SELECT * FROM `_system_`'); |
730 | + while($setting=$settingsq->fetch_assoc()) { |
731 | + switch($setting['key']) { |
732 | + case 'styles': |
733 | + $styles=explode('|',$setting['value']); |
734 | + break; |
735 | + case 'domains': |
736 | + $domains=explode('|',$setting['value']); |
737 | + break; |
738 | + case 'addons': |
739 | + $addons=doubleExplode('&', '=', $setting['value']); |
740 | + $sortedaddons=array(); |
741 | + foreach($addons as $k=>$v) { |
742 | + array_push($sortedaddons, array('id'=>$k,'name'=>$v)); |
743 | + } |
744 | + break; |
745 | + default: |
746 | + $settings[$setting['key']]=$setting['value']; |
747 | + } |
748 | + } |
749 | + $settings['styles']=$styles; |
750 | + $settings['domains']=$domains; |
751 | + $settings['addons']=$sortedaddons; |
752 | + REST::output()->setData($settings); |
753 | + break; |
754 | + case REST::post: |
755 | + auth::granted(auth::all); |
756 | + $data=REST::input()->getData(); |
757 | + $parameters=array('title'=>null,'domains'=>null); |
758 | + $data=array_intersect_key($data,$parameters); //At least one key from the parameters array should be present |
759 | + REST::check()->assure(count($data)>=1, new MissingParameterRESTException(array('title','domains'))); |
760 | + $q=array(); |
761 | + if(isset($data['title'])) { |
762 | + REST::check()->preg_match('^[a-zA-Z0-9 -_]+$', $data['title'],'title'); |
763 | + $q[]=$local_connection->query('UPDATE `remote_databases` SET `title`=\''.$local_connection->escape_string($data['title']).'\' WHERE `key`=\''.$local_connection->escape_string(REST::input()->getParts(0)).'\''); |
764 | + } |
765 | + if(isset($data['domains'])) { |
766 | + REST::load('inc/utils/validDomainName.php'); |
767 | + $domains=REST::input()->decode($data['domains']); |
768 | + foreach($domains as $domain) { |
769 | + REST::check()->assure(is_valid_domain_name($domain),new BadRequestException($domain.' is not a valid domain name')); |
770 | + } |
771 | + $domains=implode('|',$domains); |
772 | + $q[]=$remote_connection->query('UPDATE `_system_` SET `value`=\''.$domains.'\' WHERE `key`=\'domains\''); |
773 | + } |
774 | + if(in_array(false, $q,true)) REST::output()->setData(array('status'=>false)); |
775 | + else REST::output()->setData(array('status'=>true)); |
776 | + break; |
777 | + default: |
778 | + return false; |
779 | +} |
780 | \ No newline at end of file |
781 | |
782 | === added file 'api/modules/database/database.site.php' |
783 | --- api/modules/database/database.site.php 1970-01-01 00:00:00 +0000 |
784 | +++ api/modules/database/database.site.php 2011-12-11 19:47:27 +0000 |
785 | @@ -0,0 +1,97 @@ |
786 | +<?php |
787 | +switch(REST::getMethod()) { |
788 | + case REST::get: |
789 | + $sitesq=$remote_connection->query('SELECT `site_ref` FROM `system_siteinfo` GROUP BY `site_ref`'); |
790 | + while($site=$sitesq->fetch_assoc()) { |
791 | + REST::output()->appendData($site['site_ref']); |
792 | + } |
793 | + break; |
794 | + case REST::put: |
795 | + auth::granted(auth::write_db_sites_new); |
796 | + REST::check()->parameter_exists(array( |
797 | + 'domain','subdomain','style','language','title','tagline','footer','author' |
798 | + )); |
799 | + $data=REST::input()->getData(); |
800 | + //Check domain |
801 | + $c0=$remote_connection->query('SELECT `value` FROM `_system_` WHERE `key`=\'domains\''); |
802 | + REST::check()->assure($c0->num_rows==1,new GatewayException('Remote database has invalid domain settings in _system_')); |
803 | + $available_domains=explode('|', $c0->fetch_object()->value); |
804 | + $c0->free(); |
805 | + REST::check()->assure(in_array($data['domain'], $available_domains),new BadRequestException('The provided domain is not in the range of valid domains')); |
806 | + //Check subdomain |
807 | + REST::check()->preg_match('/^[a-z0-9\\-]+$/i', $data['subdomain'],'subdomain'); |
808 | + $c1=$remote_connection->query('SELECT * FROM `system_domains` WHERE `url-in`=\''.$data['subdomain'].'.'.$data['domain'].'\''); |
809 | + REST::check()->assure($c1->num_rows==0,new ConflictException('This subdomain is already registered')); |
810 | + $c1->free(); |
811 | + //Check style |
812 | + $c2=$remote_connection->query('SELECT `value` FROM `_system_` WHERE `key`=\'styles\''); |
813 | + if($c2->num_rows!=1) throw new GatewayException('Remote database has invalid style settings in _system_'); |
814 | + $available_styles=explode('|', $c2->fetch_object()->value); |
815 | + $c2->free(); |
816 | + REST::check()->assure(in_array($data['style'], $available_styles),new BadRequestException('The provided style is not in the range of valid styles')); |
817 | + //Check language |
818 | + require __DIR__.'/../../../inc/utils/languageCodes.php'; |
819 | + REST::check()->assure(array_key_exists($data['language'], $languageCodes),new BadRequestException('The provided language is not in the range of valid languages')); |
820 | + //Check title |
821 | + REST::check()->assure(trim($data['title'])!='', new BadRequestException('The provided title should be at least one character')); |
822 | + //Execute registration |
823 | + REST::load('inc/utils/guid.php'); |
824 | + REST::load('inc/utils/doubleExplode.php'); |
825 | + $site_ref=guid(); |
826 | + //Create domain link |
827 | + $x[]=$remote_connection->query('INSERT INTO `system_domains` VALUES(\''.$remote_connection->escape_string($data['subdomain'].'.'.$data['domain']).'\',NULL,\''.$site_ref.'\')'); |
828 | + //Create site constants |
829 | + $x[]=$remote_connection->query('INSERT INTO `system_siteinfo` VALUES(\''.$site_ref.'\',\'SITE_TITLE\',\''.$remote_connection->escape_string(htmlspecialchars($data['title'])).'\')'); |
830 | + $x[]=$remote_connection->query('INSERT INTO `system_siteinfo` VALUES(\''.$site_ref.'\',\'URL_SITE\',\'http://'.$remote_connection->escape_string($data['subdomain'].'.'.$data['domain']).'/\')'); |
831 | + $x[]=$remote_connection->query('INSERT INTO `system_siteinfo` VALUES(\''.$site_ref.'\',\'SITE_AUTHOR\',\''.$remote_connection->escape_string(htmlspecialchars($data['author'])).'\')'); |
832 | + $x[]=$remote_connection->query('INSERT INTO `system_siteinfo` VALUES(\''.$site_ref.'\',\'SITE_SLOGAN\',\''.$remote_connection->escape_string(htmlspecialchars($data['tagline'])).'\')'); |
833 | + $x[]=$remote_connection->query('INSERT INTO `system_siteinfo` VALUES(\''.$site_ref.'\',\'SITE_CSS\',\''.$remote_connection->escape_string($data['style']).'\')'); |
834 | + $x[]=$remote_connection->query('INSERT INTO `system_siteinfo` VALUES(\''.$site_ref.'\',\'SITE_LNG\',\''.$remote_connection->escape_string($data['language']).'\')'); |
835 | + $x[]=$remote_connection->query('INSERT INTO `system_siteinfo` VALUES(\''.$site_ref.'\',\'SITE_FOOTER\',\''.$remote_connection->escape_string($data['footer']).'\')'); |
836 | + $x[]=$remote_connection->query('INSERT INTO `system_siteinfo` VALUES(\''.$site_ref.'\',\'ADMIN_GROUP\',NULL)'); |
837 | + |
838 | + //Create site addons index |
839 | + $x[]=$remote_connection->query("CREATE TABLE `{$site_ref}_addons` (`name` varchar(30) NOT NULL,`reference` varchar(30) NOT NULL,`status` int(1) NOT NULL default '0',`gid` char(36) NULL default NULL,`editable` int(1) NOT NULL default '1') ENGINE=MyISAM DEFAULT CHARSET=latin1"); |
840 | + $q=$remote_connection->query('SELECT * FROM `_system_` WHERE `key`=\'addons\''); //Get installed addons |
841 | + $prepared_q="INSERT INTO `{$site_ref}_addons` (`name`, `reference`, `status`, `gid`, `editable`) VALUES ('CMS', 'cms', 1, NULL, 0),('Column1', 'col1', 1, NULL, 0),('Column 3', 'col3', 1, NULL, 0),('File manager', 'filemanager', 1, NULL, 0)"; |
842 | + $q=$q->fetch_assoc(); |
843 | + $q['value']=preg_replace('@^&?(.*)&?$@', '$1', $q['value']); |
844 | + $addons=doubleExplode('&','=',$q['value']); |
845 | + foreach($addons as $name=>$addon) { |
846 | + $prepared_q.=",('$name', '$addon', 0, NULL, 1)"; |
847 | + } |
848 | + $x[]=$remote_connection->query($prepared_q); //Dump addons into table |
849 | + //Create col1 table |
850 | + $x[]=$remote_connection->query("CREATE TABLE `{$site_ref}_col1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `order` int(5) NOT NULL, `title` varchar(30) NOT NULL, `content` text NOT NULL, `plugin-reference` varchar(30) DEFAULT NULL, `access` int(1) NOT NULL DEFAULT '0', PRIMARY KEY (`id`)) ENGINE=MyISAM DEFAULT CHARSET=latin1"); |
851 | + $remote_connection->query("TRUNCATE TABLE `{$site_ref}_col1`"); //Clean table |
852 | + //Dump col1 contents into table |
853 | + //No contents |
854 | + //Create col3 table |
855 | + $x[]=$remote_connection->query("CREATE TABLE `{$site_ref}_col3` ( `id` int(11) NOT NULL AUTO_INCREMENT, `order` int(5) NOT NULL, `title` varchar(30) NOT NULL, `content` text NOT NULL, `plugin-reference` varchar(30) DEFAULT NULL, `access` int(1) NOT NULL DEFAULT '0', PRIMARY KEY (`id`)) ENGINE=MyISAM DEFAULT CHARSET=latin1"); |
856 | + $remote_connection->query("TRUNCATE TABLE `{$site_ref}_col3`"); //Clean table |
857 | + //Dump col3 contents into table |
858 | + //No contents |
859 | + //Create pageindex table |
860 | + $x[]=$remote_connection->query("CREATE TABLE `{$site_ref}_pageindex` ( `id` int(5) NOT NULL AUTO_INCREMENT, `type` int(1) NOT NULL DEFAULT '0', `page_order` int(5) NOT NULL, `page_title` text COLLATE latin1_general_ci NOT NULL, `link` text COLLATE latin1_general_ci NOT NULL, `access` int(1) NOT NULL DEFAULT '0', `visible` int(11) NOT NULL DEFAULT '1', PRIMARY KEY (`id`)) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;"); |
861 | + $remote_connection->query("TRUNCATE TABLE `{$site_ref}_pageindex`"); //Clean table |
862 | + //Dump pageindex contents into table |
863 | + $x[]=$remote_connection->query("INSERT INTO `{$site_ref}_pageindex` (`id`, `type`, `page_order`, `page_title`, `link`, `access`, `visible`) VALUES(1, 2, 1, 'Home', '', 0, 1)"); |
864 | + //Create pages tables |
865 | + $x[]=$remote_connection->query("CREATE TABLE `{$site_ref}_pages` ( `id` int(11) NOT NULL AUTO_INCREMENT, `page_id` int(5) NOT NULL, `section_order` int(11) NOT NULL DEFAULT '1', `section_title` text COLLATE latin1_general_ci NOT NULL, `section_main` text COLLATE latin1_general_ci NOT NULL, `plugin-reference` varchar(30) COLLATE latin1_general_ci DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci"); |
866 | + $remote_connection->query("TRUNCATE TABLE `{$site_ref}_pages`"); //Clean table |
867 | + //Dump pages contents into table |
868 | + //No contents |
869 | + //Create MySQLfs index table |
870 | + $x[]=$remote_connection->query("CREATE TABLE `{$site_ref}_fs` (`path` varchar(900) NOT NULL,`filename` varchar(100) NOT NULL,`rights` int(3) unsigned zerofill NOT NULL DEFAULT '777',`owner` char(36) DEFAULT NULL,`group` char(36) DEFAULT NULL,`time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,`type` enum('d','f') NOT NULL,`mime` varchar(100) NOT NULL DEFAULT 'application/octet-stream',`size` int(11) unsigned NOT NULL DEFAULT '0',`mfi` int(11) unsigned NOT NULL AUTO_INCREMENT,UNIQUE KEY `path` (`path`,`filename`),UNIQUE KEY `mfi` (`mfi`)) ENGINE=MyISAM"); |
871 | + //Dump MySQLfs primary folder |
872 | + $x[]=$remote_connection->query("INSERT INTO `{$site_ref}_fs` (`path`, `filename`, `rights`, `owner`, `group`, `time`, `type`, `mime`, `size`, `mfi`) VALUES('/', '', 777, NULL, NULL, NULL, 'd', 'application/octet-stream', 0, 1);"); |
873 | + //Create MySQLfs data table |
874 | + $x[]=$remote_connection->query("CREATE TABLE `{$site_ref}_fsdata` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`masterid` int(11) unsigned NOT NULL,`data` blob NOT NULL,PRIMARY KEY (`id`),KEY `masterid` (`masterid`)) ENGINE=MyISAM"); |
875 | + //Assign admin link |
876 | + $x[]=$remote_connection->query("INSERT INTO `sites` VALUES ('".session::$guid."', '{$site_ref}', '')"); |
877 | + if(in_array(false, $x,true)) REST::output()->setData(array('status'=>false)); |
878 | + else REST::output()->setData(array('status'=>true,'id'=>$site_ref)); |
879 | + break; |
880 | + default: |
881 | + return false; |
882 | +} |
883 | \ No newline at end of file |
884 | |
885 | === added directory 'api/modules/database/site' |
886 | === added file 'api/modules/database/site/database.site.a.php' |
887 | --- api/modules/database/site/database.site.a.php 1970-01-01 00:00:00 +0000 |
888 | +++ api/modules/database/site/database.site.a.php 2011-12-11 19:47:27 +0000 |
889 | @@ -0,0 +1,49 @@ |
890 | +<?php |
891 | +switch(REST::getMethod()) { |
892 | + case REST::get: |
893 | + $addons=array(); |
894 | + $users=array(); |
895 | + $q0=$remote_connection->query('SELECT * FROM `'.SITE.'_addons'); |
896 | + while($addon=$q0->fetch_assoc()) { |
897 | + $addons[]=array('name'=>$addon['name'],'identifier'=>$addon['reference'],'status'=>(bool)$addon['status'],'administrator_group'=>$addon['gid'],'editable'=>(bool)$addon['editable']); |
898 | + } |
899 | + $q0->free(); |
900 | + $q1=$remote_connection->query('SELECT * FROM `sites` WHERE `ref`=\''.SITE.'\''); |
901 | + while($user=$q1->fetch_assoc()) { |
902 | + $users[]=array('user'=>$user['user'],'role'=>$user['title']); |
903 | + } |
904 | + $q1->free(); |
905 | + REST::output()->setData(array('addons'=>$addons,'users'=>$users)); |
906 | + break; |
907 | + case REST::put: |
908 | + auth::granted(auth::write_db_sites_edit); |
909 | + REST::check()->parameter_exists('user'); |
910 | + $data=REST::input()->getData(); |
911 | + REST::check()->assure(session::userExists($data['user']),new NotFoundException('This user does not exist')); |
912 | + REST::check()->assure(isSiteFullAdmin(),new ForbiddenException('You are not allowed to add a user to this site')); |
913 | + if(isset($data['role'])) { |
914 | + REST::check()->preg_match('/^[a-zA-Z\\-\\_ ]*$/', $data['role'],'role'); |
915 | + } |
916 | + else { |
917 | + $data['role']=''; |
918 | + } |
919 | + $q=$remote_connection->query('INSERT INTO `sites` VALUES (\''.$data['user'].'\',\''.SITE.'\',\''.$data['role'].'\')'); |
920 | + if($q) REST::output()->setData(array('status'=>true)); |
921 | + else REST::output()->setData(array('status'=>false)); |
922 | + break; |
923 | + case REST::delete: |
924 | + auth::granted(auth::write_db_sites_new); |
925 | + $x=array(); |
926 | + $tables=$remote_connection->query('SHOW TABLES LIKE \''.SITE.'_%\''); |
927 | + while($table=$tables->fetch_array()) { |
928 | + $x[]=$remote_connection->query('DROP TABLE `'.$table[0].'`'); |
929 | + } |
930 | + $x[]=$remote_connection->query('DELETE FROM `system_domains` WHERE `site`=\''.SITE.'\''); |
931 | + $x[]=$remote_connection->query('DELETE FROM `system_siteinfo` WHERE `site_ref`=\''.SITE.'\''); |
932 | + $x[]=$remote_connection->query('DELETE FROM `sites` WHERE `ref`=\''.SITE.'\''); |
933 | + if(!in_array(false,$x,true)) REST::output()->setData(array('status'=>true)); |
934 | + else REST::output()->setData(array('status'=>false)); |
935 | + break; |
936 | + default: |
937 | + return false; |
938 | +} |
939 | |
940 | === added file 'api/modules/database/site/database.site.subhandler.php' |
941 | --- api/modules/database/site/database.site.subhandler.php 1970-01-01 00:00:00 +0000 |
942 | +++ api/modules/database/site/database.site.subhandler.php 2011-12-11 19:47:27 +0000 |
943 | @@ -0,0 +1,13 @@ |
944 | +<?php |
945 | +$site_ref=REST::input()->getParts(2); |
946 | +$_GET['site']=$site_ref; |
947 | +REST::load('inc/accountlevels.php'); |
948 | +REST::load('inc/groups/groups.php'); |
949 | +$sitecheck=$remote_connection->query('SELECT COUNT(*) FROM `sites` WHERE `user`=\''.session::$guid.'\' AND `ref`=\''.$site_ref.'\'')->fetch_array(); |
950 | +REST::check()->assure($sitecheck[0]==1, new UnauthorizedException('You do not have access to this site')); |
951 | +//Running at database/{ID}/site/{GUID} |
952 | +REST::dispatch('','a') |
953 | +->dispatch('user/{GUID}','user') |
954 | +->dispatch('addon','addon') |
955 | +->dispatch('addon/*','addon.subhandler') |
956 | +; |
957 | |
958 | === added file 'api/modules/database/site/database.site.user.php' |
959 | --- api/modules/database/site/database.site.user.php 1970-01-01 00:00:00 +0000 |
960 | +++ api/modules/database/site/database.site.user.php 2011-12-11 19:47:27 +0000 |
961 | @@ -0,0 +1,24 @@ |
962 | +<?php |
963 | +$username=REST::input()->getParts(4); |
964 | +$sitecheck=$remote_connection->query('SELECT * FROM `sites` WHERE `user`=\''.$username.'\' AND `ref`=\''.SITE.'\''); |
965 | +REST::check()->assure($sitecheck->num_rows==1, new NotFoundException('This user is not a member of this site')); |
966 | +switch(REST::getMethod()) { |
967 | + case REST::get: |
968 | + $role=$sitecheck->fetch_object()->title; |
969 | + REST::output()->setData(array('role'=>$role)); |
970 | + break; |
971 | + case REST::post: |
972 | + REST::check()->parameter_exists('role'); |
973 | + $data=REST::input()->getData(); |
974 | + $q=$remote_connection->query('UPDATE `sites` SET `title`=\''.$remote_connection->escape_string($data['role']).'\' WHERE `user`=\''.$username.'\' AND `ref`=\''.SITE.'\''); |
975 | + if($q) REST::output()->setData(array('status'=>true)); |
976 | + else REST::output()->setData(array('status'=>false)); |
977 | + break; |
978 | + case REST::delete: |
979 | + $q=$remote_connection->query('DELETE FROM `sites` WHERE `user`=\''.$username.'\' AND `ref`=\''.SITE.'\''); |
980 | + if($q) REST::output()->setData(array('status'=>true)); |
981 | + else REST::output()->setData(array('status'=>false)); |
982 | + break; |
983 | + default: |
984 | + return false; |
985 | +} |
986 | \ No newline at end of file |
987 | |
988 | === added directory 'api/modules/user' |
989 | === modified file 'api/modules/user.php' |
990 | --- api/modules/user.php 2011-09-22 16:07:24 +0000 |
991 | +++ api/modules/user.php 2011-12-11 19:47:27 +0000 |
992 | @@ -1,98 +1,9 @@ |
993 | <?php |
994 | $input=REST::input(); |
995 | $method=REST::getMethod(); |
996 | -if($input->getPart()=='') { |
997 | - switch ($method) { |
998 | - case REST::get: //List |
999 | - $q=$local_connection->query('SELECT `GUID`,`username` FROM `users`'); |
1000 | - while($r=$q->fetch_assoc()) { |
1001 | - REST::output()->appendData($r); |
1002 | - } |
1003 | - break; |
1004 | - case REST::put: //Create new |
1005 | - auth::init(); |
1006 | - auth::granted(auth::all,true); |
1007 | - if(!session::isAdmin()) throw new UnauthorizedException('You need admin privileges to create a user'); |
1008 | - $data=$input->getData(); |
1009 | - if(!isset($data['username'],$data['password'],$data['email'])) throw new BadRequestException('Please provide username, password and email parameters'); |
1010 | - if(session::register($data['username'], $data['password'], $data['email'])) { |
1011 | - REST::output()->setData(array('status'=>true,'errors'=>array())); |
1012 | - REST::success(201); |
1013 | - } |
1014 | - else { |
1015 | - $errors=JSError::get(); |
1016 | - REST::output()->setData(array('status'=>false,'errors'=>$errors)); |
1017 | - } |
1018 | - break; |
1019 | - default: |
1020 | - throw new MethodNotAllowedException('Invalid method for "'.$input->getPart().'" on "'.$input->getModule().'"'); |
1021 | - } |
1022 | -} |
1023 | -else if(strlen($input->getPart())==36&&preg_match('/^[0-9A-F]{8}-([0-9A-F]{4}-){3}[0-9A-F]{12}$/i', $input->getPart())) { //User by guid |
1024 | - switch ($method) { |
1025 | - case REST::get: //Show user info |
1026 | - auth::init(); |
1027 | - $q=$local_connection->query('SELECT `GUID`,`username` FROM `users` WHERE `GUID`=\''.$local_connection->escape_string($input->getPart()).'\''); |
1028 | - if($q->num_rows!=1) throw new NotFoundException('This user does not exist'); |
1029 | - $data=$q->fetch_assoc(); |
1030 | - REST::output()->setData($data); |
1031 | - break; |
1032 | - case REST::delete: //Delete this user |
1033 | - auth::init(); |
1034 | - auth::granted(auth::all,true); |
1035 | - if(!session::isAdmin()) throw new UnauthorizedException('You need admin privileges to delete a user'); |
1036 | - $q=$local_connection->query('DELETE FROM `users` WHERE `GUID`=\''.$local_connection->escape_string($input->getPart().'\'')); |
1037 | - if($q) REST::output()->setData(array('status'=>true)); |
1038 | - else REST::output()->setData(array('status'=>false)); |
1039 | - default: |
1040 | - throw new MethodNotAllowedException('Invalid method for "'.$input->getPart().'" on "'.$input->getModule().'"'); |
1041 | - } |
1042 | -} |
1043 | -elseif($input->getPart()=='search') { |
1044 | - switch($method) { |
1045 | - case REST::get: |
1046 | - $data=$input->getData(); |
1047 | - if(!isset($data['username'])) $data['username']=''; |
1048 | - $q=$local_connection->query('SELECT `GUID`,`username` FROM `users` WHERE `username` LIKE \''.$local_connection->escape_string($data['username']).'\''); |
1049 | - while($r=$q->fetch_assoc()){ |
1050 | - REST::output()->appendData($r); |
1051 | - } |
1052 | - break; |
1053 | - default: |
1054 | - throw new MethodNotAllowedException('Invalid method for "'.$input->getPart().'" on "'.$input->geModule().'"'); |
1055 | - } |
1056 | -} |
1057 | -elseif($input->getPart()=='me') { |
1058 | - switch ($method) { |
1059 | - case REST::get: //Show user info |
1060 | - auth::init(); |
1061 | - $mail=auth::granted(auth::read_mail_addr); |
1062 | - $lang=auth::granted(auth::read_lang); |
1063 | - $q=$local_connection->query('SELECT `GUID`,`username`'.($mail?',`email`':'').($lang?',`lang`':'').' FROM `users` WHERE `GUID`=\''.$local_connection->escape_string(session::$guid).'\''); |
1064 | - if($q->num_rows!=1) throw new GoneException('Authenticated user no longer exists'); |
1065 | - $data=$q->fetch_assoc(); |
1066 | - if(isset($data['lang'])) $data['lang']=unserialize($data['lang']); |
1067 | - REST::output()->setData($data); |
1068 | - break; |
1069 | - case REST::post: //Update user info |
1070 | - auth::init(); |
1071 | - auth::granted(auth::write_lang,true); |
1072 | - $data=$input->getData(); |
1073 | - if(!isset($data['lang'])) throw new BadRequestException('Please provide lang parameter'); |
1074 | - $data['lang']=(REST::getDataType()==REST::json?json_decode($data['lang']):unserialize($data['lang'])); |
1075 | - if(!is_array($data['lang'])) throw new BadRequestException('Please provide a valid lang parameter'); |
1076 | - $q=$local_connection->query('UPDATE `users` SET `lang`=\''.serialize($data['lang']).'\' WHERE `GUID`=\''.$local_connection->escape_string(session::$guid).'\''); |
1077 | - if($q) { |
1078 | - REST::output()->setData(array('status'=>true)); |
1079 | - } |
1080 | - else { |
1081 | - REST::output()->setData(array('status'=>false)); |
1082 | - } |
1083 | - break; |
1084 | - default: |
1085 | - throw new MethodNotAllowedException('Invalid method for "'.$input->getPart().'" on "'.$input->getModule().'"'); |
1086 | - } |
1087 | -} |
1088 | -else { |
1089 | - throw new NotImplementedException('"'.$input->getPart().'" is not implemented in the module "'.$input->getModule().'"'); |
1090 | -} |
1091 | \ No newline at end of file |
1092 | +REST::dispatch() |
1093 | +->override('user',NULL,'./user') |
1094 | +->dispatch('{GUID}', 'a') |
1095 | +->dispatch('search', 'search') |
1096 | +->dispatch('me', 'me') |
1097 | +->dispatch('', ''); |
1098 | \ No newline at end of file |
1099 | |
1100 | === added file 'api/modules/user/user.a.php' |
1101 | --- api/modules/user/user.a.php 1970-01-01 00:00:00 +0000 |
1102 | +++ api/modules/user/user.a.php 2011-12-11 19:47:27 +0000 |
1103 | @@ -0,0 +1,19 @@ |
1104 | +<?php |
1105 | +$input=REST::input(); |
1106 | +switch (REST::getMethod()) { |
1107 | + case REST::get: //Show user info |
1108 | + $q=$local_connection->query('SELECT `GUID`,`username` FROM `users` WHERE `GUID`=\''.$local_connection->escape_string($input->getPart()).'\''); |
1109 | + if($q->num_rows!=1) throw new NotFoundException('This user does not exist'); |
1110 | + $data=$q->fetch_assoc(); |
1111 | + REST::output()->setData($data); |
1112 | + break; |
1113 | + case REST::delete: //Delete this user |
1114 | + auth::init(); |
1115 | + auth::granted(auth::all,true); |
1116 | + REST::check()->assure(session::isAdmin(),new UnauthorizedException('You need admin privileges to delete a user')); |
1117 | + $q=$local_connection->query('DELETE FROM `users` WHERE `GUID`=\''.$local_connection->escape_string($input->getPart().'\'')); |
1118 | + if($q) REST::output()->setData(array('status'=>true)); |
1119 | + else REST::output()->setData(array('status'=>false)); |
1120 | + default: |
1121 | + return false; |
1122 | +} |
1123 | \ No newline at end of file |
1124 | |
1125 | === added file 'api/modules/user/user.me.php' |
1126 | --- api/modules/user/user.me.php 1970-01-01 00:00:00 +0000 |
1127 | +++ api/modules/user/user.me.php 2011-12-11 19:47:27 +0000 |
1128 | @@ -0,0 +1,30 @@ |
1129 | +<?php |
1130 | +switch (REST::getMethod()) { |
1131 | + case REST::get: //Show user info |
1132 | + auth::init(); |
1133 | + $mail=auth::granted(auth::read_mail_addr); |
1134 | + $lang=auth::granted(auth::read_lang); |
1135 | + $q=$local_connection->query('SELECT `GUID`,`username`'.($mail?',`email`':'').($lang?',`lang`':'').' FROM `users` WHERE `GUID`=\''.$local_connection->escape_string(session::$guid).'\''); |
1136 | + if($q->num_rows!=1) throw new GoneException('Authenticated user no longer exists'); |
1137 | + $data=$q->fetch_assoc(); |
1138 | + if(isset($data['lang'])) $data['lang']=unserialize($data['lang']); |
1139 | + REST::output()->setData($data); |
1140 | + break; |
1141 | + case REST::post: //Update user info |
1142 | + auth::init(); |
1143 | + auth::granted(auth::write_lang,true); |
1144 | + $data=REST::input()->getData(); |
1145 | + REST::check()->parameter_exists('lang'); |
1146 | + $data['lang']=(REST::getDataType()==REST::json?json_decode($data['lang']):unserialize($data['lang'])); |
1147 | + if(!is_array($data['lang'])) throw new BadRequestException('Please provide a valid lang parameter'); |
1148 | + $q=$local_connection->query('UPDATE `users` SET `lang`=\''.serialize($data['lang']).'\' WHERE `GUID`=\''.$local_connection->escape_string(session::$guid).'\''); |
1149 | + if($q) { |
1150 | + REST::output()->setData(array('status'=>true)); |
1151 | + } |
1152 | + else { |
1153 | + REST::output()->setData(array('status'=>false)); |
1154 | + } |
1155 | + break; |
1156 | + default: |
1157 | + return false; |
1158 | +} |
1159 | \ No newline at end of file |
1160 | |
1161 | === added file 'api/modules/user/user.php' |
1162 | --- api/modules/user/user.php 1970-01-01 00:00:00 +0000 |
1163 | +++ api/modules/user/user.php 2011-12-11 19:47:27 +0000 |
1164 | @@ -0,0 +1,29 @@ |
1165 | +<?php |
1166 | +$input=REST::input(); |
1167 | +switch (REST::getMethod()) { |
1168 | + case REST::get: //List |
1169 | + $q=$local_connection->query('SELECT `GUID`,`username` FROM `users`'); |
1170 | + while($r=$q->fetch_assoc()) { |
1171 | + REST::output()->appendData($r); |
1172 | + } |
1173 | + break; |
1174 | + case REST::put: //Create new |
1175 | + auth::init(); |
1176 | + auth::granted(auth::all,true); |
1177 | + REST::check()->assure(session::isAdmin(),new UnauthorizedException('You need admin privileges to create a user')); |
1178 | + $data=$input->getData(); |
1179 | + REST::check()->parameter_exists('username'); |
1180 | + REST::check()->parameter_exists('password'); |
1181 | + REST::check()->parameter_exists('email'); |
1182 | + if(session::register($data['username'], $data['password'], $data['email'])) { |
1183 | + REST::output()->setData(array('status'=>true,'errors'=>array())); |
1184 | + REST::success(201); |
1185 | + } |
1186 | + else { |
1187 | + $errors=JSError::get(); |
1188 | + REST::output()->setData(array('status'=>false,'errors'=>$errors)); |
1189 | + } |
1190 | + break; |
1191 | + default: |
1192 | + return false; |
1193 | +} |
1194 | \ No newline at end of file |
1195 | |
1196 | === added file 'api/modules/user/user.search.php' |
1197 | --- api/modules/user/user.search.php 1970-01-01 00:00:00 +0000 |
1198 | +++ api/modules/user/user.search.php 2011-12-11 19:47:27 +0000 |
1199 | @@ -0,0 +1,9 @@ |
1200 | +<?php |
1201 | +if(REST::getMethod()!==REST::get) return false; |
1202 | +$data=REST::input()->getData(); |
1203 | +REST::check()->parameter_exists('username'); |
1204 | +$q=$local_connection->query('SELECT `GUID`,`username` FROM `users` WHERE `username` LIKE \''.$local_connection->escape_string($data['username']).'\''); |
1205 | +REST::output()->setData(array('matches'=>$q->num_rows)); |
1206 | +while($r=$q->fetch_assoc()){ |
1207 | + REST::output()->appendData($r); |
1208 | +} |
1209 | \ No newline at end of file |
1210 | |
1211 | === added file 'api/paths.txt' |
1212 | --- api/paths.txt 1970-01-01 00:00:00 +0000 |
1213 | +++ api/paths.txt 2011-12-11 19:47:27 +0000 |
1214 | @@ -0,0 +1,77 @@ |
1215 | +RemoteCP API paths |
1216 | +------------------ |
1217 | +1. User (user.*) |
1218 | +------- |
1219 | +GET user Show all usernames and GUIDs (user.core) |
1220 | +PUT user (AUTH::all, session::isAdmin()) Create a new user (needs 'username', 'password', 'email') (user.core) |
1221 | +GET user/{GUID} Show information about user with GUID {GUID} (user.a) |
1222 | +DELETE user/{GUID} (AUTH::all, session::isAdmin()) Delete the user with GUID {GUID} (user.a) |
1223 | +GET user/search Search for a username matching the pattern in 'username' (needs 'username') (user.search- |
1224 | +GET user/me Get information about the authenticated user (user.me) |
1225 | +POST user/me (AUTH::write_lang) Update user information of the authenticated user (needs 'lang':array) (user.me) |
1226 | + |
1227 | +2. Database (AUTH::read_db) (database.*) |
1228 | +--------------------------- |
1229 | +GET database Show all databases accessible by the authenticated user (database.core) |
1230 | +DELETE database/{ID} (AUTH::all, rdb_auth::$level=9) Delete the database with id {ID} (database.a) |
1231 | + |
1232 | +2.1. Groups (database.group) |
1233 | +----------- |
1234 | +GET database/{ID}/group Get all groups of the user |
1235 | +PUT database/{ID}/group (AUTH::write_db_groups) Add a group |
1236 | + |
1237 | +2.1.1. A group (database.group.a) |
1238 | +-------------- |
1239 | +GET database/{ID}/group/{GID} Gets information about a group: name and users |
1240 | +PUT database/{ID}/group/{GID} (AUTH::write_db_groups) Adds a new user to group {GID} (needs 'user':GUID) |
1241 | +POST database/{ID}/group/{GID} (AUTH::write_db_groups) Change group information of group {GID} (needs 'name') |
1242 | + |
1243 | +2.1.1.1. Users in a group (database.group.a.user) |
1244 | +------------------------- |
1245 | +GET database/{ID}/group/{GID}/{GUID} Checks if the user {GUID} belongs to the group {GID} |
1246 | +POST database/{ID}/group/{GID}/{GUID} (AUTH::write_db_groups) Changes properties of the user {GUID} in the group {GID} (needs 'administrator':bool) |
1247 | + |
1248 | +2.2. Sites (database.site) |
1249 | +---------- |
1250 | +GET database/{ID}/site Gets all sites on the database |
1251 | +PUT database/{ID}/site (AUTH::write_db_sites_new) Create a new site (needs:'domain','subdomain','style','language','title','tagline','footer','author') |
1252 | + |
1253 | +2.2.1. A site (database.site.a) |
1254 | +------------- |
1255 | +GET database/{ID}/site/{SID} Retrieves all addons and users of the site (+ user level and addon status) |
1256 | +PUT database/{ID}/site/{SID} (AUTH::write_db_sites_edit) Add a new user to the site (needs:'user',optional:'role') |
1257 | +DELETE database/{ID}/site/{SID} (AUTH::write_db_sites_new) Removes a site |
1258 | + |
1259 | +2.2.1.1. A site user (database.site.user) |
1260 | +-------------------- |
1261 | +GET database/{ID}/site/{SID}/user/{GUID} Retieve user role on the site |
1262 | +POST database/{ID}/site/{SID}/user/{GUID} (AUTH::write_db_sites_edit) Change the role of a user (needs: 'role') |
1263 | +DELETE database/{ID}/site/{SID}/user/{GUID} (AUTH::write_db_sites_edit) Remove a user from the site editors |
1264 | + |
1265 | +2.2.1.2. Addons of a site (database.site.addon) |
1266 | +------------------------- |
1267 | +*GET database/{ID}/site/{SID}/addon Retieves a list of installed, a list of available addons and a list of addons available on runner but not on panel |
1268 | +*PUT database/{ID}/site/{SID}/addon (AUTH::write_db_sites_edit) Forwarded to ./{AID} where {AID}=addon (needs:'addon') |
1269 | +*POST database/{ID}/site/{SID}/addon (AUTH::write_db_sites_edit) Changes the administrator group of an addon (needs:'addon','admingroup') |
1270 | + |
1271 | +2.2.1.2.1 An addon (database.site.addon.subhandler) (Recommended: Implementation may vary) |
1272 | +------------------ |
1273 | +*GET database/{ID}/site/{SID}/addon/{AID} Retieves a list of exposed functions |
1274 | +*POST database/{ID}/site/{SID}/addon/{AID} (AUTH::write_db_sites_edit) Forwarded to .. where addon={AID} |
1275 | +*PUT database/{ID}/site/{SID}/addon/{AID} (AUTH::write_db_sites_edit) Installs the addon |
1276 | +*DELETE database/{ID}/site/{SID}/addon/{AID} (AUTH::write_db_sites_edit) Removes the addon |
1277 | + |
1278 | +2.3. Database settings (database.settings) |
1279 | +---------------------- |
1280 | +GET database/{ID}/settings Retrieve all information about the database (no credentials) |
1281 | +POST database/{ID}/settings (AUTH::all) Update database information (no credentials) |
1282 | + |
1283 | +2.4. Database users (database.user) |
1284 | +------------------- |
1285 | +*GET database/{ID}/user Gets all users allowed to access the database |
1286 | +*PUT database/{ID}/user Adds a new user allowed to access the database |
1287 | + |
1288 | +2.4.1 A database user (database.user.a) |
1289 | +--------------------- |
1290 | +*POST database/{ID}/user/{GUID} Change user admin state (needs:'administrator':bool) |
1291 | +*DELETE database/{ID}/user/{GUID} Remove a user from the database |
1292 | \ No newline at end of file |
1293 | |
1294 | === modified file 'api/request.php' |
1295 | --- api/request.php 2011-09-22 13:55:20 +0000 |
1296 | +++ api/request.php 2011-12-11 19:47:27 +0000 |
1297 | @@ -1,4 +1,6 @@ |
1298 | <?php |
1299 | +echo '<!DOCTYPE ><html><head><title>API request sender</title><style>'. |
1300 | + 'input { width: 80% } textarea { width: 100%; height: 80px;}</style></head><body>'; |
1301 | echo '<form method="POST">'; |
1302 | echo '<select name="method">'; |
1303 | if(!isset($_POST['method'])) $method='GET'; |
1304 | @@ -36,4 +38,5 @@ |
1305 | } |
1306 | echo '</pre>'; |
1307 | fclose($sock); |
1308 | -} |
1309 | \ No newline at end of file |
1310 | +} |
1311 | +echo '</body></html>'; |
1312 | \ No newline at end of file |
1313 | |
1314 | === modified file 'api/responder.php' |
1315 | --- api/responder.php 2011-09-13 19:41:07 +0000 |
1316 | +++ api/responder.php 2011-12-11 19:47:27 +0000 |
1317 | @@ -1,7 +1,35 @@ |
1318 | <?php |
1319 | define('NO_UURL', true); |
1320 | +header('HTTP/1.1 500 Internal Server Error'); |
1321 | +ob_start(); |
1322 | +function error_to_exception($enum,$estring,$efile,$eline) { |
1323 | + if(error_reporting()===0) { |
1324 | + return; |
1325 | + } |
1326 | + throw new ErrorException($estring, 0, $enum, $efile, $eline); |
1327 | +} |
1328 | +set_error_handler('error_to_exception',-1); |
1329 | +function shutdown() { |
1330 | + if ($error = error_get_last()) { |
1331 | + ob_clean(); |
1332 | + switch($error['type']) { |
1333 | + case E_ERROR: |
1334 | + case E_CORE_ERROR: |
1335 | + case E_COMPILE_ERROR: |
1336 | + case E_USER_ERROR: |
1337 | + REST::error(500, $error['message']); |
1338 | + } |
1339 | + } |
1340 | +} |
1341 | +//register_shutdown_function('shutdown'); |
1342 | try { |
1343 | - require 'REST_entry.php'; |
1344 | + require 'REST/REST.php'; |
1345 | + require 'auth/auth.php'; |
1346 | + $module=REST::input()->getModule(); |
1347 | + if(!file_exists('modules/'.$module.'.php')) { |
1348 | + throw new NotFoundException('Module '.$module.' does not exist'); |
1349 | + } |
1350 | + require 'modules/'.$module.'.php'; |
1351 | } |
1352 | catch (HTTPException $e) { |
1353 | REST::error($e->getCode(), $e->getMessage()); |
1354 | |
1355 | === modified file 'inc/groups/groups.php' |
1356 | --- inc/groups/groups.php 2011-09-02 16:38:47 +0000 |
1357 | +++ inc/groups/groups.php 2011-12-11 19:47:27 +0000 |
1358 | @@ -52,7 +52,7 @@ |
1359 | JSError::add($t->_('You are not an administrator of that group')); |
1360 | return false; |
1361 | } |
1362 | - return self::$dbconn->query('INSERT INTO `groups` VALUES(\''.self::$dbconn->escape_string($group).'\',\''.self::$dbconn->escape_string($user).'\',NULL)'); |
1363 | + return self::$dbconn->query('INSERT INTO `groups` VALUES(\''.self::$dbconn->escape_string($group).'\',\''.self::$dbconn->escape_string($user).'\',0)'); |
1364 | } |
1365 | /** |
1366 | * Checks wether a group exists |
1367 | |
1368 | === modified file 'inc/rdb/auth.php' |
1369 | --- inc/rdb/auth.php 2011-10-19 19:38:18 +0000 |
1370 | +++ inc/rdb/auth.php 2011-12-11 19:47:27 +0000 |
1371 | @@ -13,7 +13,7 @@ |
1372 | $dblookup=$local_connection->query('SELECT * FROM `remote_databases` WHERE `key`=\''.substr($_SERVER['PATH_INFO'],1,32).'\''); |
1373 | if($dblookup->num_rows==1) |
1374 | self::$exists=true; |
1375 | - else |
1376 | + else |
1377 | return; |
1378 | if(($chkauth=self::checkauth())!==false) { |
1379 | self::$logged_in=true; |
1380 | |
1381 | === added file 'inc/utils/validDomainName.php' |
1382 | --- inc/utils/validDomainName.php 1970-01-01 00:00:00 +0000 |
1383 | +++ inc/utils/validDomainName.php 2011-12-11 19:47:27 +0000 |
1384 | @@ -0,0 +1,15 @@ |
1385 | +<?php |
1386 | +function is_valid_domain_name($domain_name) |
1387 | +{ |
1388 | + $pieces = explode(".",$domain_name); |
1389 | + if(count($pieces)<2) return false; |
1390 | + foreach($pieces as $piece) |
1391 | + { |
1392 | + if (!preg_match('/^[a-z\d][a-z\d-]{0,62}$/i', $piece) |
1393 | + || preg_match('/-$/', $piece) ) |
1394 | + { |
1395 | + return false; |
1396 | + } |
1397 | + } |
1398 | + return true; |
1399 | +} |
1400 | |
1401 | === modified file 'licenses/licenses.txt' |
1402 | --- licenses/licenses.txt 2011-09-18 16:51:00 +0000 |
1403 | +++ licenses/licenses.txt 2011-12-11 19:47:27 +0000 |
1404 | @@ -10,6 +10,7 @@ |
1405 | inc/utils/guid.php Public Domain Soulhuntre: Core Dump http://www.soulhuntre.com/2004/10/29/uuid-guid-in-native-php/ |
1406 | inc/utils/languageCodes.php Public Domain krillzip (adapted by Lars Vierbergen) http://snipplr.com/view/46886/ |
1407 | inc/utils/time_ago.php Public Domain Viral Patel (adapted by Lars Vierbergen) http://viralpatel.net/blogs/2009/06/twitter-like-n-min-sec-ago-timestamp-in-php-mysql.html |
1408 | +inc/utils/validDomainName.php Public Domain velcrow (adapted by Lars Vierbergen) http://stackoverflow.com/questions/1755144/how-to-validate-domain-name-in-php |
1409 | php.js/dirname.js MIT, GPL Ozh, XoraX http://phpjs.org/functions/dirname:388 |
1410 | scripts/permanent/jquery_escape.js Public Domain Karl Varga http://kjvarga.blogspot.com/2009/06/jquery-plugin-to-escape-css-selector.html |
1411 | scripts/permanent/jquery.timepicker.js, css/jquery.timepicker.css MIT, GPL Trent Richardson http://trentrichardson.com |
1412 | |
1413 | === removed directory 'zz-schemas' |
1414 | === removed file 'zz-schemas/SSO diagram servers.dia' |
1415 | Binary files zz-schemas/SSO diagram servers.dia 2011-03-27 18:43:25 +0000 and zz-schemas/SSO diagram servers.dia 1970-01-01 00:00:00 +0000 differ |
1416 | === removed file 'zz-schemas/SSO diagram.dia' |
1417 | Binary files zz-schemas/SSO diagram.dia 2011-03-25 20:23:35 +0000 and zz-schemas/SSO diagram.dia 1970-01-01 00:00:00 +0000 differ |
1418 | === removed file 'zz-schemas/new_userscheme.dia' |
1419 | Binary files zz-schemas/new_userscheme.dia 2011-03-31 16:36:14 +0000 and zz-schemas/new_userscheme.dia 1970-01-01 00:00:00 +0000 differ |
1420 | === removed file 'zz-schemas/schemas.readme.txt' |
1421 | --- zz-schemas/schemas.readme.txt 2011-06-28 16:13:01 +0000 |
1422 | +++ zz-schemas/schemas.readme.txt 1970-01-01 00:00:00 +0000 |
1423 | @@ -1,2 +0,0 @@ |
1424 | -These schemas are made with Dia. |
1425 | -Dia is open-source software. Get your copy at http://live.gnome.org/Dia |
1426 | \ No newline at end of file |