diff options
Diffstat (limited to 'src/rest-plugins/plugin_rest_identity.c')
-rw-r--r-- | src/rest-plugins/plugin_rest_identity.c | 1319 |
1 files changed, 1319 insertions, 0 deletions
diff --git a/src/rest-plugins/plugin_rest_identity.c b/src/rest-plugins/plugin_rest_identity.c new file mode 100644 index 000000000..9f1765a63 --- /dev/null +++ b/src/rest-plugins/plugin_rest_identity.c | |||
@@ -0,0 +1,1319 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2012-2015 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | /** | ||
19 | * @author Martin Schanzenbach | ||
20 | * @author Philippe Buschmann | ||
21 | * @file identity/plugin_rest_identity.c | ||
22 | * @brief GNUnet Identity REST plugin | ||
23 | */ | ||
24 | |||
25 | #include "platform.h" | ||
26 | #include "gnunet_rest_plugin.h" | ||
27 | #include "gnunet_identity_service.h" | ||
28 | #include "gnunet_rest_lib.h" | ||
29 | #include "microhttpd.h" | ||
30 | #include <jansson.h> | ||
31 | |||
32 | /** | ||
33 | * Identity Namespace | ||
34 | */ | ||
35 | #define GNUNET_REST_API_NS_IDENTITY "/identity" | ||
36 | |||
37 | /** | ||
38 | * Identity Namespace with public key specifier | ||
39 | */ | ||
40 | #define GNUNET_REST_API_NS_IDENTITY_ALL "/identity/all" | ||
41 | |||
42 | /** | ||
43 | * Identity Namespace with public key specifier | ||
44 | */ | ||
45 | #define GNUNET_REST_API_NS_IDENTITY_PUBKEY "/identity/pubkey" | ||
46 | |||
47 | /** | ||
48 | * Identity Namespace with public key specifier | ||
49 | */ | ||
50 | #define GNUNET_REST_API_NS_IDENTITY_NAME "/identity/name" | ||
51 | |||
52 | /** | ||
53 | * Identity Subsystem Namespace | ||
54 | */ | ||
55 | #define GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM "/identity/subsystem" | ||
56 | |||
57 | /** | ||
58 | * Parameter public key | ||
59 | */ | ||
60 | #define GNUNET_REST_IDENTITY_PARAM_PUBKEY "pubkey" | ||
61 | |||
62 | /** | ||
63 | * Parameter subsystem | ||
64 | */ | ||
65 | #define GNUNET_REST_IDENTITY_PARAM_SUBSYSTEM "subsystem" | ||
66 | |||
67 | /** | ||
68 | * Parameter name | ||
69 | */ | ||
70 | #define GNUNET_REST_IDENTITY_PARAM_NAME "name" | ||
71 | |||
72 | /** | ||
73 | * Parameter new name | ||
74 | */ | ||
75 | #define GNUNET_REST_IDENTITY_PARAM_NEWNAME "newname" | ||
76 | |||
77 | /** | ||
78 | * Error message Unknown Error | ||
79 | */ | ||
80 | #define GNUNET_REST_IDENTITY_ERROR_UNKNOWN "Unknown Error" | ||
81 | |||
82 | /** | ||
83 | * Error message No identity found | ||
84 | */ | ||
85 | #define GNUNET_REST_IDENTITY_NOT_FOUND "No identity found" | ||
86 | |||
87 | /** | ||
88 | * Error message Missing identity name | ||
89 | */ | ||
90 | #define GNUNET_REST_IDENTITY_MISSING_NAME "Missing identity name" | ||
91 | |||
92 | /** | ||
93 | * Error message Missing identity name | ||
94 | */ | ||
95 | #define GNUNET_REST_IDENTITY_MISSING_PUBKEY "Missing identity public key" | ||
96 | |||
97 | /** | ||
98 | * Error message No data | ||
99 | */ | ||
100 | #define GNUNET_REST_ERROR_NO_DATA "No data" | ||
101 | |||
102 | /** | ||
103 | * Error message Data invalid | ||
104 | */ | ||
105 | #define GNUNET_REST_ERROR_DATA_INVALID "Data invalid" | ||
106 | |||
107 | /** | ||
108 | * State while collecting all egos | ||
109 | */ | ||
110 | #define ID_REST_STATE_INIT 0 | ||
111 | |||
112 | /** | ||
113 | * Done collecting egos | ||
114 | */ | ||
115 | #define ID_REST_STATE_POST_INIT 1 | ||
116 | |||
117 | /** | ||
118 | * The configuration handle | ||
119 | */ | ||
120 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
121 | |||
122 | /** | ||
123 | * HTTP methods allows for this plugin | ||
124 | */ | ||
125 | static char* allow_methods; | ||
126 | |||
127 | /** | ||
128 | * @brief struct returned by the initialization function of the plugin | ||
129 | */ | ||
130 | struct Plugin | ||
131 | { | ||
132 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
133 | }; | ||
134 | |||
135 | /** | ||
136 | * The ego list | ||
137 | */ | ||
138 | struct EgoEntry | ||
139 | { | ||
140 | /** | ||
141 | * DLL | ||
142 | */ | ||
143 | struct EgoEntry *next; | ||
144 | |||
145 | /** | ||
146 | * DLL | ||
147 | */ | ||
148 | struct EgoEntry *prev; | ||
149 | |||
150 | /** | ||
151 | * Ego Identifier | ||
152 | */ | ||
153 | char *identifier; | ||
154 | |||
155 | /** | ||
156 | * Public key string | ||
157 | */ | ||
158 | char *keystring; | ||
159 | |||
160 | /** | ||
161 | * The Ego | ||
162 | */ | ||
163 | struct GNUNET_IDENTITY_Ego *ego; | ||
164 | }; | ||
165 | |||
166 | /** | ||
167 | * The request handle | ||
168 | */ | ||
169 | struct RequestHandle | ||
170 | { | ||
171 | /** | ||
172 | * The data from the REST request | ||
173 | */ | ||
174 | const char* data; | ||
175 | |||
176 | /** | ||
177 | * The name to look up | ||
178 | */ | ||
179 | char *name; | ||
180 | |||
181 | /** | ||
182 | * the length of the REST data | ||
183 | */ | ||
184 | size_t data_size; | ||
185 | |||
186 | |||
187 | /** | ||
188 | * Ego list | ||
189 | */ | ||
190 | struct EgoEntry *ego_head; | ||
191 | |||
192 | /** | ||
193 | * Ego list | ||
194 | */ | ||
195 | struct EgoEntry *ego_tail; | ||
196 | |||
197 | /** | ||
198 | * The processing state | ||
199 | */ | ||
200 | int state; | ||
201 | |||
202 | /** | ||
203 | * Handle to Identity service. | ||
204 | */ | ||
205 | struct GNUNET_IDENTITY_Handle *identity_handle; | ||
206 | |||
207 | /** | ||
208 | * IDENTITY Operation | ||
209 | */ | ||
210 | struct GNUNET_IDENTITY_Operation *op; | ||
211 | |||
212 | /** | ||
213 | * Rest connection | ||
214 | */ | ||
215 | struct GNUNET_REST_RequestHandle *rest_handle; | ||
216 | |||
217 | /** | ||
218 | * Desired timeout for the lookup (default is no timeout). | ||
219 | */ | ||
220 | struct GNUNET_TIME_Relative timeout; | ||
221 | |||
222 | /** | ||
223 | * ID of a task associated with the resolution process. | ||
224 | */ | ||
225 | struct GNUNET_SCHEDULER_Task *timeout_task; | ||
226 | |||
227 | /** | ||
228 | * The plugin result processor | ||
229 | */ | ||
230 | GNUNET_REST_ResultProcessor proc; | ||
231 | |||
232 | /** | ||
233 | * The closure of the result processor | ||
234 | */ | ||
235 | void *proc_cls; | ||
236 | |||
237 | /** | ||
238 | * The url | ||
239 | */ | ||
240 | char *url; | ||
241 | |||
242 | /** | ||
243 | * Error response message | ||
244 | */ | ||
245 | char *emsg; | ||
246 | |||
247 | /** | ||
248 | * Response code | ||
249 | */ | ||
250 | int response_code; | ||
251 | |||
252 | }; | ||
253 | |||
254 | /** | ||
255 | * Cleanup lookup handle | ||
256 | * @param handle Handle to clean up | ||
257 | */ | ||
258 | static void | ||
259 | cleanup_handle (void *cls) | ||
260 | { | ||
261 | struct RequestHandle *handle = cls; | ||
262 | struct EgoEntry *ego_entry; | ||
263 | struct EgoEntry *ego_tmp; | ||
264 | |||
265 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n"); | ||
266 | if (NULL != handle->timeout_task) | ||
267 | { | ||
268 | GNUNET_SCHEDULER_cancel (handle->timeout_task); | ||
269 | handle->timeout_task = NULL; | ||
270 | } | ||
271 | |||
272 | if (NULL != handle->url) | ||
273 | GNUNET_free(handle->url); | ||
274 | if (NULL != handle->emsg) | ||
275 | GNUNET_free(handle->emsg); | ||
276 | if (NULL != handle->name) | ||
277 | GNUNET_free (handle->name); | ||
278 | if (NULL != handle->identity_handle) | ||
279 | GNUNET_IDENTITY_disconnect (handle->identity_handle); | ||
280 | |||
281 | for (ego_entry = handle->ego_head; | ||
282 | NULL != ego_entry;) | ||
283 | { | ||
284 | ego_tmp = ego_entry; | ||
285 | ego_entry = ego_entry->next; | ||
286 | GNUNET_free(ego_tmp->identifier); | ||
287 | GNUNET_free(ego_tmp->keystring); | ||
288 | GNUNET_free(ego_tmp); | ||
289 | } | ||
290 | |||
291 | GNUNET_free(handle); | ||
292 | } | ||
293 | |||
294 | /** | ||
295 | * Task run on errors. Reports an error and cleans up everything. | ||
296 | * | ||
297 | * @param cls the `struct RequestHandle` | ||
298 | */ | ||
299 | static void | ||
300 | do_error (void *cls) | ||
301 | { | ||
302 | struct RequestHandle *handle = cls; | ||
303 | struct MHD_Response *resp; | ||
304 | json_t *json_error = json_object(); | ||
305 | char *response; | ||
306 | |||
307 | if (NULL == handle->emsg) | ||
308 | handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_ERROR_UNKNOWN); | ||
309 | |||
310 | json_object_set_new(json_error,"error", json_string(handle->emsg)); | ||
311 | |||
312 | if (0 == handle->response_code) | ||
313 | handle->response_code = MHD_HTTP_OK; | ||
314 | response = json_dumps (json_error, 0); | ||
315 | resp = GNUNET_REST_create_response (response); | ||
316 | handle->proc (handle->proc_cls, resp, handle->response_code); | ||
317 | json_decref(json_error); | ||
318 | GNUNET_free(response); | ||
319 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
320 | } | ||
321 | |||
322 | |||
323 | |||
324 | /** | ||
325 | * Get EgoEntry from list with either a public key or a name | ||
326 | * If public key and name are not NULL, it returns the public key result first | ||
327 | * | ||
328 | * @param handle the RequestHandle | ||
329 | * @param pubkey the public key of an identity (only one can be NULL) | ||
330 | * @param name the name of an identity (only one can be NULL) | ||
331 | * @return EgoEntry or NULL if not found | ||
332 | */ | ||
333 | struct EgoEntry* | ||
334 | get_egoentry(struct RequestHandle *handle, char* pubkey, char *name) | ||
335 | { | ||
336 | struct EgoEntry *ego_entry; | ||
337 | if (NULL != pubkey) | ||
338 | { | ||
339 | for (ego_entry = handle->ego_head; | ||
340 | NULL != ego_entry; | ||
341 | ego_entry = ego_entry->next) | ||
342 | { | ||
343 | if (0 != strcasecmp (pubkey, ego_entry->keystring)) | ||
344 | continue; | ||
345 | return ego_entry; | ||
346 | } | ||
347 | } | ||
348 | if (NULL != name) | ||
349 | { | ||
350 | for (ego_entry = handle->ego_head; | ||
351 | NULL != ego_entry; | ||
352 | ego_entry = ego_entry->next) | ||
353 | { | ||
354 | if (0 != strcasecmp (name, ego_entry->identifier)) | ||
355 | continue; | ||
356 | return ego_entry; | ||
357 | } | ||
358 | } | ||
359 | return NULL; | ||
360 | } | ||
361 | |||
362 | |||
363 | /** | ||
364 | * Callback for GET Request with subsystem | ||
365 | * | ||
366 | * @param cls the RequestHandle | ||
367 | * @param ego the Ego found | ||
368 | * @param ctx the context | ||
369 | * @param name the id of the ego | ||
370 | */ | ||
371 | static void | ||
372 | ego_get_for_subsystem (void *cls, | ||
373 | struct GNUNET_IDENTITY_Ego *ego, | ||
374 | void **ctx, | ||
375 | const char *name) | ||
376 | { | ||
377 | struct RequestHandle *handle = cls; | ||
378 | struct MHD_Response *resp; | ||
379 | struct GNUNET_CRYPTO_EcdsaPublicKey public_key; | ||
380 | json_t *json_root; | ||
381 | char *result_str; | ||
382 | char *public_key_string; | ||
383 | |||
384 | if(NULL == ego) | ||
385 | { | ||
386 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
387 | handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND); | ||
388 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
389 | return; | ||
390 | } | ||
391 | |||
392 | GNUNET_IDENTITY_ego_get_public_key(ego,&public_key); | ||
393 | public_key_string = GNUNET_CRYPTO_ecdsa_public_key_to_string(&public_key); | ||
394 | |||
395 | // create json with subsystem identity | ||
396 | json_root = json_object (); | ||
397 | json_object_set_new (json_root, | ||
398 | GNUNET_REST_IDENTITY_PARAM_PUBKEY, | ||
399 | json_string(public_key_string)); | ||
400 | json_object_set_new (json_root, | ||
401 | GNUNET_REST_IDENTITY_PARAM_NAME, | ||
402 | json_string(name)); | ||
403 | |||
404 | result_str = json_dumps (json_root, 0); | ||
405 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); | ||
406 | resp = GNUNET_REST_create_response (result_str); | ||
407 | |||
408 | json_decref (json_root); | ||
409 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
410 | GNUNET_free(result_str); | ||
411 | GNUNET_free(public_key_string); | ||
412 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
413 | } | ||
414 | |||
415 | /** | ||
416 | * Handle identity GET request for subsystem | ||
417 | * | ||
418 | * @param con_handle the connection handle | ||
419 | * @param url the url | ||
420 | * @param cls the RequestHandle | ||
421 | */ | ||
422 | void | ||
423 | ego_get_subsystem (struct GNUNET_REST_RequestHandle *con_handle, | ||
424 | const char* url, | ||
425 | void *cls) | ||
426 | { | ||
427 | struct RequestHandle *handle = cls; | ||
428 | char *subsystem; | ||
429 | |||
430 | if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url)) | ||
431 | { | ||
432 | handle->emsg = GNUNET_strdup("Missing subsystem name"); | ||
433 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
434 | return; | ||
435 | } | ||
436 | subsystem = &handle->url[strlen ( | ||
437 | GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) + 1]; | ||
438 | //requested default identity of subsystem | ||
439 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", subsystem); | ||
440 | |||
441 | handle->op = GNUNET_IDENTITY_get (handle->identity_handle, | ||
442 | subsystem, | ||
443 | &ego_get_for_subsystem, | ||
444 | handle); | ||
445 | |||
446 | if (NULL == handle->op) | ||
447 | { | ||
448 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
449 | handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND); | ||
450 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
451 | return; | ||
452 | } | ||
453 | } | ||
454 | |||
455 | |||
456 | /** | ||
457 | * Handle identity GET request - responds with all identities | ||
458 | * | ||
459 | * @param con_handle the connection handle | ||
460 | * @param url the url | ||
461 | * @param cls the RequestHandle | ||
462 | */ | ||
463 | void | ||
464 | ego_get_all (struct GNUNET_REST_RequestHandle *con_handle, | ||
465 | const char* url, | ||
466 | void *cls) | ||
467 | { | ||
468 | struct RequestHandle *handle = cls; | ||
469 | struct EgoEntry *ego_entry; | ||
470 | struct MHD_Response *resp; | ||
471 | json_t *json_root; | ||
472 | json_t *json_ego; | ||
473 | char *result_str; | ||
474 | |||
475 | json_root = json_array (); | ||
476 | //Return ego/egos | ||
477 | for (ego_entry = handle->ego_head; | ||
478 | NULL != ego_entry; ego_entry = ego_entry->next) | ||
479 | { | ||
480 | json_ego = json_object (); | ||
481 | json_object_set_new (json_ego, | ||
482 | GNUNET_REST_IDENTITY_PARAM_PUBKEY, | ||
483 | json_string (ego_entry->keystring)); | ||
484 | json_object_set_new (json_ego, | ||
485 | GNUNET_REST_IDENTITY_PARAM_NAME, | ||
486 | json_string (ego_entry->identifier)); | ||
487 | json_array_append (json_root, json_ego); | ||
488 | json_decref (json_ego); | ||
489 | } | ||
490 | |||
491 | if ((size_t) 0 == json_array_size (json_root)) | ||
492 | { | ||
493 | json_decref (json_root); | ||
494 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
495 | handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND); | ||
496 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
497 | return; | ||
498 | } | ||
499 | |||
500 | result_str = json_dumps (json_root, 0); | ||
501 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); | ||
502 | resp = GNUNET_REST_create_response (result_str); | ||
503 | |||
504 | json_decref (json_root); | ||
505 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
506 | GNUNET_free(result_str); | ||
507 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
508 | } | ||
509 | |||
510 | |||
511 | /** | ||
512 | * Responds with the ego_entry identity | ||
513 | * | ||
514 | * @param handle the struct RequestHandle | ||
515 | * @param ego_entry the struct EgoEntry for the response | ||
516 | */ | ||
517 | void | ||
518 | ego_get_response (struct RequestHandle *handle, struct EgoEntry *ego_entry) | ||
519 | { | ||
520 | struct MHD_Response *resp; | ||
521 | json_t *json_ego; | ||
522 | char *result_str; | ||
523 | |||
524 | json_ego = json_object (); | ||
525 | json_object_set_new (json_ego, | ||
526 | GNUNET_REST_IDENTITY_PARAM_PUBKEY, | ||
527 | json_string (ego_entry->keystring)); | ||
528 | json_object_set_new (json_ego, | ||
529 | GNUNET_REST_IDENTITY_PARAM_NAME, | ||
530 | json_string (ego_entry->identifier)); | ||
531 | |||
532 | result_str = json_dumps (json_ego, 0); | ||
533 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); | ||
534 | resp = GNUNET_REST_create_response (result_str); | ||
535 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
536 | |||
537 | json_decref (json_ego); | ||
538 | GNUNET_free(result_str); | ||
539 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
540 | } | ||
541 | |||
542 | |||
543 | /** | ||
544 | * Handle identity GET request with a public key | ||
545 | * | ||
546 | * @param con_handle the connection handle | ||
547 | * @param url the url | ||
548 | * @param cls the RequestHandle | ||
549 | */ | ||
550 | void | ||
551 | ego_get_pubkey (struct GNUNET_REST_RequestHandle *con_handle, | ||
552 | const char* url, | ||
553 | void *cls) | ||
554 | { | ||
555 | struct RequestHandle *handle = cls; | ||
556 | struct EgoEntry *ego_entry; | ||
557 | char *keystring; | ||
558 | |||
559 | keystring = NULL; | ||
560 | |||
561 | if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url)) | ||
562 | { | ||
563 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
564 | handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_PUBKEY); | ||
565 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
566 | return; | ||
567 | } | ||
568 | keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY)+1]; | ||
569 | ego_entry = get_egoentry(handle, keystring, NULL); | ||
570 | |||
571 | if (NULL == ego_entry) | ||
572 | { | ||
573 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
574 | handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND); | ||
575 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
576 | return; | ||
577 | } | ||
578 | |||
579 | ego_get_response(handle, ego_entry); | ||
580 | } | ||
581 | |||
582 | /** | ||
583 | * Handle identity GET request with a name | ||
584 | * | ||
585 | * @param con_handle the connection handle | ||
586 | * @param url the url | ||
587 | * @param cls the RequestHandle | ||
588 | */ | ||
589 | void | ||
590 | ego_get_name (struct GNUNET_REST_RequestHandle *con_handle, | ||
591 | const char* url, | ||
592 | void *cls) | ||
593 | { | ||
594 | struct RequestHandle *handle = cls; | ||
595 | struct EgoEntry *ego_entry; | ||
596 | char *egoname; | ||
597 | |||
598 | egoname = NULL; | ||
599 | |||
600 | if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url)) | ||
601 | { | ||
602 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
603 | handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_NAME); | ||
604 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
605 | return; | ||
606 | } | ||
607 | egoname = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME)+1]; | ||
608 | ego_entry = get_egoentry(handle, NULL, egoname); | ||
609 | |||
610 | if (NULL == ego_entry) | ||
611 | { | ||
612 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
613 | handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND); | ||
614 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
615 | return; | ||
616 | } | ||
617 | |||
618 | ego_get_response(handle, ego_entry); | ||
619 | } | ||
620 | |||
621 | |||
622 | /** | ||
623 | * Processing finished | ||
624 | * | ||
625 | * @param cls request handle | ||
626 | * @param emsg error message | ||
627 | */ | ||
628 | static void | ||
629 | do_finished (void *cls, const char *emsg) | ||
630 | { | ||
631 | struct RequestHandle *handle = cls; | ||
632 | struct MHD_Response *resp; | ||
633 | |||
634 | handle->op = NULL; | ||
635 | if (NULL != emsg) | ||
636 | { | ||
637 | handle->emsg = GNUNET_strdup(emsg); | ||
638 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
639 | return; | ||
640 | } | ||
641 | if (0 == handle->response_code) | ||
642 | { | ||
643 | handle->response_code = MHD_HTTP_NO_CONTENT; | ||
644 | } | ||
645 | resp = GNUNET_REST_create_response (NULL); | ||
646 | handle->proc (handle->proc_cls, resp, handle->response_code); | ||
647 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
648 | } | ||
649 | |||
650 | |||
651 | /** | ||
652 | * Processing edit ego with EgoEntry ego_entry | ||
653 | * | ||
654 | * @param handle the struct RequestHandle | ||
655 | * @param ego_entry the struct EgoEntry we want to edit | ||
656 | */ | ||
657 | void | ||
658 | ego_edit (struct RequestHandle *handle, struct EgoEntry *ego_entry) | ||
659 | { | ||
660 | struct EgoEntry *ego_entry_tmp; | ||
661 | struct MHD_Response *resp; | ||
662 | json_t *data_js; | ||
663 | json_error_t err; | ||
664 | char *newname; | ||
665 | char term_data[handle->data_size + 1]; | ||
666 | int json_state; | ||
667 | |||
668 | //if no data | ||
669 | if (0 >= handle->data_size) | ||
670 | { | ||
671 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA); | ||
672 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
673 | return; | ||
674 | } | ||
675 | //if not json | ||
676 | term_data[handle->data_size] = '\0'; | ||
677 | GNUNET_memcpy(term_data, handle->data, handle->data_size); | ||
678 | data_js = json_loads (term_data,JSON_DECODE_ANY,&err); | ||
679 | |||
680 | if (NULL == data_js) | ||
681 | { | ||
682 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA); | ||
683 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
684 | return; | ||
685 | } | ||
686 | |||
687 | newname = NULL; | ||
688 | //NEW NAME | ||
689 | json_state = 0; | ||
690 | json_state = json_unpack(data_js, | ||
691 | "{s:s!}", | ||
692 | GNUNET_REST_IDENTITY_PARAM_NEWNAME, | ||
693 | &newname); | ||
694 | //Change name with pubkey or name identifier | ||
695 | if (0 != json_state) | ||
696 | { | ||
697 | |||
698 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); | ||
699 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
700 | json_decref (data_js); | ||
701 | return; | ||
702 | } | ||
703 | |||
704 | if (NULL == newname) | ||
705 | { | ||
706 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); | ||
707 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
708 | json_decref (data_js); | ||
709 | return; | ||
710 | } | ||
711 | |||
712 | if (0 >= strlen (newname)) | ||
713 | { | ||
714 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); | ||
715 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
716 | json_decref (data_js); | ||
717 | return; | ||
718 | } | ||
719 | |||
720 | ego_entry_tmp = get_egoentry (handle, NULL, newname); | ||
721 | if (NULL != ego_entry_tmp) | ||
722 | { | ||
723 | //Ego with same name not allowed (even if its the ego we change) | ||
724 | resp = GNUNET_REST_create_response (NULL); | ||
725 | handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); | ||
726 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
727 | json_decref (data_js); | ||
728 | return; | ||
729 | } | ||
730 | handle->op = GNUNET_IDENTITY_rename (handle->identity_handle, | ||
731 | ego_entry->identifier, | ||
732 | newname, | ||
733 | &do_finished, | ||
734 | handle); | ||
735 | if (NULL == handle->op) | ||
736 | { | ||
737 | handle->emsg = GNUNET_strdup("Rename failed"); | ||
738 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
739 | json_decref (data_js); | ||
740 | return; | ||
741 | } | ||
742 | json_decref (data_js); | ||
743 | return; | ||
744 | |||
745 | } | ||
746 | |||
747 | |||
748 | /** | ||
749 | * Handle identity PUT request with public key | ||
750 | * | ||
751 | * @param con_handle the connection handle | ||
752 | * @param url the url | ||
753 | * @param cls the RequestHandle | ||
754 | */ | ||
755 | void | ||
756 | ego_edit_pubkey (struct GNUNET_REST_RequestHandle *con_handle, | ||
757 | const char* url, | ||
758 | void *cls) | ||
759 | { | ||
760 | struct RequestHandle *handle = cls; | ||
761 | struct EgoEntry *ego_entry; | ||
762 | char *keystring; | ||
763 | |||
764 | keystring = NULL; | ||
765 | |||
766 | if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url)) | ||
767 | { | ||
768 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
769 | handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_PUBKEY); | ||
770 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
771 | return; | ||
772 | } | ||
773 | keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY)+1]; | ||
774 | ego_entry = get_egoentry(handle, keystring, NULL); | ||
775 | |||
776 | if (NULL == ego_entry) | ||
777 | { | ||
778 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
779 | handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND); | ||
780 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
781 | return; | ||
782 | } | ||
783 | |||
784 | ego_edit(handle,ego_entry); | ||
785 | } | ||
786 | |||
787 | /** | ||
788 | * Handle identity PUT request with name | ||
789 | * | ||
790 | * @param con_handle the connection handle | ||
791 | * @param url the url | ||
792 | * @param cls the RequestHandle | ||
793 | */ | ||
794 | void | ||
795 | ego_edit_name (struct GNUNET_REST_RequestHandle *con_handle, | ||
796 | const char* url, | ||
797 | void *cls) | ||
798 | { | ||
799 | struct RequestHandle *handle = cls; | ||
800 | struct EgoEntry *ego_entry; | ||
801 | char *name; | ||
802 | |||
803 | name = NULL; | ||
804 | |||
805 | if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url)) | ||
806 | { | ||
807 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
808 | handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_NAME); | ||
809 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
810 | return; | ||
811 | } | ||
812 | name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME)+1]; | ||
813 | ego_entry = get_egoentry(handle, NULL, name); | ||
814 | |||
815 | if (NULL == ego_entry) | ||
816 | { | ||
817 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
818 | handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND); | ||
819 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
820 | return; | ||
821 | } | ||
822 | |||
823 | ego_edit(handle,ego_entry); | ||
824 | } | ||
825 | |||
826 | /** | ||
827 | * Handle identity subsystem PUT request with name | ||
828 | * | ||
829 | * @param con_handle the connection handle | ||
830 | * @param url the url | ||
831 | * @param cls the RequestHandle | ||
832 | */ | ||
833 | void | ||
834 | ego_edit_subsystem (struct GNUNET_REST_RequestHandle *con_handle, | ||
835 | const char* url, | ||
836 | void *cls) | ||
837 | { | ||
838 | struct RequestHandle *handle = cls; | ||
839 | struct EgoEntry *ego_entry; | ||
840 | json_t *data_js; | ||
841 | json_error_t err; | ||
842 | char *newsubsys; | ||
843 | char *name; | ||
844 | char term_data[handle->data_size + 1]; | ||
845 | int json_state; | ||
846 | |||
847 | name = NULL; | ||
848 | |||
849 | if (strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM) >= strlen (handle->url)) | ||
850 | { | ||
851 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
852 | handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_NAME); | ||
853 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
854 | return; | ||
855 | } | ||
856 | name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM)+1]; | ||
857 | ego_entry = get_egoentry(handle, NULL, name); | ||
858 | |||
859 | if (NULL == ego_entry) | ||
860 | { | ||
861 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
862 | handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND); | ||
863 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
864 | return; | ||
865 | } | ||
866 | |||
867 | //if no data | ||
868 | if (0 >= handle->data_size) | ||
869 | { | ||
870 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA); | ||
871 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
872 | return; | ||
873 | } | ||
874 | //if not json | ||
875 | term_data[handle->data_size] = '\0'; | ||
876 | GNUNET_memcpy(term_data, handle->data, handle->data_size); | ||
877 | data_js = json_loads (term_data,JSON_DECODE_ANY,&err); | ||
878 | |||
879 | if (NULL == data_js) | ||
880 | { | ||
881 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA); | ||
882 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
883 | return; | ||
884 | } | ||
885 | |||
886 | newsubsys = NULL; | ||
887 | //SUBSYSTEM | ||
888 | json_state = 0; | ||
889 | json_state = json_unpack(data_js, | ||
890 | "{s:s!}", | ||
891 | GNUNET_REST_IDENTITY_PARAM_SUBSYSTEM, | ||
892 | &newsubsys); | ||
893 | //Change subsystem with pubkey or name identifier | ||
894 | if (0 != json_state) | ||
895 | { | ||
896 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); | ||
897 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
898 | json_decref (data_js); | ||
899 | return; | ||
900 | } | ||
901 | |||
902 | if (NULL == newsubsys) | ||
903 | { | ||
904 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); | ||
905 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
906 | json_decref (data_js); | ||
907 | return; | ||
908 | } | ||
909 | |||
910 | if (0 >= strlen (newsubsys)) | ||
911 | { | ||
912 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); | ||
913 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
914 | json_decref (data_js); | ||
915 | return; | ||
916 | } | ||
917 | |||
918 | handle->response_code = MHD_HTTP_NO_CONTENT; | ||
919 | handle->op = GNUNET_IDENTITY_set (handle->identity_handle, | ||
920 | newsubsys, | ||
921 | ego_entry->ego, | ||
922 | &do_finished, | ||
923 | handle); | ||
924 | if (NULL == handle->op) | ||
925 | { | ||
926 | handle->emsg = GNUNET_strdup("Setting subsystem failed"); | ||
927 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
928 | return; | ||
929 | } | ||
930 | json_decref (data_js); | ||
931 | return; | ||
932 | |||
933 | } | ||
934 | |||
935 | /** | ||
936 | * Handle identity POST request | ||
937 | * | ||
938 | * @param con_handle the connection handle | ||
939 | * @param url the url | ||
940 | * @param cls the RequestHandle | ||
941 | */ | ||
942 | void | ||
943 | ego_create (struct GNUNET_REST_RequestHandle *con_handle, | ||
944 | const char* url, | ||
945 | void *cls) | ||
946 | { | ||
947 | struct RequestHandle *handle = cls; | ||
948 | struct EgoEntry *ego_entry; | ||
949 | struct MHD_Response *resp; | ||
950 | json_t *data_js; | ||
951 | json_error_t err; | ||
952 | char* egoname; | ||
953 | int json_unpack_state; | ||
954 | char term_data[handle->data_size + 1]; | ||
955 | |||
956 | if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url)) | ||
957 | { | ||
958 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
959 | return; | ||
960 | } | ||
961 | |||
962 | if (0 >= handle->data_size) | ||
963 | { | ||
964 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA); | ||
965 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
966 | return; | ||
967 | } | ||
968 | term_data[handle->data_size] = '\0'; | ||
969 | GNUNET_memcpy(term_data, handle->data, handle->data_size); | ||
970 | data_js = json_loads (term_data, | ||
971 | JSON_DECODE_ANY, | ||
972 | &err); | ||
973 | if (NULL == data_js) | ||
974 | { | ||
975 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA); | ||
976 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
977 | json_decref (data_js); | ||
978 | return; | ||
979 | } | ||
980 | json_unpack_state = 0; | ||
981 | json_unpack_state = json_unpack(data_js, | ||
982 | "{s:s!}", | ||
983 | GNUNET_REST_IDENTITY_PARAM_NAME, | ||
984 | &egoname); | ||
985 | if (0 != json_unpack_state) | ||
986 | { | ||
987 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); | ||
988 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
989 | json_decref (data_js); | ||
990 | return; | ||
991 | } | ||
992 | |||
993 | if (NULL == egoname) | ||
994 | { | ||
995 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); | ||
996 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
997 | json_decref (data_js); | ||
998 | return; | ||
999 | } | ||
1000 | if (0 >= strlen (egoname)) | ||
1001 | { | ||
1002 | json_decref (data_js); | ||
1003 | handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID); | ||
1004 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1005 | return; | ||
1006 | } | ||
1007 | GNUNET_STRINGS_utf8_tolower(egoname, egoname); | ||
1008 | for (ego_entry = handle->ego_head; | ||
1009 | NULL != ego_entry; ego_entry = ego_entry->next) | ||
1010 | { | ||
1011 | if (0 == strcasecmp (egoname, ego_entry->identifier)) | ||
1012 | { | ||
1013 | resp = GNUNET_REST_create_response (NULL); | ||
1014 | handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); | ||
1015 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
1016 | json_decref (data_js); | ||
1017 | return; | ||
1018 | } | ||
1019 | } | ||
1020 | handle->name = GNUNET_strdup(egoname); | ||
1021 | json_decref (data_js); | ||
1022 | handle->response_code = MHD_HTTP_CREATED; | ||
1023 | handle->op = GNUNET_IDENTITY_create (handle->identity_handle, handle->name, | ||
1024 | &do_finished, handle); | ||
1025 | } | ||
1026 | |||
1027 | /** | ||
1028 | * Handle identity DELETE request with public key | ||
1029 | * | ||
1030 | * @param con_handle the connection handle | ||
1031 | * @param url the url | ||
1032 | * @param cls the RequestHandle | ||
1033 | */ | ||
1034 | void | ||
1035 | ego_delete_pubkey (struct GNUNET_REST_RequestHandle *con_handle, | ||
1036 | const char* url, | ||
1037 | void *cls) | ||
1038 | { | ||
1039 | struct RequestHandle *handle = cls; | ||
1040 | struct EgoEntry *ego_entry; | ||
1041 | char *keystring; | ||
1042 | |||
1043 | keystring = NULL; | ||
1044 | |||
1045 | if (strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY) >= strlen (handle->url)) | ||
1046 | { | ||
1047 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
1048 | handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_PUBKEY); | ||
1049 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1050 | return; | ||
1051 | } | ||
1052 | keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_PUBKEY)+1]; | ||
1053 | ego_entry = get_egoentry(handle, keystring, NULL); | ||
1054 | |||
1055 | if (NULL == ego_entry) | ||
1056 | { | ||
1057 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
1058 | handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND); | ||
1059 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1060 | return; | ||
1061 | } | ||
1062 | |||
1063 | handle->response_code = MHD_HTTP_NO_CONTENT; | ||
1064 | handle->op = GNUNET_IDENTITY_delete (handle->identity_handle, | ||
1065 | ego_entry->identifier, | ||
1066 | &do_finished, | ||
1067 | handle); | ||
1068 | } | ||
1069 | |||
1070 | |||
1071 | /** | ||
1072 | * Handle identity DELETE request with name | ||
1073 | * | ||
1074 | * @param con_handle the connection handle | ||
1075 | * @param url the url | ||
1076 | * @param cls the RequestHandle | ||
1077 | */ | ||
1078 | void | ||
1079 | ego_delete_name (struct GNUNET_REST_RequestHandle *con_handle, | ||
1080 | const char* url, | ||
1081 | void *cls) | ||
1082 | { | ||
1083 | struct RequestHandle *handle = cls; | ||
1084 | struct EgoEntry *ego_entry; | ||
1085 | char *name; | ||
1086 | |||
1087 | name = NULL; | ||
1088 | |||
1089 | if (strlen (GNUNET_REST_API_NS_IDENTITY_NAME) >= strlen (handle->url)) | ||
1090 | { | ||
1091 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
1092 | handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_MISSING_NAME); | ||
1093 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1094 | return; | ||
1095 | } | ||
1096 | name = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY_NAME)+1]; | ||
1097 | ego_entry = get_egoentry(handle, NULL, name); | ||
1098 | |||
1099 | if (NULL == ego_entry) | ||
1100 | { | ||
1101 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
1102 | handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_NOT_FOUND); | ||
1103 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1104 | return; | ||
1105 | } | ||
1106 | |||
1107 | handle->response_code = MHD_HTTP_NO_CONTENT; | ||
1108 | handle->op = GNUNET_IDENTITY_delete (handle->identity_handle, | ||
1109 | ego_entry->identifier, | ||
1110 | &do_finished, | ||
1111 | handle); | ||
1112 | } | ||
1113 | |||
1114 | |||
1115 | /** | ||
1116 | * Respond to OPTIONS request | ||
1117 | * | ||
1118 | * @param con_handle the connection handle | ||
1119 | * @param url the url | ||
1120 | * @param cls the RequestHandle | ||
1121 | */ | ||
1122 | static void | ||
1123 | options_cont (struct GNUNET_REST_RequestHandle *con_handle, const char* url, | ||
1124 | void *cls) | ||
1125 | { | ||
1126 | struct MHD_Response *resp; | ||
1127 | struct RequestHandle *handle = cls; | ||
1128 | |||
1129 | //For now, independent of path return all options | ||
1130 | resp = GNUNET_REST_create_response (NULL); | ||
1131 | MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods); | ||
1132 | handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); | ||
1133 | GNUNET_SCHEDULER_add_now (&cleanup_handle, handle); | ||
1134 | return; | ||
1135 | } | ||
1136 | |||
1137 | /** | ||
1138 | * Handle rest request | ||
1139 | * | ||
1140 | * @param handle the request handle | ||
1141 | */ | ||
1142 | static void | ||
1143 | init_cont (struct RequestHandle *handle) | ||
1144 | { | ||
1145 | struct GNUNET_REST_RequestHandlerError err; | ||
1146 | static const struct GNUNET_REST_RequestHandler handlers[] = { | ||
1147 | { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_ALL, &ego_get_all }, | ||
1148 | { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_PUBKEY, &ego_get_pubkey }, | ||
1149 | { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_get_name }, | ||
1150 | { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM, &ego_get_subsystem }, | ||
1151 | { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_PUBKEY, &ego_edit_pubkey }, | ||
1152 | { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_edit_name }, | ||
1153 | { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY_SUBSYSTEM, &ego_edit_subsystem }, | ||
1154 | { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create }, | ||
1155 | { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_IDENTITY_PUBKEY, &ego_delete_pubkey }, | ||
1156 | { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_IDENTITY_NAME, &ego_delete_name }, | ||
1157 | { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont }, | ||
1158 | GNUNET_REST_HANDLER_END | ||
1159 | }; | ||
1160 | |||
1161 | if (GNUNET_NO | ||
1162 | == GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, | ||
1163 | handle)) | ||
1164 | { | ||
1165 | handle->response_code = err.error_code; | ||
1166 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
1167 | } | ||
1168 | } | ||
1169 | |||
1170 | /** | ||
1171 | * If listing is enabled, prints information about the egos. | ||
1172 | * | ||
1173 | * This function is initially called for all egos and then again | ||
1174 | * whenever a ego's identifier changes or if it is deleted. At the | ||
1175 | * end of the initial pass over all egos, the function is once called | ||
1176 | * with 'NULL' for 'ego'. That does NOT mean that the callback won't | ||
1177 | * be invoked in the future or that there was an error. | ||
1178 | * | ||
1179 | * When used with 'GNUNET_IDENTITY_create' or 'GNUNET_IDENTITY_get', | ||
1180 | * this function is only called ONCE, and 'NULL' being passed in | ||
1181 | * 'ego' does indicate an error (i.e. name is taken or no default | ||
1182 | * value is known). If 'ego' is non-NULL and if '*ctx' | ||
1183 | * is set in those callbacks, the value WILL be passed to a subsequent | ||
1184 | * call to the identity callback of 'GNUNET_IDENTITY_connect' (if | ||
1185 | * that one was not NULL). | ||
1186 | * | ||
1187 | * When an identity is renamed, this function is called with the | ||
1188 | * (known) ego but the NEW identifier. | ||
1189 | * | ||
1190 | * When an identity is deleted, this function is called with the | ||
1191 | * (known) ego and "NULL" for the 'identifier'. In this case, | ||
1192 | * the 'ego' is henceforth invalid (and the 'ctx' should also be | ||
1193 | * cleaned up). | ||
1194 | * | ||
1195 | * @param cls closure | ||
1196 | * @param ego ego handle | ||
1197 | * @param ctx context for application to store data for this ego | ||
1198 | * (during the lifetime of this process, initially NULL) | ||
1199 | * @param identifier identifier assigned by the user for this ego, | ||
1200 | * NULL if the user just deleted the ego and it | ||
1201 | * must thus no longer be used | ||
1202 | */ | ||
1203 | static void | ||
1204 | init_egos (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, | ||
1205 | const char *identifier) | ||
1206 | { | ||
1207 | struct RequestHandle *handle = cls; | ||
1208 | struct EgoEntry *ego_entry; | ||
1209 | struct GNUNET_CRYPTO_EcdsaPublicKey pk; | ||
1210 | |||
1211 | if ((NULL == ego) && (ID_REST_STATE_INIT == handle->state)) | ||
1212 | { | ||
1213 | handle->state = ID_REST_STATE_POST_INIT; | ||
1214 | init_cont (handle); | ||
1215 | return; | ||
1216 | } | ||
1217 | if (ID_REST_STATE_INIT == handle->state) | ||
1218 | { | ||
1219 | ego_entry = GNUNET_new(struct EgoEntry); | ||
1220 | GNUNET_IDENTITY_ego_get_public_key (ego, &pk); | ||
1221 | ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk); | ||
1222 | ego_entry->ego = ego; | ||
1223 | GNUNET_asprintf (&ego_entry->identifier, "%s", identifier); | ||
1224 | GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head, handle->ego_tail, | ||
1225 | ego_entry); | ||
1226 | } | ||
1227 | } | ||
1228 | |||
1229 | /** | ||
1230 | * Function processing the REST call | ||
1231 | * | ||
1232 | * @param method HTTP method | ||
1233 | * @param url URL of the HTTP request | ||
1234 | * @param data body of the HTTP request (optional) | ||
1235 | * @param data_size length of the body | ||
1236 | * @param proc callback function for the result | ||
1237 | * @param proc_cls closure for callback function | ||
1238 | * @return GNUNET_OK if request accepted | ||
1239 | */ | ||
1240 | static void | ||
1241 | rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle, | ||
1242 | GNUNET_REST_ResultProcessor proc, void *proc_cls) | ||
1243 | { | ||
1244 | struct RequestHandle *handle = GNUNET_new(struct RequestHandle); | ||
1245 | |||
1246 | handle->response_code = 0; | ||
1247 | handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; | ||
1248 | handle->proc_cls = proc_cls; | ||
1249 | handle->proc = proc; | ||
1250 | handle->rest_handle = rest_handle; | ||
1251 | handle->data = rest_handle->data; | ||
1252 | handle->data_size = rest_handle->data_size; | ||
1253 | |||
1254 | handle->url = GNUNET_strdup(rest_handle->url); | ||
1255 | if (handle->url[strlen (handle->url) - 1] == '/') | ||
1256 | handle->url[strlen (handle->url) - 1] = '\0'; | ||
1257 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n"); | ||
1258 | |||
1259 | handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &init_egos, handle); | ||
1260 | |||
1261 | handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout, | ||
1262 | &do_error, handle); | ||
1263 | |||
1264 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected\n"); | ||
1265 | } | ||
1266 | |||
1267 | /** | ||
1268 | * Entry point for the plugin. | ||
1269 | * | ||
1270 | * @param cls Config info | ||
1271 | * @return NULL on error, otherwise the plugin context | ||
1272 | */ | ||
1273 | void * | ||
1274 | libgnunet_plugin_rest_identity_init (void *cls) | ||
1275 | { | ||
1276 | static struct Plugin plugin; | ||
1277 | struct GNUNET_REST_Plugin *api; | ||
1278 | |||
1279 | cfg = cls; | ||
1280 | if (NULL != plugin.cfg) | ||
1281 | return NULL; /* can only initialize once! */ | ||
1282 | memset (&plugin, 0, sizeof(struct Plugin)); | ||
1283 | plugin.cfg = cfg; | ||
1284 | api = GNUNET_new(struct GNUNET_REST_Plugin); | ||
1285 | api->cls = &plugin; | ||
1286 | api->name = GNUNET_REST_API_NS_IDENTITY; | ||
1287 | api->process_request = &rest_process_request; | ||
1288 | GNUNET_asprintf (&allow_methods, "%s, %s, %s, %s, %s", | ||
1289 | MHD_HTTP_METHOD_GET, | ||
1290 | MHD_HTTP_METHOD_POST, | ||
1291 | MHD_HTTP_METHOD_PUT, | ||
1292 | MHD_HTTP_METHOD_DELETE, | ||
1293 | MHD_HTTP_METHOD_OPTIONS); | ||
1294 | |||
1295 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, _("Identity REST API initialized\n")); | ||
1296 | return api; | ||
1297 | } | ||
1298 | |||
1299 | /** | ||
1300 | * Exit point from the plugin. | ||
1301 | * | ||
1302 | * @param cls the plugin context (as returned by "init") | ||
1303 | * @return always NULL | ||
1304 | */ | ||
1305 | void * | ||
1306 | libgnunet_plugin_rest_identity_done (void *cls) | ||
1307 | { | ||
1308 | struct GNUNET_REST_Plugin *api = cls; | ||
1309 | struct Plugin *plugin = api->cls; | ||
1310 | plugin->cfg = NULL; | ||
1311 | |||
1312 | GNUNET_free_non_null(allow_methods); | ||
1313 | GNUNET_free(api); | ||
1314 | GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Identity REST plugin is finished\n"); | ||
1315 | return NULL; | ||
1316 | } | ||
1317 | |||
1318 | /* end of plugin_rest_identity.c */ | ||
1319 | |||