aboutsummaryrefslogtreecommitdiff
path: root/src/identity
diff options
context:
space:
mode:
Diffstat (limited to 'src/identity')
-rw-r--r--src/identity/Makefile.am2
-rw-r--r--src/identity/plugin_rest_identity.c1057
-rwxr-xr-xsrc/identity/test_plugin_rest_identity.sh159
3 files changed, 725 insertions, 493 deletions
diff --git a/src/identity/Makefile.am b/src/identity/Makefile.am
index b8e70fffb..e7104f0c3 100644
--- a/src/identity/Makefile.am
+++ b/src/identity/Makefile.am
@@ -60,8 +60,6 @@ libgnunet_plugin_rest_identity_la_SOURCES = \
60libgnunet_plugin_rest_identity_la_LIBADD = \ 60libgnunet_plugin_rest_identity_la_LIBADD = \
61 libgnunetidentity.la \ 61 libgnunetidentity.la \
62 $(top_builddir)/src/rest/libgnunetrest.la \ 62 $(top_builddir)/src/rest/libgnunetrest.la \
63 $(top_builddir)/src/jsonapi/libgnunetjsonapi.la \
64 $(top_builddir)/src/jsonapi/libgnunetjsonapiutils.la \
65 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ 63 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
66 $(LTLIBINTL) -ljansson -lmicrohttpd 64 $(LTLIBINTL) -ljansson -lmicrohttpd
67libgnunet_plugin_rest_identity_la_LDFLAGS = \ 65libgnunet_plugin_rest_identity_la_LDFLAGS = \
diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c
index 355d75fd9..a518a74cc 100644
--- a/src/identity/plugin_rest_identity.c
+++ b/src/identity/plugin_rest_identity.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2012-2015 GNUnet e.V. 3 Copyright (C) 2012-2015 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -11,74 +11,51 @@
11 WITHOUT ANY WARRANTY; without even the implied warranty of 11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details. 13 Affero General Public License for more details.
14 14
15 You should have received a copy of the GNU Affero General Public License 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/>. 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */ 17 */
18/** 18/**
19 * @author Martin Schanzenbach 19 * @author Martin Schanzenbach
20 * @author Philippe Buschmann
20 * @file identity/plugin_rest_identity.c 21 * @file identity/plugin_rest_identity.c
21 * @brief GNUnet Namestore REST plugin 22 * @brief GNUnet Identity REST plugin
22 *
23 */ 23 */
24 24
25#include "platform.h" 25#include "platform.h"
26#include "gnunet_rest_plugin.h" 26#include "gnunet_rest_plugin.h"
27#include "gnunet_identity_service.h" 27#include "gnunet_identity_service.h"
28#include "gnunet_rest_lib.h" 28#include "gnunet_rest_lib.h"
29#include "gnunet_jsonapi_lib.h"
30#include "gnunet_jsonapi_util.h"
31#include "microhttpd.h" 29#include "microhttpd.h"
32#include <jansson.h> 30#include <jansson.h>
33#include "gnunet_signatures.h"
34 31
35/**
36 * REST root namespace
37 */
38#define GNUNET_REST_API_NS_IDENTITY "/identity" 32#define GNUNET_REST_API_NS_IDENTITY "/identity"
39 33
40/** 34/**
41 * State while collecting all egos 35 * Parameter names
42 */
43#define ID_REST_STATE_INIT 0
44
45/**
46 * Done collecting egos
47 */
48#define ID_REST_STATE_POST_INIT 1
49
50/**
51 * Resource type
52 */
53#define GNUNET_REST_JSONAPI_IDENTITY_EGO "ego"
54
55/**
56 * Name attribute
57 */
58#define GNUNET_REST_JSONAPI_IDENTITY_NAME "name"
59
60/**
61 * Attribute to rename "name" TODO we changed id to the pubkey
62 * so this can be unified with "name"
63 */
64#define GNUNET_REST_JSONAPI_IDENTITY_NEWNAME "newname"
65
66/**
67 * URL parameter to change the subsytem for ego
68 */ 36 */
69#define GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM "subsystem" 37#define GNUNET_REST_PARAM_PUBKEY "pubkey"
70 38#define GNUNET_REST_PARAM_SUBSYSTEM "subsystem"
39#define GNUNET_REST_PARAM_NAME "name"
40#define GNUNET_REST_PARAM_NEWNAME "newname"
71 41
72/** 42/**
73 * Error messages 43 * Error messages
74 */ 44 */
45#define GNUNET_REST_IDENTITY_ERROR_UNKNOWN "Unknown Error"
75#define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid" 46#define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid"
76#define GNUNET_REST_ERROR_NO_DATA "No data" 47#define GNUNET_REST_ERROR_NO_DATA "No data"
48#define GNUNET_REST_ERROR_DATA_INVALID "Data invalid"
77 49
78/** 50/**
79 * GNUid token lifetime 51 * State while collecting all egos
80 */ 52 */
81#define GNUNET_GNUID_TOKEN_EXPIRATION_MICROSECONDS 300000000 53#define ID_REST_STATE_INIT 0
54
55/**
56 * Done collecting egos
57 */
58#define ID_REST_STATE_POST_INIT 1
82 59
83/** 60/**
84 * The configuration handle 61 * The configuration handle
@@ -129,28 +106,37 @@ struct EgoEntry
129 struct GNUNET_IDENTITY_Ego *ego; 106 struct GNUNET_IDENTITY_Ego *ego;
130}; 107};
131 108
132
133struct RequestHandle 109struct RequestHandle
134{ 110{
135 /** 111 /**
136 * Ego list 112 * The data from the REST request
137 */ 113 */
138 struct EgoEntry *ego_head; 114 const char* data;
139 115
140 /** 116 /**
141 * Ego list 117 * The name to look up
142 */ 118 */
143 struct EgoEntry *ego_tail; 119 char *name;
144 120
145 /** 121 /**
146 * Handle to the rest connection 122 * the length of the REST data
147 */ 123 */
148 struct GNUNET_REST_RequestHandle *conndata_handle; 124 size_t data_size;
149 125
150 /** 126 /**
151 * response code 127 * Requested Subsystem
152 */ 128 */
153 int response_code; 129 char *subsystem;
130
131 /**
132 * Ego list
133 */
134 struct EgoEntry *ego_head;
135
136 /**
137 * Ego list
138 */
139 struct EgoEntry *ego_tail;
154 140
155 /** 141 /**
156 * The processing state 142 * The processing state
@@ -158,7 +144,7 @@ struct RequestHandle
158 int state; 144 int state;
159 145
160 /** 146 /**
161 * Handle to GNS service. 147 * Handle to Identity service.
162 */ 148 */
163 struct GNUNET_IDENTITY_Handle *identity_handle; 149 struct GNUNET_IDENTITY_Handle *identity_handle;
164 150
@@ -168,6 +154,11 @@ struct RequestHandle
168 struct GNUNET_IDENTITY_Operation *op; 154 struct GNUNET_IDENTITY_Operation *op;
169 155
170 /** 156 /**
157 * Rest connection
158 */
159 struct GNUNET_REST_RequestHandle *rest_handle;
160
161 /**
171 * Desired timeout for the lookup (default is no timeout). 162 * Desired timeout for the lookup (default is no timeout).
172 */ 163 */
173 struct GNUNET_TIME_Relative timeout; 164 struct GNUNET_TIME_Relative timeout;
@@ -175,7 +166,7 @@ struct RequestHandle
175 /** 166 /**
176 * ID of a task associated with the resolution process. 167 * ID of a task associated with the resolution process.
177 */ 168 */
178 struct GNUNET_SCHEDULER_Task * timeout_task; 169 struct GNUNET_SCHEDULER_Task *timeout_task;
179 170
180 /** 171 /**
181 * The plugin result processor 172 * The plugin result processor
@@ -188,81 +179,63 @@ struct RequestHandle
188 void *proc_cls; 179 void *proc_cls;
189 180
190 /** 181 /**
191 * The name to look up
192 */
193 char *name;
194
195 /**
196 * The subsystem set from REST
197 */
198 char *subsys;
199
200 /**
201 * The url 182 * The url
202 */ 183 */
203 char *url; 184 char *url;
204 185
205 /** 186 /**
206 * The data from the REST request 187 * Error response message
207 */
208 const char* data;
209
210 /**
211 * the length of the REST data
212 */
213 size_t data_size;
214
215 /**
216 * HTTP method
217 */ 188 */
218 const char* method; 189 char *emsg;
219 190
220 /** 191 /**
221 * Error response message 192 * Reponse code
222 */ 193 */
223 char *emsg; 194 int response_code;
224 195
225}; 196};
226 197
227
228/** 198/**
229 * Cleanup lookup handle 199 * Cleanup lookup handle
230 * @param handle Handle to clean up 200 * @param handle Handle to clean up
231 */ 201 */
232static void 202static void
233cleanup_handle (struct RequestHandle *handle) 203cleanup_handle (void *cls)
234{ 204{
205 struct RequestHandle *handle = cls;
235 struct EgoEntry *ego_entry; 206 struct EgoEntry *ego_entry;
236 struct EgoEntry *ego_tmp; 207 struct EgoEntry *ego_tmp;
237 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 208
238 "Cleaning up\n"); 209 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
239 if (NULL != handle->name)
240 GNUNET_free (handle->name);
241 if (NULL != handle->timeout_task) 210 if (NULL != handle->timeout_task)
242 { 211 {
243 GNUNET_SCHEDULER_cancel (handle->timeout_task); 212 GNUNET_SCHEDULER_cancel (handle->timeout_task);
244 handle->timeout_task = NULL; 213 handle->timeout_task = NULL;
245 } 214 }
246 if (NULL != handle->identity_handle) 215
247 GNUNET_IDENTITY_disconnect (handle->identity_handle); 216 if (NULL != handle->subsystem)
248 if (NULL != handle->subsys) 217 GNUNET_free(handle->subsystem);
249 GNUNET_free (handle->subsys);
250 if (NULL != handle->url) 218 if (NULL != handle->url)
251 GNUNET_free (handle->url); 219 GNUNET_free(handle->url);
252 if (NULL != handle->emsg) 220 if (NULL != handle->emsg)
253 GNUNET_free (handle->emsg); 221 GNUNET_free(handle->emsg);
222 if (NULL != handle->name)
223 GNUNET_free (handle->name);
224 if (NULL != handle->identity_handle)
225 GNUNET_IDENTITY_disconnect (handle->identity_handle);
226
254 for (ego_entry = handle->ego_head; 227 for (ego_entry = handle->ego_head;
255 NULL != ego_entry;) 228 NULL != ego_entry;)
256 { 229 {
257 ego_tmp = ego_entry; 230 ego_tmp = ego_entry;
258 ego_entry = ego_entry->next; 231 ego_entry = ego_entry->next;
259 GNUNET_free (ego_tmp->identifier); 232 GNUNET_free(ego_tmp->identifier);
260 GNUNET_free (ego_tmp->keystring); 233 GNUNET_free(ego_tmp->keystring);
261 GNUNET_free (ego_tmp); 234 GNUNET_free(ego_tmp);
262 } 235 }
263 GNUNET_free (handle);
264}
265 236
237 GNUNET_free(handle);
238}
266 239
267/** 240/**
268 * Task run on errors. Reports an error and cleans up everything. 241 * Task run on errors. Reports an error and cleans up everything.
@@ -274,23 +247,67 @@ do_error (void *cls)
274{ 247{
275 struct RequestHandle *handle = cls; 248 struct RequestHandle *handle = cls;
276 struct MHD_Response *resp; 249 struct MHD_Response *resp;
277 char *json_error; 250 json_t *json_error = json_object();
278 251 char *response;
279 GNUNET_asprintf (&json_error, 252
280 "{Error while processing request: %s}", 253 if (NULL == handle->emsg)
281 &handle->emsg); 254 handle->emsg = GNUNET_strdup(GNUNET_REST_IDENTITY_ERROR_UNKNOWN);
282 255
283 resp = GNUNET_REST_create_response (json_error); 256 json_object_set_new(json_error,"error", json_string(handle->emsg));
284 handle->proc (handle->proc_cls, 257
285 resp, 258 if (0 == handle->response_code)
286 handle->response_code); 259 handle->response_code = MHD_HTTP_OK;
287 cleanup_handle (handle); 260 response = json_dumps (json_error, 0);
288 GNUNET_free (json_error); 261 resp = GNUNET_REST_create_response (response);
262 handle->proc (handle->proc_cls, resp, handle->response_code);
263 json_decref(json_error);
264 GNUNET_free(response);
265 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
289} 266}
290 267
291 268
269
292/** 270/**
293 * Callback for IDENTITY_get() 271 * Get EgoEntry from list with either a public key or a name
272 * If public key and name are not NULL, it returns the public key result first
273 *
274 * @param handle the RequestHandle
275 * @param pubkey the public key of an identity (only one can be NULL)
276 * @param name the name of an identity (only one can be NULL)
277 * @return EgoEntry or NULL if not found
278 */
279struct EgoEntry*
280get_egoentry(struct RequestHandle *handle, char* pubkey, char *name)
281{
282 struct EgoEntry *ego_entry;
283 if (NULL != pubkey)
284 {
285 for (ego_entry = handle->ego_head;
286 NULL != ego_entry;
287 ego_entry = ego_entry->next)
288 {
289 if (0 != strcasecmp (pubkey, ego_entry->keystring))
290 continue;
291 return ego_entry;
292 }
293 }
294 if (NULL != name)
295 {
296 for (ego_entry = handle->ego_head;
297 NULL != ego_entry;
298 ego_entry = ego_entry->next)
299 {
300 if (0 != strcasecmp (name, ego_entry->identifier))
301 continue;
302 return ego_entry;
303 }
304 }
305 return NULL;
306}
307
308
309/**
310 * Callback for GET Request with subsystem
294 * 311 *
295 * @param cls the RequestHandle 312 * @param cls the RequestHandle
296 * @param ego the Ego found 313 * @param ego the Ego found
@@ -298,153 +315,177 @@ do_error (void *cls)
298 * @param name the id of the ego 315 * @param name the id of the ego
299 */ 316 */
300static void 317static void
301get_ego_for_subsys (void *cls, 318ego_get_for_subsystem (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx,
302 struct GNUNET_IDENTITY_Ego *ego, 319 const char *name)
303 void **ctx,
304 const char *name)
305{ 320{
306 struct RequestHandle *handle = cls; 321 struct RequestHandle *handle = cls;
307 struct GNUNET_JSONAPI_Document *json_document;
308 struct GNUNET_JSONAPI_Resource *json_resource;
309 struct EgoEntry *ego_entry;
310 struct MHD_Response *resp; 322 struct MHD_Response *resp;
311 json_t *name_json; 323 struct GNUNET_CRYPTO_EcdsaPublicKey public_key;
324 json_t *json_root;
312 char *result_str; 325 char *result_str;
326 char *public_key_string;
313 327
314 json_document = GNUNET_JSONAPI_document_new (); 328 if(NULL == ego)
315
316 for (ego_entry = handle->ego_head;
317 NULL != ego_entry;
318 ego_entry = ego_entry->next)
319 { 329 {
320 if ( (NULL != name) && (0 != strcmp (name, ego_entry->identifier)) ) 330 handle->emsg = GNUNET_strdup("No identity found for subsystem");
321 continue;
322 if (NULL == name)
323 continue;
324 json_resource = GNUNET_JSONAPI_resource_new
325 (GNUNET_REST_JSONAPI_IDENTITY_EGO, ego_entry->keystring);
326 name_json = json_string (ego_entry->identifier);
327 GNUNET_JSONAPI_resource_add_attr (json_resource,
328 GNUNET_REST_JSONAPI_IDENTITY_NAME,
329 name_json);
330 json_decref (name_json);
331 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
332 break;
333 }
334 if (0 == GNUNET_JSONAPI_document_resource_count (json_document))
335 {
336 GNUNET_JSONAPI_document_delete (json_document);
337 handle->emsg = GNUNET_strdup("No identity matches results!");
338 GNUNET_SCHEDULER_add_now (&do_error, handle); 331 GNUNET_SCHEDULER_add_now (&do_error, handle);
339 return; 332 return;
340 } 333 }
341 GNUNET_JSONAPI_document_serialize (json_document, &result_str); 334
342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); 335 GNUNET_IDENTITY_ego_get_public_key(ego,&public_key);
336 public_key_string = GNUNET_CRYPTO_ecdsa_public_key_to_string(&public_key);
337
338 // create json with subsystem identity
339 json_root = json_object ();
340 json_object_set_new (json_root, GNUNET_REST_PARAM_PUBKEY, json_string(public_key_string));
341 json_object_set_new (json_root, GNUNET_REST_PARAM_NAME, json_string(name));
342
343 result_str = json_dumps (json_root, 0);
344 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
343 resp = GNUNET_REST_create_response (result_str); 345 resp = GNUNET_REST_create_response (result_str);
344 GNUNET_JSONAPI_document_delete (json_document); 346
347 json_decref (json_root);
345 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 348 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
346 GNUNET_free (result_str); 349 GNUNET_free(result_str);
347 cleanup_handle (handle); 350 GNUNET_free(public_key_string);
351 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
348} 352}
349 353
350/** 354/**
351 * Create a response with requested ego(s) 355 * Handle identity GET request
352 * 356 *
353 * @param con the Rest handle 357 * @param con_handle the connection handle
354 * @param url the requested url 358 * @param url the url
355 * @param cls the request handle 359 * @param cls the RequestHandle
356 */ 360 */
357static void 361void
358ego_info_response (struct GNUNET_REST_RequestHandle *con, 362ego_get (struct GNUNET_REST_RequestHandle *con_handle, const char* url,
359 const char *url, 363 void *cls)
360 void *cls)
361{ 364{
362 const char *egoname;
363 char *result_str;
364 char *subsys_val;
365 char *keystring;
366 struct RequestHandle *handle = cls; 365 struct RequestHandle *handle = cls;
367 struct EgoEntry *ego_entry; 366 struct EgoEntry *ego_entry;
368 struct GNUNET_HashCode key; 367 struct GNUNET_HashCode key;
369 struct MHD_Response *resp; 368 struct MHD_Response *resp;
370 struct GNUNET_JSONAPI_Document *json_document; 369 char *keystring;
371 struct GNUNET_JSONAPI_Resource *json_resource; 370 char *egoname;
372 json_t *name_str; 371 json_t *json_root;
372 json_t *json_ego;
373 char *result_str;
373 374
374 if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url, GNUNET_REST_API_NS_IDENTITY)) 375 //requested default identity of subsystem
376 GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_SUBSYSTEM,
377 strlen (GNUNET_REST_PARAM_SUBSYSTEM), &key);
378 if ( GNUNET_YES
379 == GNUNET_CONTAINER_multihashmap_contains (
380 handle->rest_handle->url_param_map, &key))
375 { 381 {
376 resp = GNUNET_REST_create_response (NULL); 382 handle->subsystem = GNUNET_strdup(
377 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST); 383 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
378 cleanup_handle (handle); 384 &key));
385 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n",
386 handle->subsystem);
387
388 handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
389 handle->subsystem,
390 &ego_get_for_subsystem,
391 handle);
392 if (NULL == handle->op)
393 {
394 handle->emsg = GNUNET_strdup("No identity found for subsystem");
395 GNUNET_SCHEDULER_add_now (&do_error, handle);
396 return;
397 }
379 return; 398 return;
380 } 399 }
381 egoname = NULL; 400 egoname = NULL;
382 keystring = NULL; 401 keystring = NULL;
383 if (strlen (GNUNET_REST_API_NS_IDENTITY) < strlen (handle->url)) 402
403 //one identity requested with key
404 GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_PUBKEY,
405 strlen (GNUNET_REST_PARAM_PUBKEY),
406 &key);
407 if ( GNUNET_YES
408 == GNUNET_CONTAINER_multihashmap_contains (
409 handle->rest_handle->url_param_map, &key))
384 { 410 {
385 keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY)+1]; 411 keystring = GNUNET_CONTAINER_multihashmap_get (
386 //Return all egos 412 handle->rest_handle->url_param_map, &key);
387 for (ego_entry = handle->ego_head; 413
388 NULL != ego_entry; 414 ego_entry = get_egoentry(handle, keystring, NULL);
389 ego_entry = ego_entry->next) 415 if (NULL == ego_entry)
390 { 416 {
391 if ( (NULL != keystring) && (0 != strcmp (keystring, ego_entry->keystring)) ) 417 handle->emsg = GNUNET_strdup("No identity found for public key");
392 continue; 418 GNUNET_SCHEDULER_add_now (&do_error, handle);
393 egoname = ego_entry->identifier; 419 return;
394 } 420 }
421 egoname = ego_entry->identifier;
395 } 422 }
396 423
397 if ( NULL == egoname ) { 424 //one identity requested with name
398 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM, 425 if (NULL == egoname)
399 strlen (GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM), 426 {
400 &key); 427 GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_NAME,
401 if ( GNUNET_YES == 428 strlen (GNUNET_REST_PARAM_NAME),
402 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, 429 &key);
403 &key) ) 430 if ( GNUNET_YES
431 == GNUNET_CONTAINER_multihashmap_contains (
432 handle->rest_handle->url_param_map, &key))
404 { 433 {
405 subsys_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, 434 egoname = GNUNET_CONTAINER_multihashmap_get (
406 &key); 435 handle->rest_handle->url_param_map, &key);
407 if (NULL != subsys_val) 436 if (0 >= strlen(egoname))
408 { 437 {
409 GNUNET_asprintf (&handle->subsys, "%s", subsys_val); 438 handle->emsg = GNUNET_strdup("No identity found for name");
410 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", subsys_val); 439 GNUNET_SCHEDULER_add_now (&do_error, handle);
411 handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
412 handle->subsys,
413 &get_ego_for_subsys,
414 handle);
415 return; 440 return;
416 } 441 }
442 //LOWERCASE ego names?
443 GNUNET_STRINGS_utf8_tolower(egoname, egoname);
417 } 444 }
418 } 445 }
419 446
420 json_document = GNUNET_JSONAPI_document_new (); 447 json_root = json_array ();
421 448 //Return ego/egos
422 //Return all egos
423 for (ego_entry = handle->ego_head; 449 for (ego_entry = handle->ego_head;
424 NULL != ego_entry; 450 NULL != ego_entry; ego_entry = ego_entry->next)
425 ego_entry = ego_entry->next)
426 { 451 {
427 if ( (NULL != egoname) && (0 != strcmp (egoname, ego_entry->identifier)) ) 452 //if only one ego requested
428 continue; 453 if ((NULL != egoname)){
429 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_EGO, 454 if(0 != strcmp (egoname, ego_entry->identifier)){
430 ego_entry->keystring); 455 continue;
431 name_str = json_string (ego_entry->identifier); 456 }
432 GNUNET_JSONAPI_resource_add_attr ( 457 }
433 json_resource, 458
434 GNUNET_REST_JSONAPI_IDENTITY_NAME, 459 json_ego = json_object ();
435 name_str); 460 json_object_set_new (json_ego,
436 json_decref (name_str); 461 GNUNET_REST_PARAM_PUBKEY,
437 GNUNET_JSONAPI_document_resource_add (json_document, json_resource); 462 json_string (ego_entry->keystring));
463 json_object_set_new (json_ego,
464 GNUNET_REST_PARAM_NAME,
465 json_string (ego_entry->identifier));
466 json_array_append (json_root, json_ego);
467 json_decref (json_ego);
468 }
469
470 if ((size_t) 0 == json_array_size (json_root))
471 {
472 json_decref (json_root);
473 handle->emsg = GNUNET_strdup("No identities found!");
474 GNUNET_SCHEDULER_add_now (&do_error, handle);
475 return;
438 } 476 }
439 GNUNET_JSONAPI_document_serialize (json_document, &result_str); 477
440 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); 478 result_str = json_dumps (json_root, 0);
479 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
441 resp = GNUNET_REST_create_response (result_str); 480 resp = GNUNET_REST_create_response (result_str);
442 GNUNET_JSONAPI_document_delete (json_document); 481
482 json_decref (json_root);
443 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 483 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
444 GNUNET_free (result_str); 484 GNUNET_free(result_str);
445 cleanup_handle (handle); 485 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
446} 486}
447 487
488
448/** 489/**
449 * Processing finished 490 * Processing finished
450 * 491 *
@@ -460,311 +501,363 @@ do_finished (void *cls, const char *emsg)
460 handle->op = NULL; 501 handle->op = NULL;
461 if (NULL != emsg) 502 if (NULL != emsg)
462 { 503 {
463 handle->emsg = GNUNET_strdup (emsg); 504 handle->emsg = GNUNET_strdup(emsg);
464 GNUNET_SCHEDULER_add_now (&do_error, handle); 505 GNUNET_SCHEDULER_add_now (&do_error, handle);
465 return; 506 return;
466 } 507 }
467 resp = GNUNET_REST_create_response (NULL); 508 resp = GNUNET_REST_create_response (NULL);
468 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT); 509 handle->proc (handle->proc_cls, resp, handle->response_code);
469 cleanup_handle (handle); 510 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
470} 511}
471 512
513
472/** 514/**
473 * Create a new ego 515 * Handle identity PUT request
474 * 516 *
475 * @param con rest handle 517 * @param con_handle the connection handle
476 * @param url url 518 * @param url the url
477 * @param cls request handle 519 * @param cls the RequestHandle
478 */ 520 */
479static void 521void
480ego_create_cont (struct GNUNET_REST_RequestHandle *con, 522ego_edit (struct GNUNET_REST_RequestHandle *con_handle,
481 const char *url, 523 const char* url,
482 void *cls) 524 void *cls)
483{ 525{
484 struct RequestHandle *handle = cls; 526 struct RequestHandle *handle = cls;
485 struct EgoEntry *ego_entry; 527 struct EgoEntry *ego_entry;
528 struct EgoEntry *ego_entry_tmp;
486 struct MHD_Response *resp; 529 struct MHD_Response *resp;
487 struct GNUNET_JSONAPI_Document *json_obj; 530 int json_state;
488 struct GNUNET_JSONAPI_Resource *json_res;
489 json_t *egoname_json;
490 json_t *data_js; 531 json_t *data_js;
491 json_error_t err; 532 json_error_t err;
492 const char* egoname; 533 char *pubkey;
493 char term_data[handle->data_size+1]; 534 char *name;
494 struct GNUNET_JSON_Specification docspec[] = { 535 char *newsubsys;
495 GNUNET_JSON_spec_jsonapi_document (&json_obj), 536 char *newname;
496 GNUNET_JSON_spec_end() 537 char term_data[handle->data_size + 1];
497 }; 538
498 if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url)) 539 //if no data
499 {
500 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID);
501 GNUNET_SCHEDULER_add_now (&do_error, handle);
502 return;
503 }
504 if (0 >= handle->data_size) 540 if (0 >= handle->data_size)
505 { 541 {
506 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA); 542 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
507 GNUNET_SCHEDULER_add_now (&do_error, handle); 543 GNUNET_SCHEDULER_add_now (&do_error, handle);
508 return; 544 return;
509 } 545 }
546 //if not json
510 term_data[handle->data_size] = '\0'; 547 term_data[handle->data_size] = '\0';
511 GNUNET_memcpy (term_data, handle->data, handle->data_size); 548 GNUNET_memcpy(term_data, handle->data, handle->data_size);
512 data_js = json_loads (term_data, 549 data_js = json_loads (term_data,JSON_DECODE_ANY,&err);
513 JSON_DECODE_ANY,
514 &err);
515 GNUNET_assert (NULL != data_js);
516 GNUNET_assert (GNUNET_OK ==
517 GNUNET_JSON_parse (data_js, docspec,
518 NULL, NULL));
519 550
520 json_decref (data_js); 551 if (NULL == data_js)
521
522 if (NULL == json_obj)
523 { 552 {
553 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
524 GNUNET_SCHEDULER_add_now (&do_error, handle); 554 GNUNET_SCHEDULER_add_now (&do_error, handle);
525 return; 555 return;
526 } 556 }
527 if (1 != GNUNET_JSONAPI_document_resource_count (json_obj)) 557
528 { 558 ego_entry = NULL;
529 GNUNET_JSONAPI_document_delete (json_obj); 559 pubkey = NULL;
530 handle->emsg = GNUNET_strdup ("Provided resource count invalid"); 560 name = NULL;
531 GNUNET_SCHEDULER_add_now (&do_error, handle); 561 newname = NULL;
532 return; 562 //NEW NAME
533 } 563 json_state = 0;
534 json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0); 564 json_state = json_unpack(data_js,
535 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res, GNUNET_REST_JSONAPI_IDENTITY_EGO)) 565 "{s:s,s?:s,s?:s}",
536 { 566 GNUNET_REST_PARAM_NEWNAME,
537 GNUNET_JSONAPI_document_delete (json_obj); 567 &newname,
538 resp = GNUNET_REST_create_response (NULL); 568 GNUNET_REST_PARAM_PUBKEY,
539 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); 569 &pubkey,
540 cleanup_handle (handle); 570 GNUNET_REST_PARAM_NAME,
541 return; 571 &name);
542 } 572 //Change name with pubkey or name identifier
543 egoname_json = GNUNET_JSONAPI_resource_read_attr (json_res, GNUNET_REST_JSONAPI_IDENTITY_NAME); 573 if (0 == json_state)
544 if (!json_is_string (egoname_json))
545 { 574 {
546 GNUNET_JSONAPI_document_delete (json_obj); 575 if (NULL == newname)
547 handle->emsg = GNUNET_strdup ("No name provided"); 576 {
548 GNUNET_SCHEDULER_add_now (&do_error, handle); 577 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
578 GNUNET_SCHEDULER_add_now (&do_error, handle);
579 json_decref (data_js);
580 return;
581 }
582
583 if (0 >= strlen(newname))
584 {
585 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
586 GNUNET_SCHEDULER_add_now (&do_error, handle);
587 json_decref (data_js);
588 return;
589 }
590 //lower case name
591 GNUNET_STRINGS_utf8_tolower(newname,newname);
592
593 ego_entry = get_egoentry(handle,pubkey,name);
594
595 if (NULL == ego_entry)
596 {
597 resp = GNUNET_REST_create_response (NULL);
598 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
599 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
600 json_decref (data_js);
601 return;
602 }
603
604 for (ego_entry_tmp = handle->ego_head;
605 NULL != ego_entry_tmp; ego_entry_tmp = ego_entry_tmp->next)
606 {
607 if (0 == strcasecmp (newname, ego_entry_tmp->identifier))
608 {
609 //Ego with same name not allowed
610 resp = GNUNET_REST_create_response (NULL);
611 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
612 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
613 json_decref (data_js);
614 return;
615 }
616 }
617 handle->response_code = MHD_HTTP_NO_CONTENT;
618 handle->op = GNUNET_IDENTITY_rename (handle->identity_handle,
619 ego_entry->identifier, newname,
620 &do_finished, handle);
621 json_decref (data_js);
549 return; 622 return;
550 } 623 }
551 egoname = json_string_value (egoname_json); 624
552 for (ego_entry = handle->ego_head; 625 newsubsys = NULL;
553 NULL != ego_entry; 626 //SUBSYSTEM
554 ego_entry = ego_entry->next) 627 json_state = 0;
628 json_state = json_unpack(data_js,
629 "{s:s,s?:s,s?:s}",
630 GNUNET_REST_PARAM_SUBSYSTEM,
631 &newsubsys,
632 GNUNET_REST_PARAM_PUBKEY,
633 &pubkey,
634 GNUNET_REST_PARAM_NAME,
635 &name);
636 //Change subsystem with pubkey or name identifier
637 if (0 == json_state)
555 { 638 {
556 if (0 == strcasecmp (egoname, ego_entry->identifier)) 639 if (NULL == newsubsys || (NULL == pubkey && NULL == name))
557 { 640 {
558 GNUNET_JSONAPI_document_delete (json_obj); 641 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
559 resp = GNUNET_REST_create_response (NULL); 642 GNUNET_SCHEDULER_add_now (&do_error, handle);
560 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); 643 json_decref (data_js);
561 cleanup_handle (handle); 644 return;
645 }
646
647 if (0 >= strlen(newsubsys))
648 {
649 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
650 GNUNET_SCHEDULER_add_now (&do_error, handle);
651 json_decref (data_js);
562 return; 652 return;
563 } 653 }
654
655 ego_entry = get_egoentry(handle, pubkey, name);
656
657 if (NULL == ego_entry)
658 {
659 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
660 GNUNET_SCHEDULER_add_now (&do_error, handle);
661 json_decref (data_js);
662 return;
663 }
664
665 handle->response_code = MHD_HTTP_NO_CONTENT;
666 handle->op = GNUNET_IDENTITY_set (handle->identity_handle,
667 newsubsys,
668 ego_entry->ego,
669 &do_finished,
670 handle);
671 json_decref (data_js);
672 return;
564 } 673 }
565 GNUNET_asprintf (&handle->name, "%s", egoname);
566 GNUNET_JSONAPI_document_delete (json_obj);
567 handle->op = GNUNET_IDENTITY_create (handle->identity_handle,
568 handle->name,
569 &do_finished,
570 handle);
571}
572 674
675 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
676 GNUNET_SCHEDULER_add_now (&do_error, handle);
677 json_decref (data_js);
678 return;
679}
573 680
574/** 681/**
575 * Handle ego edit request 682 * Handle identity POST request
576 * 683 *
577 * @param con rest connection handle 684 * @param con_handle the connection handle
578 * @param url the url that is requested 685 * @param url the url
579 * @param cls the RequestHandle 686 * @param cls the RequestHandle
580 */ 687 */
581static void 688void
582ego_edit_cont (struct GNUNET_REST_RequestHandle *con, 689ego_create (struct GNUNET_REST_RequestHandle *con_handle, const char* url,
583 const char *url, 690 void *cls)
584 void *cls)
585{ 691{
586 struct GNUNET_JSONAPI_Document *json_obj;
587 struct GNUNET_JSONAPI_Resource *json_res;
588 struct RequestHandle *handle = cls; 692 struct RequestHandle *handle = cls;
589 struct EgoEntry *ego_entry; 693 struct EgoEntry *ego_entry;
590 struct EgoEntry *ego_entry_tmp;
591 struct MHD_Response *resp; 694 struct MHD_Response *resp;
592 json_t *subsys_json;
593 json_t *name_json;
594 json_t *data_js; 695 json_t *data_js;
595 json_error_t err; 696 json_error_t err;
596 const char *keystring; 697 char* egoname;
597 const char *subsys; 698 int json_unpack_state;
598 const char *newname; 699 char term_data[handle->data_size + 1];
599 char term_data[handle->data_size+1];
600 int ego_exists = GNUNET_NO;
601 struct GNUNET_JSON_Specification docspec[] = {
602 GNUNET_JSON_spec_jsonapi_document (&json_obj),
603 GNUNET_JSON_spec_end()
604 };
605 700
606 if (strlen (GNUNET_REST_API_NS_IDENTITY) > strlen (handle->url)) 701 if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url))
607 { 702 {
608 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID); 703 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_RESOURCE_INVALID);
609 GNUNET_SCHEDULER_add_now (&do_error, handle); 704 GNUNET_SCHEDULER_add_now (&do_error, handle);
610 return; 705 return;
611 } 706 }
612 707
613 keystring = &handle->url[strlen(GNUNET_REST_API_NS_IDENTITY)+1];
614
615 for (ego_entry = handle->ego_head;
616 NULL != ego_entry;
617 ego_entry = ego_entry->next)
618 {
619 if (0 != strcasecmp (keystring, ego_entry->keystring))
620 continue;
621 ego_exists = GNUNET_YES;
622 break;
623 }
624
625 if (GNUNET_NO == ego_exists)
626 {
627 resp = GNUNET_REST_create_response (NULL);
628 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
629 cleanup_handle (handle);
630 return;
631 }
632
633 if (0 >= handle->data_size) 708 if (0 >= handle->data_size)
634 { 709 {
635 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA); 710 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
636 GNUNET_SCHEDULER_add_now (&do_error, handle); 711 GNUNET_SCHEDULER_add_now (&do_error, handle);
637 return; 712 return;
638 } 713 }
639
640 term_data[handle->data_size] = '\0'; 714 term_data[handle->data_size] = '\0';
641 GNUNET_memcpy (term_data, handle->data, handle->data_size); 715 GNUNET_memcpy(term_data, handle->data, handle->data_size);
642 data_js = json_loads (term_data, 716 data_js = json_loads (term_data,
643 JSON_DECODE_ANY, 717 JSON_DECODE_ANY,
644 &err); 718 &err);
645 GNUNET_assert (NULL != data_js); 719 if (NULL == data_js)
646 GNUNET_assert (GNUNET_OK ==
647 GNUNET_JSON_parse (data_js, docspec,
648 NULL, NULL));
649
650 json_decref (data_js);
651
652 if (NULL == json_obj)
653 { 720 {
654 handle->emsg = GNUNET_strdup ("Data invalid"); 721 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
655 GNUNET_SCHEDULER_add_now (&do_error, handle); 722 GNUNET_SCHEDULER_add_now (&do_error, handle);
723 json_decref (data_js);
656 return; 724 return;
657 } 725 }
658 726 json_unpack_state = 0;
659 if (1 != GNUNET_JSONAPI_document_resource_count (json_obj)) 727 json_unpack_state = json_unpack(data_js,
728 "{s:s!}",
729 GNUNET_REST_PARAM_NAME,
730 &egoname);
731 if (0 != json_unpack_state)
660 { 732 {
661 GNUNET_JSONAPI_document_delete (json_obj); 733 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
662 handle->emsg = GNUNET_strdup ("Resource amount invalid");
663 GNUNET_SCHEDULER_add_now (&do_error, handle); 734 GNUNET_SCHEDULER_add_now (&do_error, handle);
735 json_decref (data_js);
664 return; 736 return;
665 } 737 }
666 json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
667 738
668 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res, GNUNET_REST_JSONAPI_IDENTITY_EGO)) 739 if (NULL == egoname)
669 { 740 {
670 GNUNET_JSONAPI_document_delete (json_obj); 741 handle->emsg = GNUNET_strdup("No name provided");
671 handle->emsg = GNUNET_strdup ("Resource type invalid");
672 GNUNET_SCHEDULER_add_now (&do_error, handle); 742 GNUNET_SCHEDULER_add_now (&do_error, handle);
743 json_decref (data_js);
673 return; 744 return;
674 } 745 }
675 746 if (0 >= strlen (egoname))
676 //This is a rename
677 name_json = GNUNET_JSONAPI_resource_read_attr (json_res,
678 GNUNET_REST_JSONAPI_IDENTITY_NEWNAME);
679 if ((NULL != name_json) && json_is_string (name_json))
680 { 747 {
681 newname = json_string_value (name_json); 748 json_decref (data_js);
682 for (ego_entry_tmp = handle->ego_head; 749 handle->emsg = GNUNET_strdup("No name provided");
683 NULL != ego_entry_tmp; 750 GNUNET_SCHEDULER_add_now (&do_error, handle);
684 ego_entry_tmp = ego_entry_tmp->next)
685 {
686 if (0 == strcasecmp (newname, ego_entry_tmp->identifier) &&
687 0 != strcasecmp (keystring, ego_entry_tmp->keystring))
688 {
689 //Ego with same name not allowed
690 GNUNET_JSONAPI_document_delete (json_obj);
691 resp = GNUNET_REST_create_response (NULL);
692 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
693 cleanup_handle (handle);
694 return;
695 }
696 }
697 handle->op = GNUNET_IDENTITY_rename (handle->identity_handle,
698 ego_entry->identifier,
699 newname,
700 &do_finished,
701 handle);
702 GNUNET_JSONAPI_document_delete (json_obj);
703 return; 751 return;
704 } 752 }
705 753 GNUNET_STRINGS_utf8_tolower(egoname, egoname);
706 //Set subsystem 754 for (ego_entry = handle->ego_head;
707 subsys_json = GNUNET_JSONAPI_resource_read_attr (json_res, GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM); 755 NULL != ego_entry; ego_entry = ego_entry->next)
708 if ( (NULL != subsys_json) && json_is_string (subsys_json))
709 { 756 {
710 subsys = json_string_value (subsys_json); 757 if (0 == strcasecmp (egoname, ego_entry->identifier))
711 GNUNET_asprintf (&handle->subsys, "%s", subsys); 758 {
712 GNUNET_JSONAPI_document_delete (json_obj); 759 resp = GNUNET_REST_create_response (NULL);
713 handle->op = GNUNET_IDENTITY_set (handle->identity_handle, 760 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
714 handle->subsys, 761 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
715 ego_entry->ego, 762 json_decref (data_js);
716 &do_finished, 763 return;
717 handle); 764 }
718 return;
719 } 765 }
720 GNUNET_JSONAPI_document_delete (json_obj); 766 handle->name = GNUNET_strdup(egoname);
721 handle->emsg = GNUNET_strdup ("Subsystem not provided"); 767 json_decref (data_js);
722 GNUNET_SCHEDULER_add_now (&do_error, handle); 768 handle->response_code = MHD_HTTP_CREATED;
769 handle->op = GNUNET_IDENTITY_create (handle->identity_handle, handle->name,
770 &do_finished, handle);
723} 771}
724 772
773/**
774 * Handle identity DELETE request
775 *
776 * @param con_handle the connection handle
777 * @param url the url
778 * @param cls the RequestHandle
779 */
725void 780void
726ego_delete_cont (struct GNUNET_REST_RequestHandle *con_handle, 781ego_delete (struct GNUNET_REST_RequestHandle *con_handle, const char* url,
727 const char* url, 782 void *cls)
728 void *cls)
729{ 783{
730 const char *keystring; 784 struct RequestHandle *handle = cls;
731 struct EgoEntry *ego_entry; 785 struct EgoEntry *ego_entry;
786 struct GNUNET_HashCode key;
732 struct MHD_Response *resp; 787 struct MHD_Response *resp;
733 struct RequestHandle *handle = cls; 788 const char *keystring;
789 char *egoname;
734 int ego_exists = GNUNET_NO; 790 int ego_exists = GNUNET_NO;
735 791
736 if (strlen (GNUNET_REST_API_NS_IDENTITY) >= strlen (handle->url)) 792 keystring = NULL;
793 egoname = NULL;
794
795 //delete with pubkey
796 GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_PUBKEY,
797 strlen (GNUNET_REST_PARAM_PUBKEY), &key);
798 if ( GNUNET_YES
799 == GNUNET_CONTAINER_multihashmap_contains (
800 handle->rest_handle->url_param_map, &key))
737 { 801 {
738 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID); 802 keystring = GNUNET_CONTAINER_multihashmap_get (
739 GNUNET_SCHEDULER_add_now (&do_error, handle); 803 handle->rest_handle->url_param_map,&key);
740 return;
741 } 804 }
742 805
743 keystring = &handle->url[strlen(GNUNET_REST_API_NS_IDENTITY)+1]; 806 GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_NAME,
744 for (ego_entry = handle->ego_head; 807 strlen (GNUNET_REST_PARAM_NAME), &key);
745 NULL != ego_entry; 808 if ( GNUNET_YES
746 ego_entry = ego_entry->next) 809 == GNUNET_CONTAINER_multihashmap_contains (
810 handle->rest_handle->url_param_map, &key))
747 { 811 {
748 if (0 != strcasecmp (keystring, ego_entry->keystring)) 812 egoname = GNUNET_CONTAINER_multihashmap_get (
749 continue; 813 handle->rest_handle->url_param_map, &key);
750 ego_exists = GNUNET_YES; 814 //LOWERCASE ego names?
751 break; 815 //GNUNET_STRINGS_utf8_tolower(egoname, egoname);
752 } 816 }
817
818 if (NULL != keystring)
819 {
820 for (ego_entry = handle->ego_head;
821 NULL != ego_entry; ego_entry = ego_entry->next)
822 {
823 if (0 != strcasecmp (keystring, ego_entry->keystring))
824 continue;
825 ego_exists = GNUNET_YES;
826 break;
827 }
828 }
829 else if (NULL != egoname)
830 {
831 for (ego_entry = handle->ego_head;
832 NULL != ego_entry; ego_entry = ego_entry->next)
833 {
834 if (0 != strcmp (egoname, ego_entry->identifier))
835 continue;
836 ego_exists = GNUNET_YES;
837 break;
838 }
839 }
840 else
841 {
842 handle->emsg = GNUNET_strdup("Missing parameter pubkey or name");
843 GNUNET_SCHEDULER_add_now (&do_error, handle);
844 return;
845 }
846
753 if (GNUNET_NO == ego_exists) 847 if (GNUNET_NO == ego_exists)
754 { 848 {
755 resp = GNUNET_REST_create_response (NULL); 849 resp = GNUNET_REST_create_response (NULL);
756 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); 850 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
757 cleanup_handle (handle); 851 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
758 return; 852 return;
759 } 853 }
854 handle->response_code = MHD_HTTP_NO_CONTENT;
760 handle->op = GNUNET_IDENTITY_delete (handle->identity_handle, 855 handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
761 ego_entry->identifier, 856 ego_entry->identifier, &do_finished,
762 &do_finished, 857 handle);
763 handle);
764 858
765} 859}
766 860
767
768/** 861/**
769 * Respond to OPTIONS request 862 * Respond to OPTIONS request
770 * 863 *
@@ -773,20 +866,17 @@ ego_delete_cont (struct GNUNET_REST_RequestHandle *con_handle,
773 * @param cls the RequestHandle 866 * @param cls the RequestHandle
774 */ 867 */
775static void 868static void
776options_cont (struct GNUNET_REST_RequestHandle *con_handle, 869options_cont (struct GNUNET_REST_RequestHandle *con_handle, const char* url,
777 const char* url, 870 void *cls)
778 void *cls)
779{ 871{
780 struct MHD_Response *resp; 872 struct MHD_Response *resp;
781 struct RequestHandle *handle = cls; 873 struct RequestHandle *handle = cls;
782 874
783 //For now, independent of path return all options 875 //For now, independent of path return all options
784 resp = GNUNET_REST_create_response (NULL); 876 resp = GNUNET_REST_create_response (NULL);
785 MHD_add_response_header (resp, 877 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
786 "Access-Control-Allow-Methods",
787 allow_methods);
788 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 878 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
789 cleanup_handle (handle); 879 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
790 return; 880 return;
791} 881}
792 882
@@ -800,18 +890,17 @@ init_cont (struct RequestHandle *handle)
800{ 890{
801 struct GNUNET_REST_RequestHandlerError err; 891 struct GNUNET_REST_RequestHandlerError err;
802 static const struct GNUNET_REST_RequestHandler handlers[] = { 892 static const struct GNUNET_REST_RequestHandler handlers[] = {
803 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_info_response}, 893 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_get },
804 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create_cont}, 894 { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY, &ego_edit },
805 {MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY, &ego_edit_cont}, 895 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create },
806 {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_IDENTITY, &ego_delete_cont}, 896 { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_IDENTITY, &ego_delete },
807 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont}, 897 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont },
808 GNUNET_REST_HANDLER_END 898 GNUNET_REST_HANDLER_END
809 }; 899 };
810 900
811 if (GNUNET_NO == GNUNET_JSONAPI_handle_request (handle->conndata_handle, 901 if (GNUNET_NO
812 handlers, 902 == GNUNET_REST_handle_request (handle->rest_handle, handlers, &err,
813 &err, 903 handle))
814 handle))
815 { 904 {
816 handle->response_code = err.error_code; 905 handle->response_code = err.error_code;
817 GNUNET_SCHEDULER_add_now (&do_error, handle); 906 GNUNET_SCHEDULER_add_now (&do_error, handle);
@@ -852,10 +941,8 @@ init_cont (struct RequestHandle *handle)
852 * must thus no longer be used 941 * must thus no longer be used
853 */ 942 */
854static void 943static void
855list_ego (void *cls, 944init_egos (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx,
856 struct GNUNET_IDENTITY_Ego *ego, 945 const char *identifier)
857 void **ctx,
858 const char *identifier)
859{ 946{
860 struct RequestHandle *handle = cls; 947 struct RequestHandle *handle = cls;
861 struct EgoEntry *ego_entry; 948 struct EgoEntry *ego_entry;
@@ -867,16 +954,16 @@ list_ego (void *cls,
867 init_cont (handle); 954 init_cont (handle);
868 return; 955 return;
869 } 956 }
870 if (ID_REST_STATE_INIT == handle->state) { 957 if (ID_REST_STATE_INIT == handle->state)
871 ego_entry = GNUNET_new (struct EgoEntry); 958 {
959 ego_entry = GNUNET_new(struct EgoEntry);
872 GNUNET_IDENTITY_ego_get_public_key (ego, &pk); 960 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
873 ego_entry->keystring = 961 ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
874 GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
875 ego_entry->ego = ego; 962 ego_entry->ego = ego;
876 GNUNET_asprintf (&ego_entry->identifier, "%s", identifier); 963 GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
877 GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry); 964 GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head, handle->ego_tail,
965 ego_entry);
878 } 966 }
879
880} 967}
881 968
882/** 969/**
@@ -891,39 +978,30 @@ list_ego (void *cls,
891 * @return GNUNET_OK if request accepted 978 * @return GNUNET_OK if request accepted
892 */ 979 */
893static void 980static void
894rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle, 981rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
895 GNUNET_REST_ResultProcessor proc, 982 GNUNET_REST_ResultProcessor proc, void *proc_cls)
896 void *proc_cls)
897{ 983{
898 struct RequestHandle *handle = GNUNET_new (struct RequestHandle); 984 struct RequestHandle *handle = GNUNET_new(struct RequestHandle);
899
900
901 985
986 handle->response_code = 0;
902 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; 987 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
903
904 handle->proc_cls = proc_cls; 988 handle->proc_cls = proc_cls;
905 handle->proc = proc; 989 handle->proc = proc;
906 handle->state = ID_REST_STATE_INIT; 990 handle->rest_handle = rest_handle;
907 handle->conndata_handle = conndata_handle; 991 handle->data = rest_handle->data;
908 handle->data = conndata_handle->data; 992 handle->data_size = rest_handle->data_size;
909 handle->data_size = conndata_handle->data_size; 993
910 handle->method = conndata_handle->method; 994 handle->url = GNUNET_strdup(rest_handle->url);
911 GNUNET_asprintf (&handle->url, "%s", conndata_handle->url); 995 if (handle->url[strlen (handle->url) - 1] == '/')
912 if (handle->url[strlen (handle->url)-1] == '/') 996 handle->url[strlen (handle->url) - 1] = '\0';
913 handle->url[strlen (handle->url)-1] = '\0'; 997 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
914 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 998
915 "Connecting...\n"); 999 handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &init_egos, handle);
916 handle->identity_handle = GNUNET_IDENTITY_connect (cfg, 1000
917 &list_ego, 1001 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
918 handle); 1002 &do_error, handle);
919 handle->timeout_task = 1003
920 GNUNET_SCHEDULER_add_delayed (handle->timeout, 1004 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
921 &do_error,
922 handle);
923
924
925 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
926 "Connected\n");
927} 1005}
928 1006
929/** 1007/**
@@ -940,27 +1018,24 @@ libgnunet_plugin_rest_identity_init (void *cls)
940 1018
941 cfg = cls; 1019 cfg = cls;
942 if (NULL != plugin.cfg) 1020 if (NULL != plugin.cfg)
943 return NULL; /* can only initialize once! */ 1021 return NULL; /* can only initialize once! */
944 memset (&plugin, 0, sizeof (struct Plugin)); 1022 memset (&plugin, 0, sizeof(struct Plugin));
945 plugin.cfg = cfg; 1023 plugin.cfg = cfg;
946 api = GNUNET_new (struct GNUNET_REST_Plugin); 1024 api = GNUNET_new(struct GNUNET_REST_Plugin);
947 api->cls = &plugin; 1025 api->cls = &plugin;
948 api->name = GNUNET_REST_API_NS_IDENTITY; 1026 api->name = GNUNET_REST_API_NS_IDENTITY;
949 api->process_request = &rest_identity_process_request; 1027 api->process_request = &rest_process_request;
950 GNUNET_asprintf (&allow_methods, 1028 GNUNET_asprintf (&allow_methods, "%s, %s, %s, %s, %s",
951 "%s, %s, %s, %s, %s", 1029 MHD_HTTP_METHOD_GET,
952 MHD_HTTP_METHOD_GET, 1030 MHD_HTTP_METHOD_POST,
953 MHD_HTTP_METHOD_POST, 1031 MHD_HTTP_METHOD_PUT,
954 MHD_HTTP_METHOD_PUT, 1032 MHD_HTTP_METHOD_DELETE,
955 MHD_HTTP_METHOD_DELETE, 1033 MHD_HTTP_METHOD_OPTIONS);
956 MHD_HTTP_METHOD_OPTIONS); 1034
957 1035 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, _("Identity REST API initialized\n"));
958 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
959 _("Identity REST API initialized\n"));
960 return api; 1036 return api;
961} 1037}
962 1038
963
964/** 1039/**
965 * Exit point from the plugin. 1040 * Exit point from the plugin.
966 * 1041 *
@@ -972,13 +1047,13 @@ libgnunet_plugin_rest_identity_done (void *cls)
972{ 1047{
973 struct GNUNET_REST_Plugin *api = cls; 1048 struct GNUNET_REST_Plugin *api = cls;
974 struct Plugin *plugin = api->cls; 1049 struct Plugin *plugin = api->cls;
975
976 plugin->cfg = NULL; 1050 plugin->cfg = NULL;
977 GNUNET_free_non_null (allow_methods); 1051
978 GNUNET_free (api); 1052 GNUNET_free_non_null(allow_methods);
979 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 1053 GNUNET_free(api);
980 "Identity REST plugin is finished\n"); 1054 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Identity REST plugin is finished\n");
981 return NULL; 1055 return NULL;
982} 1056}
983 1057
984/* end of plugin_rest_gns.c */ 1058/* end of plugin_rest_identity.c */
1059
diff --git a/src/identity/test_plugin_rest_identity.sh b/src/identity/test_plugin_rest_identity.sh
new file mode 100755
index 000000000..d9377500e
--- /dev/null
+++ b/src/identity/test_plugin_rest_identity.sh
@@ -0,0 +1,159 @@
1#!/usr/bin/bash
2
3#First, start gnunet-arm and the rest-service.
4#Exit 0 means success, exit 1 means failed test
5
6identity_link="http://localhost:7776/identity"
7wrong_link="http://localhost:7776/identityandmore"
8
9
10curl_get () {
11 #$1 is link
12 #$2 is grep
13 cache="$(curl -v "$1" 2>&1 | grep "$2")"
14 #echo $cache
15 if [ "" == "$cache" ]
16 then
17 exit 1
18 fi
19}
20
21curl_post () {
22 #$1 is link
23 #$2 is data
24 #$3 is grep
25 cache="$(curl -v -X "POST" "$1" --data "$2" 2>&1 | grep "$3")"
26 #echo $cache
27 if [ "" == "$cache" ]
28 then
29 exit 1
30 fi
31}
32
33curl_delete () {
34 #$1 is link
35 #$2 is grep
36 cache="$(curl -v -X "DELETE" "$1" 2>&1 | grep "$2")"
37 #echo $cache
38 if [ "" == "$cache" ]
39 then
40 exit 1
41 fi
42}
43
44curl_put () {
45 #$1 is link
46 #$2 is data
47 #$3 is grep
48 cache="$(curl -v -X "PUT" "$1" --data "$2" 2>&1 | grep "$3")"
49 #echo $cache
50 if [ "" == "$cache" ]
51 then
52 exit 1
53 fi
54}
55
56#Test GET
57test="$(gnunet-identity -d)"
58#if no identity exists
59if [ "" == "$test" ]
60then
61 curl_get "$identity_link" "error"
62 gnunet-identity -C "test_plugin_rest_identity"
63 name="$(gnunet-identity -d | awk 'NR==1{print $1}')"
64 public="$(gnunet-identity -d | awk 'NR==1{print $3}')"
65
66 curl_get "${identity_link}?name=$name" "$public"
67 curl_get "${identity_link}?name=" "error"
68 curl_get "${identity_link}?name=$public" "error"
69
70 curl_get "${identity_link}?pubkey=$public" "$name"
71 curl_get "${identity_link}?pubkey=$name" "error"
72 curl_get "${identity_link}?pubkey=" "error"
73
74 gnunet-identity -D "test_plugin_rest_identity"
75else
76 name="$(gnunet-identity -d | awk 'NR==1{print $1}')"
77 public="$(gnunet-identity -d | awk 'NR==1{print $3}')"
78
79 curl_get "${identity_link}?name=$name" "$public"
80 curl_get "${identity_link}?name=" "error"
81 curl_get "${identity_link}?name=$public" "error"
82
83 curl_get "${identity_link}?pubkey=$public" "$name"
84 curl_get "${identity_link}?pubkey=$name" "error"
85 curl_get "${identity_link}?pubkey=" "error"
86fi
87
88#Test POST
89gnunet-identity -D "test_plugin_rest_identity" > /dev/null 2>&1
90gnunet-identity -D "test_plugin_rest_identity1" > /dev/null 2>&1
91
92curl_post "${identity_link}" '{"name":"test_plugin_rest_identity"}' "HTTP/1.1 201 Created"
93curl_post "${identity_link}" '{"name":"test_plugin_rest_identity"}' "HTTP/1.1 409"
94curl_post "${identity_link}" '{"name":"Test_plugin_rest_identity"}' "HTTP/1.1 409"
95curl_post "${identity_link}" '{}' "error"
96curl_post "${identity_link}" '' "error"
97curl_post "${identity_link}" '{"name":""}' "error"
98curl_post "${identity_link}" '{"name":123}' "error"
99curl_post "${identity_link}" '{"name":[]}' "error"
100curl_post "${identity_link}" '{"name1":"test_plugin_rest_identity"}' "error"
101curl_post "${identity_link}" '{"other":""}' "error"
102curl_post "${identity_link}" '{"name":"test_plugin_rest_identity1", "other":"test_plugin_rest_identity2"}' "error"
103
104#Test PUT
105name="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $1}')"
106public="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $3}')"
107
108curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubkey":"'$public'"}' "HTTP/1.1 204"
109curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubkey":"'$public'"}' "HTTP/1.1 409"
110curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubkey":"'$public'xx"}' "HTTP/1.1 404"
111curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubkey":""}' "HTTP/1.1 404"
112curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubke":""}' "HTTP/1.1 404"
113curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubke":"","other":"sdfdsf"}' "HTTP/1.1 404"
114curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","pubke":"","name":"sdfdsf"}' "HTTP/1.1 404"
115curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity","pubke":"","name":"test_plugin_rest_identity1"}' "HTTP/1.1 204"
116curl_put "${identity_link}" '{"newnam":"test_plugin_rest_identity","pubkey":"'$public'"}' "error"
117curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","name":"test_plugin_rest_identity"}' "HTTP/1.1 204"
118curl_put "${identity_link}" '{"newname":"TEST_plugin_rest_identity1","name":"test_plugin_rest_identity1"}' "HTTP/1.1 409"
119curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity1","name":"test_plugin_rest_identity1"}' "HTTP/1.1 409"
120curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity","name":"test_plugin_rest_identityxxx"}' "HTTP/1.1 404"
121curl_put "${identity_link}" '{"newname":"test_plugin_rest_identity","name":"test_plugin_rest_identity1"}' "HTTP/1.1 204"
122curl_put "${identity_link}" '{"newnam":"test_plugin_rest_identityfail","name":"test_plugin_rest_identity"}' "error"
123
124
125#Test subsystem
126curl_put "${identity_link}" '{"subsystem":"namestore","name":"test_plugin_rest_identity"}' "HTTP/1.1 204"
127curl_put "${identity_link}" '{"subsystem":"namestore","name":"test_plugin_rest_identity"}' "HTTP/1.1 204"
128curl_get "${identity_link}?subsystem=namestore" "test_plugin_rest_identity"
129curl_post "${identity_link}" '{"name":"test_plugin_rest_identity1"}' "HTTP/1.1 201 Created"
130public="$(gnunet-identity -d | grep "test_plugin_rest_identity" | awk 'NR==1{print $3}')"
131curl_put "${identity_link}" '{"subsystem":"namestore","pubkey":"'"$public"'"}' "HTTP/1.1 204"
132curl_get "${identity_link}?subsystem=namestore" "test_plugin_rest_identity1"
133curl_get "${identity_link}?subsystem=test_plugin_rest_identity_no_subsystem" "error"
134curl_put "${identity_link}" '{"subsystem":"test_plugin_rest_identity_no_subsystem","name":"test_plugin_rest_identity1"}' "HTTP/1.1 204"
135curl_get "${identity_link}?subsystem=test_plugin_rest_identity_no_subsystem" "test_plugin_rest_identity1"
136
137curl_put "${identity_link}" '{"subsyste":"test_plugin_rest_identity_no_subsystem","name":"test_plugin_rest_identity1"}' "error"
138curl_put "${identity_link}" '{"subsystem":"test_plugin_rest_identity_no_subsystem","name":"Test_plugin_rest_identity1"}' "HTTP/1.1 204"
139
140#Test DELETE
141curl_delete "${identity_link}?name=test_plugin_rest_identity" "HTTP/1.1 204"
142curl_get "${identity_link}?name=test_plugin_rest_identity" "error"
143curl_delete "${identity_link}?name=TEST_plugin_rest_identity1" "HTTP/1.1 404"
144curl_delete "${identity_link}?name=test_plugin_rest_identity1" "HTTP/1.1 204"
145curl_get "${identity_link}?name=test_plugin_rest_identity1" "error"
146curl_delete "${identity_link}?name=test_plugin_rest_identity_not_found" "HTTP/1.1 404"
147curl_post "${identity_link}" '{"name":"test_plugin_rest_identity1"}' "HTTP/1.1 201 Created"
148public="$(gnunet-identity -d | grep "test_plugin_rest_identity1" | awk 'NR==1{print $3}')"
149curl_delete "${identity_link}?pubkey=$public" "HTTP/1.1 204"
150curl_delete "${identity_link}?pubke=$public" "error"
151curl_delete "${identity_link}?pubkey=$public&other=232" "HTTP/1.1 404"
152
153#Test wrong_link
154curl_get "$wrong_link" "HTTP/1.1 404"
155curl_post "$wrong_link" '{"name":"test_plugin_rest_identity"}' "HTTP/1.1 404"
156curl_put "$wrong_link" '{"newname":"test_plugin_rest_identity1","name":"test_plugin_rest_identity"}' "HTTP/1.1 404"
157curl_delete "$wrong_link?name=test_plugin_rest_identity1" "HTTP/1.1 404"
158
159exit 0;