aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gns/plugin_rest_gns.c681
-rw-r--r--src/gns/plugin_rest_gns2.c717
-rw-r--r--src/identity/plugin_rest_identity.c910
-rwxr-xr-xsrc/identity/test_plugin_identity_rest.sh252
-rwxr-xr-xsrc/identity/test_plugin_rest_identity.sh216
5 files changed, 1849 insertions, 927 deletions
diff --git a/src/gns/plugin_rest_gns.c b/src/gns/plugin_rest_gns.c
index 2b729db54..22c908275 100644
--- a/src/gns/plugin_rest_gns.c
+++ b/src/gns/plugin_rest_gns.c
@@ -2,51 +2,50 @@
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
6 under the terms of the GNU Affero General Public License as published 6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation, either version 3 of the License, 7 by the Free Software Foundation; either version 3, or (at your
8 or (at your option) any later version. 8 option) any later version.
9 9
10 GNUnet is distributed in the hope that it will be useful, but 10 GNUnet is distributed in the hope that it will be useful, but
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 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 General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
17 */ 19 */
18/** 20/**
19 * @author Martin Schanzenbach 21 * @author Philippe Buschmann
20 * @file gns/plugin_rest_gns.c 22 * @file gns/plugin_rest_gns.c
21 * @brief GNUnet GNS REST plugin 23 * @brief GNUnet Gns REST plugin
22 *
23 */ 24 */
24 25
25#include "platform.h" 26#include "platform.h"
26#include "gnunet_rest_plugin.h" 27#include "gnunet_rest_plugin.h"
27#include <gnunet_dnsparser_lib.h> 28#include "gnunet_rest_lib.h"
28#include <gnunet_identity_service.h> 29#include "gnunet_gnsrecord_lib.h"
29#include <gnunet_gnsrecord_lib.h> 30#include "gnunet_gns_service.h"
30#include <gnunet_namestore_service.h> 31#include "microhttpd.h"
31#include <gnunet_gns_service.h>
32#include <gnunet_rest_lib.h>
33#include <gnunet_jsonapi_lib.h>
34#include <gnunet_jsonapi_util.h>
35#include <jansson.h> 32#include <jansson.h>
36 33
37#define GNUNET_REST_API_NS_GNS "/gns" 34#define GNUNET_REST_API_NS_GNS "/gns"
38 35
39#define GNUNET_REST_JSONAPI_GNS_RECORD_TYPE "record_type" 36#define GNUNET_REST_PARAMETER_GNS_NAME "name"
40
41#define GNUNET_REST_JSONAPI_GNS_TYPEINFO "gns_name"
42 37
43#define GNUNET_REST_JSONAPI_GNS_RECORD "records" 38#define GNUNET_REST_PARAMETER_GNS_RECORD_TYPE "record_type"
44 39
45#define GNUNET_REST_JSONAPI_GNS_EGO "ego" 40/**
46 41 * The configuration handle
47#define GNUNET_REST_JSONAPI_GNS_PKEY "pkey" 42 */
43const struct GNUNET_CONFIGURATION_Handle *cfg;
48 44
49#define GNUNET_REST_JSONAPI_GNS_OPTIONS "options" 45/**
46 * HTTP methods allows for this plugin
47 */
48static char* allow_methods;
50 49
51/** 50/**
52 * @brief struct returned by the initialization function of the plugin 51 * @brief struct returned by the initialization function of the plugin
@@ -56,54 +55,45 @@ struct Plugin
56 const struct GNUNET_CONFIGURATION_Handle *cfg; 55 const struct GNUNET_CONFIGURATION_Handle *cfg;
57}; 56};
58 57
59const struct GNUNET_CONFIGURATION_Handle *cfg;
60 58
61struct LookupHandle 59
60struct RequestHandle
62{ 61{
63 /**
64 * Handle to GNS service.
65 */
66 struct GNUNET_GNS_Handle *gns;
67 62
68 /** 63 /**
69 * Desired timeout for the lookup (default is no timeout). 64 * Connection to GNS
70 */ 65 */
71 struct GNUNET_TIME_Relative timeout; 66 struct GNUNET_GNS_Handle *gns;
72 67
73 /** 68 /**
74 * Handle to lookup request 69 * Active GNS lookup
75 */ 70 */
76 struct GNUNET_GNS_LookupRequest *lookup_request; 71 struct GNUNET_GNS_LookupWithTldRequest *gns_lookup;
77 72
78 /** 73 /**
79 * Handle to rest request 74 * Name to look up
80 */ 75 */
81 struct GNUNET_REST_RequestHandle *rest_handle; 76 char *name;
82 77
83 /** 78 /**
84 * Lookup an ego with the identity service. 79 * Record type to look up
85 */ 80 */
86 struct GNUNET_IDENTITY_EgoLookup *el; 81 int record_type;
87 82
88 /** 83 /**
89 * Handle for identity service. 84 * Rest connection
90 */ 85 */
91 struct GNUNET_IDENTITY_Handle *identity; 86 struct GNUNET_REST_RequestHandle *rest_handle;
92 87
93 /** 88 /**
94 * Active operation on identity service. 89 * Desired timeout for the lookup (default is no timeout).
95 */ 90 */
96 struct GNUNET_IDENTITY_Operation *id_op; 91 struct GNUNET_TIME_Relative timeout;
97 92
98 /** 93 /**
99 * ID of a task associated with the resolution process. 94 * ID of a task associated with the resolution process.
100 */ 95 */
101 struct GNUNET_SCHEDULER_Task * timeout_task; 96 struct GNUNET_SCHEDULER_Task *timeout_task;
102
103 /**
104 * The root of the received JSON or NULL
105 */
106 json_t *json_root;
107 97
108 /** 98 /**
109 * The plugin result processor 99 * The plugin result processor
@@ -116,49 +106,17 @@ struct LookupHandle
116 void *proc_cls; 106 void *proc_cls;
117 107
118 /** 108 /**
119 * The name to look up 109 * The url
120 */
121 char *name;
122
123 /**
124 * The ego to use
125 * In string representation from JSON
126 */
127 const char *ego_str;
128
129 /**
130 * The Pkey to use
131 * In string representation from JSON
132 */
133 const char *pkey_str;
134
135 /**
136 * The record type
137 */
138 int type;
139
140 /**
141 * The public key of to use for lookup
142 */ 110 */
143 struct GNUNET_CRYPTO_EcdsaPublicKey pkey; 111 char *url;
144 112
145 /** 113 /**
146 * The public key to use for lookup 114 * Error response message
147 */ 115 */
148 struct GNUNET_CRYPTO_EcdsaPublicKey pkeym; 116 char *emsg;
149 117
150 /** 118 /**
151 * The resolver options 119 * Reponse code
152 */
153 enum GNUNET_GNS_LocalOptions options;
154
155 /**
156 * the shorten key
157 */
158 struct GNUNET_CRYPTO_EcdsaPrivateKey shorten_key;
159
160 /**
161 * HTTP response code
162 */ 120 */
163 int response_code; 121 int response_code;
164 122
@@ -166,39 +124,19 @@ struct LookupHandle
166 124
167 125
168/** 126/**
169 * Cleanup lookup handle. 127 * Cleanup lookup handle
170 *
171 * @param handle Handle to clean up 128 * @param handle Handle to clean up
172 */ 129 */
173static void 130static void
174cleanup_handle (struct LookupHandle *handle) 131cleanup_handle (struct RequestHandle *handle)
175{ 132{
176 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 133 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
177 "Cleaning up\n"); 134 "Cleaning up\n");
178 if (NULL != handle->json_root)
179 json_decref (handle->json_root);
180 135
181 if (NULL != handle->name) 136 if (NULL != handle->gns_lookup)
182 GNUNET_free (handle->name);
183 if (NULL != handle->el)
184 {
185 GNUNET_IDENTITY_ego_lookup_cancel (handle->el);
186 handle->el = NULL;
187 }
188 if (NULL != handle->id_op)
189 { 137 {
190 GNUNET_IDENTITY_cancel (handle->id_op); 138 GNUNET_GNS_lookup_with_tld_cancel (handle->gns_lookup);
191 handle->id_op = NULL; 139 handle->gns_lookup = NULL;
192 }
193 if (NULL != handle->lookup_request)
194 {
195 GNUNET_GNS_lookup_cancel (handle->lookup_request);
196 handle->lookup_request = NULL;
197 }
198 if (NULL != handle->identity)
199 {
200 GNUNET_IDENTITY_disconnect (handle->identity);
201 handle->identity = NULL;
202 } 140 }
203 if (NULL != handle->gns) 141 if (NULL != handle->gns)
204 { 142 {
@@ -209,378 +147,190 @@ cleanup_handle (struct LookupHandle *handle)
209 if (NULL != handle->timeout_task) 147 if (NULL != handle->timeout_task)
210 { 148 {
211 GNUNET_SCHEDULER_cancel (handle->timeout_task); 149 GNUNET_SCHEDULER_cancel (handle->timeout_task);
150 handle->timeout_task = NULL;
212 } 151 }
152 if (NULL != handle->url)
153 GNUNET_free (handle->url);
154 if (NULL != handle->name)
155 GNUNET_free (handle->name);
156 if (NULL != handle->emsg)
157 GNUNET_free (handle->emsg);
158
213 GNUNET_free (handle); 159 GNUNET_free (handle);
214} 160}
215 161
216 162
217/** 163/**
218 * Task run on shutdown. Cleans up everything. 164 * Task run on errors. Reports an error and cleans up everything.
219 * 165 *
220 * @param cls unused 166 * @param cls the `struct RequestHandle`
221 * @param tc scheduler context
222 */ 167 */
223static void 168static void
224do_error (void *cls) 169do_error (void *cls)
225{ 170{
226 struct LookupHandle *handle = cls; 171 struct RequestHandle *handle = cls;
227 struct MHD_Response *resp; 172 struct MHD_Response *resp;
173 char *json_error;
228 174
229 resp = GNUNET_REST_create_response (NULL); 175 if (NULL == handle->emsg)
176 handle->emsg = GNUNET_strdup("Unknown Error");
177
178 GNUNET_asprintf (&json_error, "{\"error\": \"%s\"}", handle->emsg);
179
180 if (0 == handle->response_code)
181 handle->response_code = MHD_HTTP_OK;
182
183 resp = GNUNET_REST_create_response (json_error);
230 handle->proc (handle->proc_cls, resp, handle->response_code); 184 handle->proc (handle->proc_cls, resp, handle->response_code);
231 cleanup_handle (handle); 185 cleanup_handle (handle);
186 GNUNET_free(json_error);
232} 187}
233 188
234 189
235/** 190/**
236 * Create json representation of a GNSRECORD 191 * Iterator called on obtained result for a GNS lookup.
237 * 192 *
238 * @param rd the GNSRECORD_Data 193 * @param cls closure with the object
194 * @param was_gns #GNUNET_NO if name was not a GNS name
195 * @param rd_count number of records in @a rd
196 * @param rd the records in reply
239 */ 197 */
240static json_t * 198static void
241gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd) 199handle_gns_response (void *cls,
200 int was_gns,
201 uint32_t rd_count,
202 const struct GNUNET_GNSRECORD_Data *rd)
242{ 203{
243 const char *typename; 204 struct RequestHandle *handle = cls;
244 char *string_val; 205 struct MHD_Response *resp;
245 const char *exp_str; 206 json_t *result_array;
246 json_t *record_obj; 207 json_t *record_obj;
208 char *record_value;
209 char *result;
247 210
248 typename = GNUNET_GNSRECORD_number_to_typename (rd->record_type); 211 handle->gns_lookup = NULL;
249 string_val = GNUNET_GNSRECORD_value_to_string (rd->record_type,
250 rd->data,
251 rd->data_size);
252 212
253 if (NULL == string_val) 213 if (GNUNET_NO == was_gns)
254 { 214 {
255 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 215 handle->emsg = GNUNET_strdup("Name not found in GNS");
256 "Record of type %d malformed, skipping\n", 216 GNUNET_SCHEDULER_add_now (&do_error, handle);
257 (int) rd->record_type); 217 return;
258 return NULL;
259 }
260 record_obj = json_object ();
261 json_object_set_new (record_obj, "type", json_string (typename));
262 json_object_set_new (record_obj, "value", json_string (string_val));
263 GNUNET_free (string_val);
264
265 if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags)
266 {
267 struct GNUNET_TIME_Relative time_rel;
268 time_rel.rel_value_us = rd->expiration_time;
269 exp_str = GNUNET_STRINGS_relative_time_to_string (time_rel, 1);
270 } 218 }
271 else 219 if (0 == rd_count)
272 { 220 {
273 struct GNUNET_TIME_Absolute time_abs; 221 handle->emsg = GNUNET_strdup("No result found");
274 time_abs.abs_value_us = rd->expiration_time; 222 GNUNET_SCHEDULER_add_now (&do_error, handle);
275 exp_str = GNUNET_STRINGS_absolute_time_to_string (time_abs); 223 return;
276 } 224 }
277 json_object_set_new (record_obj, "expiration_time", json_string (exp_str));
278
279 json_object_set_new (record_obj, "expired",
280 json_boolean (GNUNET_YES == GNUNET_GNSRECORD_is_expired (rd)));
281 return record_obj;
282}
283
284/**
285 * Function called with the result of a GNS lookup.
286 *
287 * @param cls the 'const char *' name that was resolved
288 * @param rd_count number of records returned
289 * @param rd array of @a rd_count records with the results
290 */
291static void
292process_lookup_result (void *cls, uint32_t rd_count,
293 const struct GNUNET_GNSRECORD_Data *rd)
294{
295 struct LookupHandle *handle = cls;
296 struct MHD_Response *resp;
297 struct GNUNET_JSONAPI_Document *json_document;
298 struct GNUNET_JSONAPI_Resource *json_resource;
299 uint32_t i;
300 char *result;
301 json_t *result_array;
302 json_t *record_obj;
303 225
304 result_array = json_array(); 226 result_array = json_array();
305 json_document = GNUNET_JSONAPI_document_new (); 227 for (uint32_t i=0;i<rd_count;i++)
306 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_GNS_TYPEINFO, handle->name);
307 handle->lookup_request = NULL;
308 for (i=0; i<rd_count; i++)
309 { 228 {
310 if ( (rd[i].record_type != handle->type) && 229 if ((rd[i].record_type != handle->record_type) &&
311 (GNUNET_GNSRECORD_TYPE_ANY != handle->type) ) 230 (GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) )
231 {
312 continue; 232 continue;
313 record_obj = gnsrecord_to_json (&(rd[i])); 233 }
234
235 record_value = GNUNET_GNSRECORD_value_to_string (rd->record_type,
236 rd->data,
237 rd->data_size);
238 record_obj = json_string(record_value);
314 json_array_append (result_array, record_obj); 239 json_array_append (result_array, record_obj);
315 json_decref (record_obj); 240 json_decref (record_obj);
316 } 241 }
317 GNUNET_JSONAPI_resource_add_attr (json_resource, 242
318 GNUNET_REST_JSONAPI_GNS_RECORD, 243 result = json_dumps(result_array, 0);
319 result_array);
320 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
321 GNUNET_JSONAPI_document_serialize (json_document, &result);
322 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result); 244 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result);
323 json_decref (result_array);
324 GNUNET_JSONAPI_document_delete (json_document);
325 resp = GNUNET_REST_create_response (result); 245 resp = GNUNET_REST_create_response (result);
326 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 246 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
327 GNUNET_free (result); 247 GNUNET_free (result);
248 json_decref (result_array);
328 cleanup_handle (handle); 249 cleanup_handle (handle);
329} 250}
330 251
331 252
332/** 253/**
333 * Perform the actual resolution, starting with the zone 254 * Handle gns GET request
334 * identified by the given public key and the shorten zone.
335 * 255 *
336 * @param pkey public key to use for the zone, can be NULL 256 * @param con_handle the connection handle
257 * @param url the url
258 * @param cls the RequestHandle
337 */ 259 */
338static void 260void
339lookup_with_public_key (struct LookupHandle *handle) 261get_gns_cont (struct GNUNET_REST_RequestHandle *con_handle,
262 const char* url,
263 void *cls)
340{ 264{
341 if (UINT32_MAX == handle->type) 265 struct RequestHandle *handle = cls;
342 { 266 struct GNUNET_HashCode key;
343 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 267 int conversion_state;
344 _("Invalid typename specified, assuming `ANY'\n")); 268
345 handle->type = GNUNET_GNSRECORD_TYPE_ANY; 269 GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_NAME,
346 } 270 strlen (GNUNET_REST_PARAMETER_GNS_NAME),
347 if (NULL != handle->name) 271 &key);
348 { 272 if ( GNUNET_NO
349 handle->lookup_request = GNUNET_GNS_lookup (handle->gns, 273 == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map,
350 handle->name, 274 &key))
351 &handle->pkey,
352 handle->type,
353 handle->options,
354 &process_lookup_result,
355 handle);
356 }
357 else
358 { 275 {
276 handle->emsg = GNUNET_strdup("Parameter name is missing");
359 GNUNET_SCHEDULER_add_now (&do_error, handle); 277 GNUNET_SCHEDULER_add_now (&do_error, handle);
360 return; 278 return;
361 } 279 }
362} 280 handle->name = GNUNET_strdup(
363 281 GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,&key));
364 282
365/** 283 GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_RECORD_TYPE,
366 * Method called to with the ego we are to use for the lookup, 284 strlen (GNUNET_REST_PARAMETER_GNS_RECORD_TYPE),
367 * when the ego is determined by a name. 285 &key);
368 * 286 if ( GNUNET_NO
369 * @param cls closure (NULL, unused) 287 == GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map,
370 * @param ego ego handle, NULL if not found 288 &key))
371 */
372static void
373identity_zone_cb (void *cls,
374 const struct GNUNET_IDENTITY_Ego *ego)
375{
376 struct LookupHandle *handle = cls;
377
378 handle->el = NULL;
379 if (NULL == ego)
380 { 289 {
381 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 290 handle->emsg = GNUNET_strdup("Parameter record_type is missing");
382 _("Ego for not found, cannot perform lookup.\n"));
383 GNUNET_SCHEDULER_add_now (&do_error, handle); 291 GNUNET_SCHEDULER_add_now (&do_error, handle);
384 return; 292 return;
385 } 293 }
386 else 294 conversion_state = sscanf (
387 { 295 GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key),"%u",
388 GNUNET_IDENTITY_ego_get_public_key (ego, &handle->pkey); 296 &(handle->record_type));
389 lookup_with_public_key (handle);
390 }
391 json_decref(handle->json_root);
392}
393
394
395/**
396 * Method called to with the ego we are to use for the lookup,
397 * when the ego is the one for the default master zone.
398 *
399 * @param cls closure (NULL, unused)
400 * @param ego ego handle, NULL if not found
401 * @param ctx context for application to store data for this ego
402 * (during the lifetime of this process, initially NULL)
403 * @param name name assigned by the user for this ego,
404 * NULL if the user just deleted the ego and it
405 * must thus no longer be used
406 */
407static void
408identity_master_cb (void *cls,
409 struct GNUNET_IDENTITY_Ego *ego,
410 void **ctx,
411 const char *name)
412{
413 const char *dot;
414 struct LookupHandle *handle = cls;
415 297
416 handle->id_op = NULL; 298 if((EOF == conversion_state) || (0 == conversion_state))
417 if (NULL == ego)
418 { 299 {
419 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 300 handle->record_type = GNUNET_GNSRECORD_TYPE_ANY;
420 _("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?\n"));
421 GNUNET_SCHEDULER_add_now (&do_error, handle);
422 return;
423 } 301 }
424 GNUNET_IDENTITY_ego_get_public_key (ego,
425 &handle->pkey);
426 /* main name is our own master zone, do no look for that in the DHT */
427 handle->options = GNUNET_GNS_LO_LOCAL_MASTER;
428 /* if the name is of the form 'label.gnu', never go to the DHT */
429 dot = NULL;
430 if (NULL != handle->name)
431 dot = strchr (handle->name, '.');
432 if ( (NULL != dot) &&
433 (0 == strcasecmp (dot, ".gnu")) )
434 handle->options = GNUNET_GNS_LO_NO_DHT;
435 lookup_with_public_key (handle);
436}
437 302
438/**
439 * Parse REST uri for name and record type
440 *
441 * @param url Url to parse
442 * @param handle lookup handle to populate
443 * @return GNUNET_SYSERR on error
444 */
445static int
446parse_url (const char *url, struct LookupHandle *handle)
447{
448 char *name;
449 char tmp_url[strlen(url)+1];
450 char *tok;
451
452 strcpy (tmp_url, url);
453 tok = strtok ((char*)tmp_url, "/");
454 if (NULL == tok)
455 return GNUNET_SYSERR;
456 name = strtok (NULL, "/");
457 if (NULL == name)
458 return GNUNET_SYSERR;
459 GNUNET_asprintf (&handle->name,
460 "%s",
461 name);
462 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
463 "Got name: %s\n", handle->name);
464 return GNUNET_OK;
465}
466
467
468static void
469get_gns_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
470 const char* url,
471 void *cls)
472{
473 struct LookupHandle *handle = cls;
474 struct GNUNET_HashCode key;
475
476 //parse name and type from url
477 if (GNUNET_OK != parse_url (url, handle))
478 {
479 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing url...\n");
480 GNUNET_SCHEDULER_add_now (&do_error, handle);
481 return;
482 }
483 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
484 "Connecting...\n");
485 handle->gns = GNUNET_GNS_connect (cfg); 303 handle->gns = GNUNET_GNS_connect (cfg);
486 handle->identity = GNUNET_IDENTITY_connect (cfg, NULL, NULL);
487 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
488 &do_error, handle);
489 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
490 "Connected\n");
491 if (NULL == handle->gns) 304 if (NULL == handle->gns)
492 { 305 {
493 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 306 handle->emsg = GNUNET_strdup ("GNS not available");
494 "Connecting to GNS failed\n");
495 GNUNET_SCHEDULER_add_now (&do_error, handle); 307 GNUNET_SCHEDULER_add_now (&do_error, handle);
496 return; 308 return;
497 } 309 }
498 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_OPTIONS, 310
499 strlen (GNUNET_REST_JSONAPI_GNS_OPTIONS), 311 handle->gns_lookup = GNUNET_GNS_lookup_with_tld (handle->gns,
500 &key); 312 handle->name,
501 handle->options = GNUNET_GNS_LO_DEFAULT; 313 handle->record_type,
502 if ( GNUNET_YES == 314 GNUNET_NO,
503 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map, 315 &handle_gns_response,
504 &key) ) 316 handle);
505 { 317
506 handle->options = GNUNET_GNS_LO_DEFAULT;//TODO(char*) GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, 318 if (NULL == handle->gns_lookup)
507 //&key);
508 }
509 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE,
510 strlen (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE),
511 &key);
512 if ( GNUNET_YES ==
513 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
514 &key) )
515 {
516 handle->type = GNUNET_GNSRECORD_typename_to_number
517 (GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
518 &key));
519 }
520 else
521 handle->type = GNUNET_GNSRECORD_TYPE_ANY;
522
523 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_PKEY,
524 strlen (GNUNET_REST_JSONAPI_GNS_PKEY),
525 &key);
526 if ( GNUNET_YES ==
527 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
528 &key) )
529 {
530 handle->pkey_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
531 &key);
532 GNUNET_assert (NULL != handle->pkey_str);
533 if (GNUNET_OK !=
534 GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->pkey_str,
535 strlen(handle->pkey_str),
536 &(handle->pkey)))
537 {
538 GNUNET_SCHEDULER_add_now (&do_error, handle);
539 return;
540 }
541 lookup_with_public_key (handle);
542 return;
543 }
544 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_EGO,
545 strlen (GNUNET_REST_JSONAPI_GNS_EGO),
546 &key);
547 if ( GNUNET_YES ==
548 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
549 &key) )
550 { 319 {
551 handle->ego_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, 320 handle->emsg = GNUNET_strdup("GNS lookup failed");
552 &key); 321 GNUNET_SCHEDULER_add_now (&do_error, handle);
553 handle->el = GNUNET_IDENTITY_ego_lookup (cfg,
554 handle->ego_str,
555 &identity_zone_cb,
556 handle);
557 return; 322 return;
558 } 323 }
559 if ( (NULL != handle->name) &&
560 (strlen (handle->name) > 4) &&
561 (0 == strcmp (".zkey",
562 &handle->name[strlen (handle->name) - 4])) )
563 {
564 GNUNET_CRYPTO_ecdsa_key_get_public
565 (GNUNET_CRYPTO_ecdsa_key_get_anonymous (),
566 &(handle->pkey));
567 lookup_with_public_key (handle);
568 }
569 else
570 {
571 GNUNET_break (NULL == handle->id_op);
572 handle->id_op = GNUNET_IDENTITY_get (handle->identity,
573 "gns-master",
574 &identity_master_cb,
575 handle);
576 GNUNET_assert (NULL != handle->id_op);
577 }
578} 324}
579 325
326
327
580/** 328/**
581 * Handle rest request 329 * Respond to OPTIONS request
582 * 330 *
583 * @param handle the lookup handle 331 * @param con_handle the connection handle
332 * @param url the url
333 * @param cls the RequestHandle
584 */ 334 */
585static void 335static void
586options_cont (struct GNUNET_REST_RequestHandle *con_handle, 336options_cont (struct GNUNET_REST_RequestHandle *con_handle,
@@ -588,53 +338,38 @@ options_cont (struct GNUNET_REST_RequestHandle *con_handle,
588 void *cls) 338 void *cls)
589{ 339{
590 struct MHD_Response *resp; 340 struct MHD_Response *resp;
591 struct LookupHandle *handle = cls; 341 struct RequestHandle *handle = cls;
592 342
593 //For GNS, independent of path return all options 343 //independent of path return all options
594 resp = GNUNET_REST_create_response (NULL); 344 resp = GNUNET_REST_create_response (NULL);
595 MHD_add_response_header (resp, 345 MHD_add_response_header (resp,
596 "Access-Control-Allow-Methods", 346 "Access-Control-Allow-Methods",
597 MHD_HTTP_METHOD_GET); 347 allow_methods);
598 handle->proc (handle->proc_cls, 348 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
599 resp,
600 MHD_HTTP_OK);
601 cleanup_handle (handle); 349 cleanup_handle (handle);
350 return;
602} 351}
603 352
604 353
605/** 354/**
606 * Function processing the REST call 355 * Handle rest request
607 * 356 *
608 * @param method HTTP method 357 * @param handle the request handle
609 * @param url URL of the HTTP request
610 * @param data body of the HTTP request (optional)
611 * @param data_size length of the body
612 * @param proc callback function for the result
613 * @param proc_cls closure for @a proc
614 * @return #GNUNET_OK if request accepted
615 */ 358 */
616static void 359static void
617rest_gns_process_request (struct GNUNET_REST_RequestHandle *conndata_handle, 360init_cont (struct RequestHandle *handle)
618 GNUNET_REST_ResultProcessor proc,
619 void *proc_cls)
620{ 361{
362 struct GNUNET_REST_RequestHandlerError err;
621 static const struct GNUNET_REST_RequestHandler handlers[] = { 363 static const struct GNUNET_REST_RequestHandler handlers[] = {
622 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_GNS, &get_gns_cont}, 364 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_GNS, &get_gns_cont},
623 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_GNS, &options_cont}, 365 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_GNS, &options_cont},
624 GNUNET_REST_HANDLER_END 366 GNUNET_REST_HANDLER_END
625 }; 367 };
626 struct LookupHandle *handle = GNUNET_new (struct LookupHandle);
627 struct GNUNET_REST_RequestHandlerError err;
628 368
629 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; 369 if (GNUNET_NO == GNUNET_REST_handle_request (handle->rest_handle,
630 handle->proc_cls = proc_cls; 370 handlers,
631 handle->proc = proc; 371 &err,
632 handle->rest_handle = conndata_handle; 372 handle))
633
634 if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle,
635 handlers,
636 &err,
637 handle))
638 { 373 {
639 handle->response_code = err.error_code; 374 handle->response_code = err.error_code;
640 GNUNET_SCHEDULER_add_now (&do_error, handle); 375 GNUNET_SCHEDULER_add_now (&do_error, handle);
@@ -643,18 +378,58 @@ rest_gns_process_request (struct GNUNET_REST_RequestHandle *conndata_handle,
643 378
644 379
645/** 380/**
381 * Function processing the REST call
382 *
383 * @param method HTTP method
384 * @param url URL of the HTTP request
385 * @param data body of the HTTP request (optional)
386 * @param data_size length of the body
387 * @param proc callback function for the result
388 * @param proc_cls closure for callback function
389 * @return GNUNET_OK if request accepted
390 */
391static void
392rest_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
393 GNUNET_REST_ResultProcessor proc,
394 void *proc_cls)
395{
396 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
397
398 handle->response_code = 0;
399 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
400 handle->proc_cls = proc_cls;
401 handle->proc = proc;
402 handle->rest_handle = rest_handle;
403
404 handle->url = GNUNET_strdup (rest_handle->url);
405 if (handle->url[strlen (handle->url)-1] == '/')
406 handle->url[strlen (handle->url)-1] = '\0';
407 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
408
409 init_cont(handle);
410
411 handle->timeout_task =
412 GNUNET_SCHEDULER_add_delayed (handle->timeout,
413 &do_error,
414 handle);
415
416 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
417}
418
419
420/**
646 * Entry point for the plugin. 421 * Entry point for the plugin.
647 * 422 *
648 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*" 423 * @param cls Config info
649 * @return NULL on error, otherwise the plugin context 424 * @return NULL on error, otherwise the plugin context
650 */ 425 */
651void * 426void *
652libgnunet_plugin_rest_gns_init (void *cls) 427libgnunet_plugin_rest_gns_init (void *cls)
653{ 428{
654 static struct Plugin plugin; 429 static struct Plugin plugin;
655 cfg = cls;
656 struct GNUNET_REST_Plugin *api; 430 struct GNUNET_REST_Plugin *api;
657 431
432 cfg = cls;
658 if (NULL != plugin.cfg) 433 if (NULL != plugin.cfg)
659 return NULL; /* can only initialize once! */ 434 return NULL; /* can only initialize once! */
660 memset (&plugin, 0, sizeof (struct Plugin)); 435 memset (&plugin, 0, sizeof (struct Plugin));
@@ -662,9 +437,17 @@ libgnunet_plugin_rest_gns_init (void *cls)
662 api = GNUNET_new (struct GNUNET_REST_Plugin); 437 api = GNUNET_new (struct GNUNET_REST_Plugin);
663 api->cls = &plugin; 438 api->cls = &plugin;
664 api->name = GNUNET_REST_API_NS_GNS; 439 api->name = GNUNET_REST_API_NS_GNS;
665 api->process_request = &rest_gns_process_request; 440 api->process_request = &rest_process_request;
666 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 441 GNUNET_asprintf (&allow_methods,
667 _("GNS REST API initialized\n")); 442 "%s, %s, %s, %s, %s",
443 MHD_HTTP_METHOD_GET,
444 MHD_HTTP_METHOD_POST,
445 MHD_HTTP_METHOD_PUT,
446 MHD_HTTP_METHOD_DELETE,
447 MHD_HTTP_METHOD_OPTIONS);
448
449 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
450 _("Gns REST API initialized\n"));
668 return api; 451 return api;
669} 452}
670 453
@@ -680,12 +463,14 @@ libgnunet_plugin_rest_gns_done (void *cls)
680{ 463{
681 struct GNUNET_REST_Plugin *api = cls; 464 struct GNUNET_REST_Plugin *api = cls;
682 struct Plugin *plugin = api->cls; 465 struct Plugin *plugin = api->cls;
683
684 plugin->cfg = NULL; 466 plugin->cfg = NULL;
467
468 GNUNET_free_non_null (allow_methods);
685 GNUNET_free (api); 469 GNUNET_free (api);
686 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 470 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
687 "GNS REST plugin is finished\n"); 471 "Gns REST plugin is finished\n");
688 return NULL; 472 return NULL;
689} 473}
690 474
691/* end of plugin_rest_gns.c */ 475/* end of plugin_rest_gns.c */
476
diff --git a/src/gns/plugin_rest_gns2.c b/src/gns/plugin_rest_gns2.c
new file mode 100644
index 000000000..82d62744c
--- /dev/null
+++ b/src/gns/plugin_rest_gns2.c
@@ -0,0 +1,717 @@
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 gns/plugin_rest_gns.c
22 * @brief GNUnet GNS REST plugin
23 *
24 */
25
26#include "platform.h"
27#include "gnunet_rest_plugin.h"
28#include <gnunet_dnsparser_lib.h>
29#include <gnunet_identity_service.h>
30#include <gnunet_gnsrecord_lib.h>
31#include <gnunet_namestore_service.h>
32#include <gnunet_gns_service.h>
33#include <gnunet_rest_lib.h>
34#include <gnunet_jsonapi_lib.h>
35#include <gnunet_jsonapi_util.h>
36#include <jansson.h>
37
38#define GNUNET_REST_API_NS_GNS "/gns"
39
40#define GNUNET_REST_JSONAPI_GNS_RECORD_TYPE "record_type"
41
42#define GNUNET_REST_PARAMETER_GNS_NAME "name"
43
44#define GNUNET_REST_JSONAPI_GNS_TYPEINFO "gns_name"
45
46#define GNUNET_REST_JSONAPI_GNS_RECORD "records"
47
48#define GNUNET_REST_JSONAPI_GNS_EGO "ego"
49
50#define GNUNET_REST_JSONAPI_GNS_PKEY "pkey"
51
52#define GNUNET_REST_JSONAPI_GNS_OPTIONS "options"
53
54/**
55 * @brief struct returned by the initialization function of the plugin
56 */
57struct Plugin
58{
59 const struct GNUNET_CONFIGURATION_Handle *cfg;
60};
61
62const struct GNUNET_CONFIGURATION_Handle *cfg;
63
64struct LookupHandle
65{
66 /**
67 * Handle to GNS service.
68 */
69 struct GNUNET_GNS_Handle *gns;
70
71 /**
72 * Desired timeout for the lookup (default is no timeout).
73 */
74 struct GNUNET_TIME_Relative timeout;
75
76 /**
77 * Handle to lookup request
78 */
79 struct GNUNET_GNS_LookupRequest *lookup_request;
80
81 /**
82 * Handle to rest request
83 */
84 struct GNUNET_REST_RequestHandle *rest_handle;
85
86 /**
87 * Lookup an ego with the identity service.
88 */
89 struct GNUNET_IDENTITY_EgoLookup *el;
90
91 /**
92 * Handle for identity service.
93 */
94 struct GNUNET_IDENTITY_Handle *identity;
95
96 /**
97 * Active operation on identity service.
98 */
99 struct GNUNET_IDENTITY_Operation *id_op;
100
101 /**
102 * ID of a task associated with the resolution process.
103 */
104 struct GNUNET_SCHEDULER_Task * timeout_task;
105
106 /**
107 * The root of the received JSON or NULL
108 */
109 json_t *json_root;
110
111 /**
112 * The plugin result processor
113 */
114 GNUNET_REST_ResultProcessor proc;
115
116 /**
117 * The closure of the result processor
118 */
119 void *proc_cls;
120
121 /**
122 * The name to look up
123 */
124 char *name;
125
126 /**
127 * The ego to use
128 * In string representation from JSON
129 */
130 const char *ego_str;
131
132 /**
133 * The Pkey to use
134 * In string representation from JSON
135 */
136 const char *pkey_str;
137
138 /**
139 * The record type
140 */
141 int type;
142
143 /**
144 * The public key of to use for lookup
145 */
146 struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
147
148 /**
149 * The public key to use for lookup
150 */
151 struct GNUNET_CRYPTO_EcdsaPublicKey pkeym;
152
153 /**
154 * The resolver options
155 */
156 enum GNUNET_GNS_LocalOptions options;
157
158 /**
159 * the shorten key
160 */
161 struct GNUNET_CRYPTO_EcdsaPrivateKey shorten_key;
162
163 /**
164 * HTTP response code
165 */
166 int response_code;
167
168 /**
169 * HTTP response code
170 */
171 char* emsg;
172
173};
174
175
176/**
177 * Cleanup lookup handle.
178 *
179 * @param handle Handle to clean up
180 */
181static void
182cleanup_handle (struct LookupHandle *handle)
183{
184 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
185 "Cleaning up\n");
186 if (NULL != handle->json_root)
187 json_decref (handle->json_root);
188
189 if (NULL != handle->name)
190 GNUNET_free (handle->name);
191 if (NULL != handle->emsg)
192 GNUNET_free (handle->emsg);
193 if (NULL != handle->el)
194 {
195 GNUNET_IDENTITY_ego_lookup_cancel (handle->el);
196 handle->el = NULL;
197 }
198 if (NULL != handle->id_op)
199 {
200 GNUNET_IDENTITY_cancel (handle->id_op);
201 handle->id_op = NULL;
202 }
203 if (NULL != handle->lookup_request)
204 {
205 GNUNET_GNS_lookup_cancel (handle->lookup_request);
206 handle->lookup_request = NULL;
207 }
208 if (NULL != handle->identity)
209 {
210 GNUNET_IDENTITY_disconnect (handle->identity);
211 handle->identity = NULL;
212 }
213 if (NULL != handle->gns)
214 {
215 GNUNET_GNS_disconnect (handle->gns);
216 handle->gns = NULL;
217 }
218
219 if (NULL != handle->timeout_task)
220 {
221 GNUNET_SCHEDULER_cancel (handle->timeout_task);
222 }
223 GNUNET_free (handle);
224}
225
226
227/**
228 * Task run on shutdown. Cleans up everything.
229 *
230 * @param cls unused
231 * @param tc scheduler context
232 */
233static void
234do_error (void *cls)
235{
236 struct LookupHandle *handle = cls;
237 struct MHD_Response *resp;
238 char *json_error;
239
240 if (NULL == handle->emsg)
241 handle->emsg = GNUNET_strdup("Unknown Error");
242
243 GNUNET_asprintf (&json_error, "{\"error\": \"%s\"}", handle->emsg);
244 handle->response_code = MHD_HTTP_OK;
245
246 resp = GNUNET_REST_create_response (json_error);
247 handle->proc (handle->proc_cls, resp, handle->response_code);
248 cleanup_handle (handle);
249 GNUNET_free(json_error);
250}
251
252
253/**
254 * Create json representation of a GNSRECORD
255 *
256 * @param rd the GNSRECORD_Data
257 */
258static json_t *
259gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd)
260{
261 const char *typename;
262 char *string_val;
263 const char *exp_str;
264 json_t *record_obj;
265
266 typename = GNUNET_GNSRECORD_number_to_typename (rd->record_type);
267 string_val = GNUNET_GNSRECORD_value_to_string (rd->record_type,
268 rd->data,
269 rd->data_size);
270
271 if (NULL == string_val)
272 {
273 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
274 "Record of type %d malformed, skipping\n",
275 (int) rd->record_type);
276 return NULL;
277 }
278 record_obj = json_object ();
279 json_object_set_new (record_obj, "type", json_string (typename));
280 json_object_set_new (record_obj, "value", json_string (string_val));
281 GNUNET_free (string_val);
282
283 if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags)
284 {
285 struct GNUNET_TIME_Relative time_rel;
286 time_rel.rel_value_us = rd->expiration_time;
287 exp_str = GNUNET_STRINGS_relative_time_to_string (time_rel, 1);
288 }
289 else
290 {
291 struct GNUNET_TIME_Absolute time_abs;
292 time_abs.abs_value_us = rd->expiration_time;
293 exp_str = GNUNET_STRINGS_absolute_time_to_string (time_abs);
294 }
295 json_object_set_new (record_obj, "expiration_time", json_string (exp_str));
296
297 json_object_set_new (record_obj, "expired",
298 json_boolean (GNUNET_YES == GNUNET_GNSRECORD_is_expired (rd)));
299 return record_obj;
300}
301
302/**
303 * Function called with the result of a GNS lookup.
304 *
305 * @param cls the 'const char *' name that was resolved
306 * @param rd_count number of records returned
307 * @param rd array of @a rd_count records with the results
308 */
309static void
310process_lookup_result (void *cls, uint32_t rd_count,
311 const struct GNUNET_GNSRECORD_Data *rd)
312{
313 struct LookupHandle *handle = cls;
314 struct MHD_Response *resp;
315 uint32_t i;
316 char *result;
317 json_t *result_array;
318 json_t *record_obj;
319
320 result_array = json_array();
321 handle->lookup_request = NULL;
322 for (i=0; i<rd_count; i++)
323 {
324 if ( (rd[i].record_type != handle->type) &&
325 (GNUNET_GNSRECORD_TYPE_ANY != handle->type) )
326 continue;
327 record_obj = gnsrecord_to_json (&(rd[i]));
328 json_array_append (result_array, record_obj);
329 json_decref (record_obj);
330 }
331 result = json_dumps(result_array, 0);
332 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result);
333 resp = GNUNET_REST_create_response (result);
334 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
335 GNUNET_free (result);
336 json_decref (result_array);
337 cleanup_handle (handle);
338}
339
340
341/**
342 * Perform the actual resolution, starting with the zone
343 * identified by the given public key and the shorten zone.
344 *
345 * @param pkey public key to use for the zone, can be NULL
346 */
347static void
348lookup_with_public_key (struct LookupHandle *handle)
349{
350 if (UINT32_MAX == handle->type)
351 {
352 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
353 _("Invalid typename specified, assuming `ANY'\n"));
354 handle->type = GNUNET_GNSRECORD_TYPE_ANY;
355 }
356 if (NULL != handle->name)
357 {
358 handle->lookup_request = GNUNET_GNS_lookup (handle->gns,
359 handle->name,
360 &handle->pkey,
361 handle->type,
362 handle->options,
363 &process_lookup_result,
364 handle);
365 }
366 else
367 {
368 handle->emsg = GNUNET_strdup("Parameter name is missing");
369 GNUNET_SCHEDULER_add_now (&do_error, handle);
370 return;
371 }
372}
373
374
375/**
376 * Method called to with the ego we are to use for the lookup,
377 * when the ego is determined by a name.
378 *
379 * @param cls closure (NULL, unused)
380 * @param ego ego handle, NULL if not found
381 */
382static void
383identity_zone_cb (void *cls,
384 const struct GNUNET_IDENTITY_Ego *ego)
385{
386 struct LookupHandle *handle = cls;
387
388 handle->el = NULL;
389 if (NULL == ego)
390 {
391 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
392 _("Ego for not found, cannot perform lookup.\n"));
393 handle->emsg = GNUNET_strdup ("Ego for not found, cannot perform lookup.");
394 GNUNET_SCHEDULER_add_now (&do_error, handle);
395 return;
396 }
397 else
398 {
399 GNUNET_IDENTITY_ego_get_public_key (ego, &handle->pkey);
400 lookup_with_public_key (handle);
401 }
402 json_decref(handle->json_root);
403}
404
405
406/**
407 * Method called to with the ego we are to use for the lookup,
408 * when the ego is the one for the default master zone.
409 *
410 * @param cls closure (NULL, unused)
411 * @param ego ego handle, NULL if not found
412 * @param ctx context for application to store data for this ego
413 * (during the lifetime of this process, initially NULL)
414 * @param name name assigned by the user for this ego,
415 * NULL if the user just deleted the ego and it
416 * must thus no longer be used
417 */
418static void
419identity_master_cb (void *cls,
420 struct GNUNET_IDENTITY_Ego *ego,
421 void **ctx,
422 const char *name)
423{
424 const char *dot;
425 struct LookupHandle *handle = cls;
426
427 handle->id_op = NULL;
428 if (NULL == ego)
429 {
430 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
431 _("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?\n"));
432 handle->emsg = GNUNET_strdup("Ego for `gns-master' not found, cannot perform lookup. Did you run gnunet-gns-import.sh?");
433 GNUNET_SCHEDULER_add_now (&do_error, handle);
434 return;
435 }
436 GNUNET_IDENTITY_ego_get_public_key (ego,
437 &handle->pkey);
438 /* main name is our own master zone, do no look for that in the DHT */
439 handle->options = GNUNET_GNS_LO_LOCAL_MASTER;
440 /* if the name is of the form 'label.gnu', never go to the DHT */
441 dot = NULL;
442 if (NULL != handle->name)
443 dot = strchr (handle->name, '.');
444 if ( (NULL != dot) &&
445 (0 == strcasecmp (dot, ".gnu")) )
446 handle->options = GNUNET_GNS_LO_NO_DHT;
447 lookup_with_public_key (handle);
448}
449
450/**
451 * Handle get request
452 *
453 * @param handle the lookup handle
454 */
455static void
456get_gns_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
457 const char* url,
458 void *cls)
459{
460 struct LookupHandle *handle = cls;
461 struct GNUNET_HashCode key;
462 long int enum_test;
463 char *temp_val;
464
465 //check for /gns otherwise 404
466 if (strlen (GNUNET_REST_API_NS_GNS) > strlen (url))
467 {
468 handle->emsg = GNUNET_strdup("Wrong URL");
469 GNUNET_SCHEDULER_add_now (&do_error, handle);
470 return;
471 }
472
473 //connect to gns
474 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
475 handle->gns = GNUNET_GNS_connect (cfg);
476 handle->identity = GNUNET_IDENTITY_connect (cfg, NULL, NULL);
477 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
478 &do_error, handle);
479 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
480 if (NULL == handle->gns)
481 {
482 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Connecting to GNS failed\n");
483 handle->emsg = GNUNET_strdup("Connecting to GNS failed");
484 GNUNET_SCHEDULER_add_now (&do_error, handle);
485 return;
486 }
487
488 //check parameter name -> BAD_REQUEST
489 GNUNET_CRYPTO_hash (GNUNET_REST_PARAMETER_GNS_NAME,
490 strlen (GNUNET_REST_PARAMETER_GNS_NAME),
491 &key);
492 if ( GNUNET_NO
493 == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
494 &key))
495 {
496 handle->emsg = GNUNET_strdup("Parameter name is missing");
497 GNUNET_SCHEDULER_add_now (&do_error, handle);
498 return;
499 }
500 handle->name = GNUNET_strdup(GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
501 &key));
502
503 //check parameter record_type, optional
504 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE,
505 strlen (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE),
506 &key);
507 if ( GNUNET_YES ==
508 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
509 &key) )
510 {
511 handle->type = GNUNET_GNSRECORD_typename_to_number(
512 GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
513 &key));
514 }
515 else
516 {
517 handle->type = GNUNET_GNSRECORD_TYPE_ANY;
518 }
519
520 //check parameter options, optional
521 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_OPTIONS,
522 strlen (GNUNET_REST_JSONAPI_GNS_OPTIONS),
523 &key);
524 handle->options = GNUNET_GNS_LO_DEFAULT;
525 if ( GNUNET_YES
526 == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
527 &key))
528 {
529 temp_val = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map, &key);
530 if (1 < strlen(temp_val))
531 {
532 handle->options = GNUNET_GNS_LO_DEFAULT;
533 }
534 else
535 {
536 //atoi because no valid conversion is default local option
537 enum_test = atoi(temp_val);
538 if (2 < enum_test)
539 handle->options = GNUNET_GNS_LO_DEFAULT;
540 else
541 handle->options = enum_test;
542 }
543 }
544 else
545 handle->options = GNUNET_GNS_LO_DEFAULT;
546
547 //check parameter pkey, shortcut to lookup
548 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_PKEY,
549 strlen (GNUNET_REST_JSONAPI_GNS_PKEY),
550 &key);
551 if ( GNUNET_YES
552 == GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
553 &key))
554 {
555 handle->pkey_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
556 &key);
557 GNUNET_assert(NULL != handle->pkey_str);
558 if (GNUNET_OK
559 != GNUNET_CRYPTO_ecdsa_public_key_from_string (
560 handle->pkey_str, strlen (handle->pkey_str), &(handle->pkey)))
561 {
562 handle->emsg = GNUNET_strdup("Parameter pkey has a wrong format");
563 GNUNET_SCHEDULER_add_now (&do_error, handle);
564 return;
565 }
566 lookup_with_public_key (handle);
567 return;
568 }
569
570 //check parameter ego, lookup public key of ego
571 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_EGO,
572 strlen (GNUNET_REST_JSONAPI_GNS_EGO),
573 &key);
574 if ( GNUNET_YES ==
575 GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
576 &key) )
577 {
578 handle->ego_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
579 &key);
580 handle->el = GNUNET_IDENTITY_ego_lookup (cfg,
581 handle->ego_str,
582 &identity_zone_cb,
583 handle);
584 return;
585 }
586
587 //if name ends with .zkey then get public key
588 if ( (NULL != handle->name) &&
589 (strlen (handle->name) > 4) &&
590 (0 == strcmp (".zkey",
591 &handle->name[strlen (handle->name) - 4])) )
592 {
593 GNUNET_CRYPTO_ecdsa_key_get_public( GNUNET_CRYPTO_ecdsa_key_get_anonymous (),
594 &(handle->pkey));
595 lookup_with_public_key (handle);
596 }
597 else //else use gns-master identity
598 {
599 handle->id_op = GNUNET_IDENTITY_get (handle->identity,
600 "gns-master",
601 &identity_master_cb,
602 handle);
603 }
604}
605
606/**
607 * Handle rest request
608 *
609 * @param handle the lookup handle
610 */
611static void
612options_cont (struct GNUNET_REST_RequestHandle *con_handle,
613 const char* url,
614 void *cls)
615{
616 struct MHD_Response *resp;
617 struct LookupHandle *handle = cls;
618
619 //For GNS, independent of path return all options
620 resp = GNUNET_REST_create_response (NULL);
621 MHD_add_response_header (resp,
622 "Access-Control-Allow-Methods",
623 MHD_HTTP_METHOD_GET);
624 handle->proc (handle->proc_cls,
625 resp,
626 MHD_HTTP_OK);
627 cleanup_handle (handle);
628}
629
630
631/**
632 * Function processing the REST call
633 *
634 * @param method HTTP method
635 * @param url URL of the HTTP request
636 * @param data body of the HTTP request (optional)
637 * @param data_size length of the body
638 * @param proc callback function for the result
639 * @param proc_cls closure for @a proc
640 * @return #GNUNET_OK if request accepted
641 */
642static void
643rest_gns_process_request (struct GNUNET_REST_RequestHandle *conndata_handle,
644 GNUNET_REST_ResultProcessor proc,
645 void *proc_cls)
646{
647 static const struct GNUNET_REST_RequestHandler handlers[] = {
648 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_GNS, &get_gns_cont},
649 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_GNS, &options_cont},
650 GNUNET_REST_HANDLER_END
651 };
652 struct LookupHandle *handle = GNUNET_new (struct LookupHandle);
653 struct GNUNET_REST_RequestHandlerError err;
654
655 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
656 handle->proc_cls = proc_cls;
657 handle->proc = proc;
658 handle->rest_handle = conndata_handle;
659
660 if (GNUNET_NO == GNUNET_REST_handle_request (conndata_handle,
661 handlers,
662 &err,
663 handle))
664 {
665 handle->response_code = err.error_code;
666 GNUNET_SCHEDULER_add_now (&do_error, handle);
667 }
668}
669
670
671/**
672 * Entry point for the plugin.
673 *
674 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
675 * @return NULL on error, otherwise the plugin context
676 */
677void *
678libgnunet_plugin_rest_gns_init (void *cls)
679{
680 static struct Plugin plugin;
681 cfg = cls;
682 struct GNUNET_REST_Plugin *api;
683
684 if (NULL != plugin.cfg)
685 return NULL; /* can only initialize once! */
686 memset (&plugin, 0, sizeof (struct Plugin));
687 plugin.cfg = cfg;
688 api = GNUNET_new (struct GNUNET_REST_Plugin);
689 api->cls = &plugin;
690 api->name = GNUNET_REST_API_NS_GNS;
691 api->process_request = &rest_gns_process_request;
692 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
693 _("GNS REST API initialized\n"));
694 return api;
695}
696
697
698/**
699 * Exit point from the plugin.
700 *
701 * @param cls the plugin context (as returned by "init")
702 * @return always NULL
703 */
704void *
705libgnunet_plugin_rest_gns_done (void *cls)
706{
707 struct GNUNET_REST_Plugin *api = cls;
708 struct Plugin *plugin = api->cls;
709
710 plugin->cfg = NULL;
711 GNUNET_free (api);
712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
713 "GNS REST plugin is finished\n");
714 return NULL;
715}
716
717/* end of plugin_rest_gns.c */
diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c
index 52685c52e..8d525b950 100644
--- a/src/identity/plugin_rest_identity.c
+++ b/src/identity/plugin_rest_identity.c
@@ -1,84 +1,63 @@
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
6 under the terms of the GNU Affero General Public License as published 6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation, either version 3 of the License, 7 by the Free Software Foundation; either version 3, or (at your
8 or (at your option) any later version. 8 option) any later version.
9 9
10 GNUnet is distributed in the hope that it will be useful, but 10 GNUnet is distributed in the hope that it will be useful, but
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 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 General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. 16 along with GNUnet; see the file COPYING. If not, write to the
17 */ 17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
18/** 20/**
19 * @author Martin Schanzenbach 21 * @author Martin Schanzenbach
22 * @author Philippe Buschmann
20 * @file identity/plugin_rest_identity.c 23 * @file identity/plugin_rest_identity.c
21 * @brief GNUnet Namestore REST plugin 24 * @brief GNUnet Identity REST plugin
22 *
23 */ 25 */
24 26
25#include "platform.h" 27#include "platform.h"
26#include "gnunet_rest_plugin.h" 28#include "gnunet_rest_plugin.h"
27#include "gnunet_identity_service.h" 29#include "gnunet_identity_service.h"
28#include "gnunet_rest_lib.h" 30#include "gnunet_rest_lib.h"
29#include "gnunet_jsonapi_lib.h"
30#include "gnunet_jsonapi_util.h"
31#include "microhttpd.h" 31#include "microhttpd.h"
32#include <jansson.h> 32#include <jansson.h>
33#include "gnunet_signatures.h"
34 33
35/**
36 * REST root namespace
37 */
38#define GNUNET_REST_API_NS_IDENTITY "/identity" 34#define GNUNET_REST_API_NS_IDENTITY "/identity"
39 35
40/** 36/**
41 * State while collecting all egos 37 * Parameter names
42 */ 38 */
43#define ID_REST_STATE_INIT 0 39#define GNUNET_REST_PARAM_PUBKEY "pubkey"
44 40#define GNUNET_REST_PARAM_SUBSYSTEM "subsystem"
45/** 41#define GNUNET_REST_PARAM_NAME "name"
46 * Done collecting egos 42#define GNUNET_REST_PARAM_NEWNAME "newname"
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 */
69#define GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM "subsystem"
70
71 43
72/** 44/**
73 * Error messages 45 * Error messages
74 */ 46 */
47#define GNUNET_REST_ERROR_UNKNOWN "Unknown Error"
75#define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid" 48#define GNUNET_REST_ERROR_RESOURCE_INVALID "Resource location invalid"
76#define GNUNET_REST_ERROR_NO_DATA "No data" 49#define GNUNET_REST_ERROR_NO_DATA "No data"
50#define GNUNET_REST_ERROR_DATA_INVALID "Data invalid"
51
52/**
53 * State while collecting all egos
54 */
55#define ID_REST_STATE_INIT 0
77 56
78/** 57/**
79 * GNUid token lifetime 58 * Done collecting egos
80 */ 59 */
81#define GNUNET_GNUID_TOKEN_EXPIRATION_MICROSECONDS 300000000 60#define ID_REST_STATE_POST_INIT 1
82 61
83/** 62/**
84 * The configuration handle 63 * The configuration handle
@@ -129,28 +108,37 @@ struct EgoEntry
129 struct GNUNET_IDENTITY_Ego *ego; 108 struct GNUNET_IDENTITY_Ego *ego;
130}; 109};
131 110
132
133struct RequestHandle 111struct RequestHandle
134{ 112{
135 /** 113 /**
136 * Ego list 114 * The data from the REST request
137 */ 115 */
138 struct EgoEntry *ego_head; 116 const char* data;
139 117
140 /** 118 /**
141 * Ego list 119 * The name to look up
142 */ 120 */
143 struct EgoEntry *ego_tail; 121 char *name;
144 122
145 /** 123 /**
146 * Handle to the rest connection 124 * the length of the REST data
147 */ 125 */
148 struct GNUNET_REST_RequestHandle *conndata_handle; 126 size_t data_size;
149 127
150 /** 128 /**
151 * response code 129 * Requested Subsystem
152 */ 130 */
153 int response_code; 131 char *subsystem;
132
133 /**
134 * Ego list
135 */
136 struct EgoEntry *ego_head;
137
138 /**
139 * Ego list
140 */
141 struct EgoEntry *ego_tail;
154 142
155 /** 143 /**
156 * The processing state 144 * The processing state
@@ -158,7 +146,7 @@ struct RequestHandle
158 int state; 146 int state;
159 147
160 /** 148 /**
161 * Handle to GNS service. 149 * Handle to Identity service.
162 */ 150 */
163 struct GNUNET_IDENTITY_Handle *identity_handle; 151 struct GNUNET_IDENTITY_Handle *identity_handle;
164 152
@@ -168,6 +156,11 @@ struct RequestHandle
168 struct GNUNET_IDENTITY_Operation *op; 156 struct GNUNET_IDENTITY_Operation *op;
169 157
170 /** 158 /**
159 * Rest connection
160 */
161 struct GNUNET_REST_RequestHandle *rest_handle;
162
163 /**
171 * Desired timeout for the lookup (default is no timeout). 164 * Desired timeout for the lookup (default is no timeout).
172 */ 165 */
173 struct GNUNET_TIME_Relative timeout; 166 struct GNUNET_TIME_Relative timeout;
@@ -175,7 +168,7 @@ struct RequestHandle
175 /** 168 /**
176 * ID of a task associated with the resolution process. 169 * ID of a task associated with the resolution process.
177 */ 170 */
178 struct GNUNET_SCHEDULER_Task * timeout_task; 171 struct GNUNET_SCHEDULER_Task *timeout_task;
179 172
180 /** 173 /**
181 * The plugin result processor 174 * The plugin result processor
@@ -188,43 +181,22 @@ struct RequestHandle
188 void *proc_cls; 181 void *proc_cls;
189 182
190 /** 183 /**
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 184 * The url
202 */ 185 */
203 char *url; 186 char *url;
204 187
205 /** 188 /**
206 * The data from the REST request 189 * 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 */ 190 */
218 const char* method; 191 char *emsg;
219 192
220 /** 193 /**
221 * Error response message 194 * Reponse code
222 */ 195 */
223 char *emsg; 196 int response_code;
224 197
225}; 198};
226 199
227
228/** 200/**
229 * Cleanup lookup handle 201 * Cleanup lookup handle
230 * @param handle Handle to clean up 202 * @param handle Handle to clean up
@@ -234,35 +206,37 @@ cleanup_handle (struct RequestHandle *handle)
234{ 206{
235 struct EgoEntry *ego_entry; 207 struct EgoEntry *ego_entry;
236 struct EgoEntry *ego_tmp; 208 struct EgoEntry *ego_tmp;
237 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 209
238 "Cleaning up\n"); 210 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) 211 if (NULL != handle->timeout_task)
242 { 212 {
243 GNUNET_SCHEDULER_cancel (handle->timeout_task); 213 GNUNET_SCHEDULER_cancel (handle->timeout_task);
244 handle->timeout_task = NULL; 214 handle->timeout_task = NULL;
245 } 215 }
246 if (NULL != handle->identity_handle) 216
247 GNUNET_IDENTITY_disconnect (handle->identity_handle); 217 if (NULL != handle->subsystem)
248 if (NULL != handle->subsys) 218 GNUNET_free(handle->subsystem);
249 GNUNET_free (handle->subsys);
250 if (NULL != handle->url) 219 if (NULL != handle->url)
251 GNUNET_free (handle->url); 220 GNUNET_free(handle->url);
252 if (NULL != handle->emsg) 221 if (NULL != handle->emsg)
253 GNUNET_free (handle->emsg); 222 GNUNET_free(handle->emsg);
223 if (NULL != handle->name)
224 GNUNET_free (handle->name);
225 if (NULL != handle->identity_handle)
226 GNUNET_IDENTITY_disconnect (handle->identity_handle);
227
254 for (ego_entry = handle->ego_head; 228 for (ego_entry = handle->ego_head;
255 NULL != ego_entry;) 229 NULL != ego_entry;)
256 { 230 {
257 ego_tmp = ego_entry; 231 ego_tmp = ego_entry;
258 ego_entry = ego_entry->next; 232 ego_entry = ego_entry->next;
259 GNUNET_free (ego_tmp->identifier); 233 GNUNET_free(ego_tmp->identifier);
260 GNUNET_free (ego_tmp->keystring); 234 GNUNET_free(ego_tmp->keystring);
261 GNUNET_free (ego_tmp); 235 GNUNET_free(ego_tmp);
262 } 236 }
263 GNUNET_free (handle);
264}
265 237
238 GNUNET_free(handle);
239}
266 240
267/** 241/**
268 * Task run on errors. Reports an error and cleans up everything. 242 * Task run on errors. Reports an error and cleans up everything.
@@ -276,21 +250,22 @@ do_error (void *cls)
276 struct MHD_Response *resp; 250 struct MHD_Response *resp;
277 char *json_error; 251 char *json_error;
278 252
279 GNUNET_asprintf (&json_error, 253 if (NULL == handle->emsg)
280 "{Error while processing request: %s}", 254 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_UNKNOWN);
281 &handle->emsg); 255
256 GNUNET_asprintf (&json_error, "{\"error\": \"%s\"}", handle->emsg);
257
258 if (0 == handle->response_code)
259 handle->response_code = MHD_HTTP_OK;
282 260
283 resp = GNUNET_REST_create_response (json_error); 261 resp = GNUNET_REST_create_response (json_error);
284 handle->proc (handle->proc_cls, 262 handle->proc (handle->proc_cls, resp, handle->response_code);
285 resp,
286 handle->response_code);
287 cleanup_handle (handle); 263 cleanup_handle (handle);
288 GNUNET_free (json_error); 264 GNUNET_free(json_error);
289} 265}
290 266
291
292/** 267/**
293 * Callback for IDENTITY_get() 268 * Callback for GET Request with subsystem
294 * 269 *
295 * @param cls the RequestHandle 270 * @param cls the RequestHandle
296 * @param ego the Ego found 271 * @param ego the Ego found
@@ -298,157 +273,153 @@ do_error (void *cls)
298 * @param name the id of the ego 273 * @param name the id of the ego
299 */ 274 */
300static void 275static void
301get_ego_for_subsys (void *cls, 276ego_get_for_subsystem (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx,
302 struct GNUNET_IDENTITY_Ego *ego, 277 const char *name)
303 void **ctx,
304 const char *name)
305{ 278{
306 struct RequestHandle *handle = cls; 279 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; 280 struct MHD_Response *resp;
311 json_t *name_json; 281 struct GNUNET_CRYPTO_EcdsaPublicKey public_key;
282 json_t *json_root;
312 char *result_str; 283 char *result_str;
284 char *public_key_string;
313 285
314 json_document = GNUNET_JSONAPI_document_new (); 286 if(NULL == ego)
315
316 for (ego_entry = handle->ego_head;
317 NULL != ego_entry;
318 ego_entry = ego_entry->next)
319 {
320 if ( (NULL != name) && (0 != strcmp (name, ego_entry->identifier)) )
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 { 287 {
336 GNUNET_JSONAPI_document_delete (json_document); 288 handle->emsg = GNUNET_strdup("No identity found for subsystem");
337 handle->emsg = GNUNET_strdup("No identity matches results!");
338 GNUNET_SCHEDULER_add_now (&do_error, handle); 289 GNUNET_SCHEDULER_add_now (&do_error, handle);
339 return; 290 return;
340 } 291 }
341 GNUNET_JSONAPI_document_serialize (json_document, &result_str); 292
342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); 293 GNUNET_IDENTITY_ego_get_public_key(ego,&public_key);
294 public_key_string = GNUNET_CRYPTO_ecdsa_public_key_to_string(&public_key);
295
296 // create json with subsystem identity
297 json_root = json_object ();
298 json_object_set_new (json_root, GNUNET_REST_PARAM_PUBKEY, json_string(public_key_string));
299 json_object_set_new (json_root, GNUNET_REST_PARAM_NAME, json_string(name));
300
301 result_str = json_dumps (json_root, 0);
302 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
343 resp = GNUNET_REST_create_response (result_str); 303 resp = GNUNET_REST_create_response (result_str);
344 GNUNET_JSONAPI_document_delete (json_document); 304
305 json_decref (json_root);
345 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 306 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
346 GNUNET_free (result_str); 307 GNUNET_free(result_str);
308 GNUNET_free(public_key_string);
347 cleanup_handle (handle); 309 cleanup_handle (handle);
348} 310}
349 311
350/** 312/**
351 * Create a response with requested ego(s) 313 * Handle identity GET request
352 * 314 *
353 * @param con the Rest handle 315 * @param con_handle the connection handle
354 * @param url the requested url 316 * @param url the url
355 * @param cls the request handle 317 * @param cls the RequestHandle
356 */ 318 */
357static void 319void
358ego_info_response (struct GNUNET_REST_RequestHandle *con, 320ego_get (struct GNUNET_REST_RequestHandle *con_handle, const char* url,
359 const char *url, 321 void *cls)
360 void *cls)
361{ 322{
362 const char *egoname;
363 char *result_str;
364 char *subsys_val;
365 char *keystring;
366 struct RequestHandle *handle = cls; 323 struct RequestHandle *handle = cls;
367 struct EgoEntry *ego_entry; 324 struct EgoEntry *ego_entry;
368 struct GNUNET_HashCode key; 325 struct GNUNET_HashCode key;
369 struct MHD_Response *resp; 326 struct MHD_Response *resp;
370 struct GNUNET_JSONAPI_Document *json_document; 327 char *keystring;
371 struct GNUNET_JSONAPI_Resource *json_resource; 328 const char *egoname;
372 json_t *name_str; 329 json_t *json_root;
373 330 json_t *json_ego;
374 if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url, GNUNET_REST_API_NS_IDENTITY)) 331 char *result_str;
332 size_t index;
333
334 //if subsystem
335 GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_SUBSYSTEM,
336 strlen (GNUNET_REST_PARAM_SUBSYSTEM), &key);
337 if ( GNUNET_YES
338 == GNUNET_CONTAINER_multihashmap_contains (
339 handle->rest_handle->url_param_map, &key))
375 { 340 {
376 resp = GNUNET_REST_create_response (NULL); 341 handle->subsystem = GNUNET_strdup(
377 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST); 342 GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
378 cleanup_handle (handle); 343 &key));
344 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n",
345 handle->subsystem);
346
347 handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
348 handle->subsystem, &ego_get_for_subsystem,
349 handle);
350 if (NULL == handle->op)
351 {
352 handle->emsg = GNUNET_strdup("No identity found for subsystem");
353 GNUNET_SCHEDULER_add_now (&do_error, handle);
354 return;
355 }
379 return; 356 return;
380 } 357 }
381 egoname = NULL; 358 egoname = NULL;
382 keystring = NULL; 359 keystring = NULL;
383 if (strlen (GNUNET_REST_API_NS_IDENTITY) < strlen (handle->url)) 360
361 //if only one identity requested
362 GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_PUBKEY,
363 strlen (GNUNET_REST_PARAM_PUBKEY), &key);
364 if ( GNUNET_YES
365 == GNUNET_CONTAINER_multihashmap_contains (
366 handle->rest_handle->url_param_map, &key))
384 { 367 {
385 keystring = &handle->url[strlen (GNUNET_REST_API_NS_IDENTITY)+1]; 368 keystring = GNUNET_CONTAINER_multihashmap_get (
386 //Return all egos 369 handle->rest_handle->url_param_map, &key);
370
387 for (ego_entry = handle->ego_head; 371 for (ego_entry = handle->ego_head;
388 NULL != ego_entry; 372 NULL != ego_entry; ego_entry = ego_entry->next)
389 ego_entry = ego_entry->next)
390 { 373 {
391 if ( (NULL != keystring) && (0 != strcmp (keystring, ego_entry->keystring)) ) 374 if ((NULL != keystring)
392 continue; 375 && (0 != strcmp (keystring, ego_entry->keystring)))
376 continue;
393 egoname = ego_entry->identifier; 377 egoname = ego_entry->identifier;
394 } 378 }
395 } 379 }
396 380
397 if ( NULL == egoname ) { 381 json_root = json_array ();
398 GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM, 382 //Return ego/egos
399 strlen (GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM), 383 for (ego_entry = handle->ego_head;
400 &key); 384 NULL != ego_entry; ego_entry = ego_entry->next)
401 if ( GNUNET_YES == 385 {
402 GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, 386 //if only one ego requested
403 &key) ) 387 if ((NULL != egoname)){
404 { 388 if(0 != strcmp (egoname, ego_entry->identifier)){
405 subsys_val = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, 389 continue;
406 &key);
407 if (NULL != subsys_val)
408 {
409 GNUNET_asprintf (&handle->subsys, "%s", subsys_val);
410 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looking for %s's ego\n", subsys_val);
411 handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
412 handle->subsys,
413 &get_ego_for_subsys,
414 handle);
415 return;
416 } 390 }
417 } 391 }
418 }
419 392
420 json_document = GNUNET_JSONAPI_document_new (); 393 json_ego = json_object ();
394 json_object_set_new (json_ego,
395 GNUNET_REST_PARAM_PUBKEY,
396 json_string (ego_entry->keystring));
397 json_object_set_new (json_ego,
398 GNUNET_REST_PARAM_NAME,
399 json_string (ego_entry->identifier));
400 json_array_append (json_root, json_ego);
401 }
421 402
422 //Return all egos 403 if ((size_t) 0 == json_array_size (json_root))
423 for (ego_entry = handle->ego_head;
424 NULL != ego_entry;
425 ego_entry = ego_entry->next)
426 { 404 {
427 if ( (NULL != egoname) && (0 != strcmp (egoname, ego_entry->identifier)) ) 405 json_decref (json_root);
428 continue; 406 handle->emsg = GNUNET_strdup("No identities found!");
429 json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_IDENTITY_EGO,
430 ego_entry->keystring);
431 name_str = json_string (ego_entry->identifier);
432 GNUNET_JSONAPI_resource_add_attr (
433 json_resource,
434 GNUNET_REST_JSONAPI_IDENTITY_NAME,
435 name_str);
436 json_decref (name_str);
437 GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
438 }
439 if (0 == GNUNET_JSONAPI_document_resource_count (json_document))
440 {
441 GNUNET_JSONAPI_document_delete (json_document);
442 handle->emsg = GNUNET_strdup ("No identities found!");
443 GNUNET_SCHEDULER_add_now (&do_error, handle); 407 GNUNET_SCHEDULER_add_now (&do_error, handle);
444 return; 408 return;
445 } 409 }
446 GNUNET_JSONAPI_document_serialize (json_document, &result_str); 410
447 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); 411 result_str = json_dumps (json_root, 0);
412 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
448 resp = GNUNET_REST_create_response (result_str); 413 resp = GNUNET_REST_create_response (result_str);
449 GNUNET_JSONAPI_document_delete (json_document); 414
415 //delete json_objects in json_array with macro
416 json_array_foreach(json_root, index, json_ego )
417 {
418 json_decref (json_ego);
419 }
420 json_decref (json_root);
450 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 421 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
451 GNUNET_free (result_str); 422 GNUNET_free(result_str);
452 cleanup_handle (handle); 423 cleanup_handle (handle);
453} 424}
454 425
@@ -467,290 +438,290 @@ do_finished (void *cls, const char *emsg)
467 handle->op = NULL; 438 handle->op = NULL;
468 if (NULL != emsg) 439 if (NULL != emsg)
469 { 440 {
470 handle->emsg = GNUNET_strdup (emsg); 441 handle->emsg = GNUNET_strdup(emsg);
471 GNUNET_SCHEDULER_add_now (&do_error, handle); 442 GNUNET_SCHEDULER_add_now (&do_error, handle);
472 return; 443 return;
473 } 444 }
474 resp = GNUNET_REST_create_response (NULL); 445 resp = GNUNET_REST_create_response (NULL);
475 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT); 446 handle->proc (handle->proc_cls, resp, handle->response_code);
476 cleanup_handle (handle); 447 cleanup_handle (handle);
477} 448}
478 449
479/** 450/**
480 * Create a new ego 451 * Handle identity PUT request
481 * 452 *
482 * @param con rest handle 453 * @param con_handle the connection handle
483 * @param url url 454 * @param url the url
484 * @param cls request handle 455 * @param cls the RequestHandle
485 */ 456 */
486static void 457void
487ego_create_cont (struct GNUNET_REST_RequestHandle *con, 458ego_edit (struct GNUNET_REST_RequestHandle *con_handle, const char* url,
488 const char *url, 459 void *cls)
489 void *cls)
490{ 460{
491 struct RequestHandle *handle = cls; 461 struct RequestHandle *handle = cls;
492 struct EgoEntry *ego_entry; 462 struct EgoEntry *ego_entry;
463 struct EgoEntry *ego_entry_tmp;
493 struct MHD_Response *resp; 464 struct MHD_Response *resp;
494 struct GNUNET_JSONAPI_Document *json_obj; 465 json_t *subsys_json;
495 struct GNUNET_JSONAPI_Resource *json_res; 466 json_t *name_json;
496 json_t *egoname_json; 467 json_t *key_json;
497 json_t *data_js; 468 json_t *data_js;
498 json_error_t err; 469 json_error_t err;
499 const char* egoname; 470 const char *keystring;
500 char term_data[handle->data_size+1]; 471 const char *subsys;
501 struct GNUNET_JSON_Specification docspec[] = { 472 const char *newname;
502 GNUNET_JSON_spec_jsonapi_document (&json_obj), 473 char term_data[handle->data_size + 1];
503 GNUNET_JSON_spec_end() 474 int ego_exists = GNUNET_NO;
504 }; 475
505 if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url)) 476 //if no data
477 if (0 >= handle->data_size)
506 { 478 {
507 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID); 479 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
508 GNUNET_SCHEDULER_add_now (&do_error, handle); 480 GNUNET_SCHEDULER_add_now (&do_error, handle);
509 return; 481 return;
510 } 482 }
511 if (0 >= handle->data_size) 483 //if not json
484 term_data[handle->data_size] = '\0';
485 GNUNET_memcpy(term_data, handle->data, handle->data_size);
486 data_js = json_loads (term_data,JSON_DECODE_ANY,&err);
487 if (NULL == data_js)
512 { 488 {
513 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA); 489 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
514 GNUNET_SCHEDULER_add_now (&do_error, handle); 490 GNUNET_SCHEDULER_add_now (&do_error, handle);
515 return; 491 return;
516 } 492 }
517 term_data[handle->data_size] = '\0'; 493 if (!json_is_object(data_js))
518 GNUNET_memcpy (term_data, handle->data, handle->data_size);
519 data_js = json_loads (term_data,
520 JSON_DECODE_ANY,
521 &err);
522 GNUNET_assert (NULL != data_js);
523 GNUNET_assert (GNUNET_OK ==
524 GNUNET_JSON_parse (data_js, docspec,
525 NULL, NULL));
526
527 json_decref (data_js);
528
529 if (NULL == json_obj)
530 { 494 {
495 json_decref (data_js);
496 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
531 GNUNET_SCHEDULER_add_now (&do_error, handle); 497 GNUNET_SCHEDULER_add_now (&do_error, handle);
532 return; 498 return;
533 } 499 }
534 if (1 != GNUNET_JSONAPI_document_resource_count (json_obj)) 500 //json must contain pubkey and (subsystem or name)
501 if (2 != json_object_size (data_js))
535 { 502 {
536 GNUNET_JSONAPI_document_delete (json_obj); 503 json_decref (data_js);
537 handle->emsg = GNUNET_strdup ("Provided resource count invalid"); 504 handle->emsg = GNUNET_strdup("Resource amount invalid");
538 GNUNET_SCHEDULER_add_now (&do_error, handle); 505 GNUNET_SCHEDULER_add_now (&do_error, handle);
539 return; 506 return;
540 } 507 }
541 json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0); 508
542 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res, GNUNET_REST_JSONAPI_IDENTITY_EGO)) 509 key_json = json_object_get (data_js, GNUNET_REST_PARAM_PUBKEY);
510 if ((NULL == key_json) || !json_is_string(key_json))
511 {
512 json_decref (data_js);
513 handle->emsg = GNUNET_strdup("Missing element pubkey");
514 GNUNET_SCHEDULER_add_now (&do_error, handle);
515 return;
516 }
517 keystring = json_string_value (key_json);
518
519 for (ego_entry = handle->ego_head;
520 NULL != ego_entry; ego_entry = ego_entry->next)
521 {
522 if (0 != strcasecmp (keystring, ego_entry->keystring))
523 continue;
524 ego_exists = GNUNET_YES;
525 break;
526 }
527
528 if (GNUNET_NO == ego_exists)
543 { 529 {
544 GNUNET_JSONAPI_document_delete (json_obj); 530 json_decref (data_js);
545 resp = GNUNET_REST_create_response (NULL); 531 resp = GNUNET_REST_create_response (NULL);
546 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); 532 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
547 cleanup_handle (handle); 533 cleanup_handle (handle);
548 return; 534 return;
549 } 535 }
550 egoname_json = GNUNET_JSONAPI_resource_read_attr (json_res, GNUNET_REST_JSONAPI_IDENTITY_NAME); 536 //This is a rename
551 if (!json_is_string (egoname_json)) 537 name_json = json_object_get (data_js, GNUNET_REST_PARAM_NEWNAME);
538 if ((NULL != name_json) && json_is_string(name_json))
552 { 539 {
553 GNUNET_JSONAPI_document_delete (json_obj); 540 newname = json_string_value (name_json);
554 handle->emsg = GNUNET_strdup ("No name provided"); 541 if (0 >= strlen (newname))
555 GNUNET_SCHEDULER_add_now (&do_error, handle); 542 {
543 json_decref (data_js);
544 handle->emsg = GNUNET_strdup("No name provided");
545 GNUNET_SCHEDULER_add_now (&do_error, handle);
546 return;
547 }
548 for (ego_entry_tmp = handle->ego_head;
549 NULL != ego_entry_tmp; ego_entry_tmp = ego_entry_tmp->next)
550 {
551 if (0 == strcasecmp (newname, ego_entry_tmp->identifier)
552 && 0 != strcasecmp (keystring, ego_entry_tmp->keystring))
553 {
554 //Ego with same name not allowed
555 json_decref (data_js);
556 resp = GNUNET_REST_create_response (NULL);
557 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
558 cleanup_handle (handle);
559 return;
560 }
561 }
562 handle->response_code = MHD_HTTP_NO_CONTENT;
563 handle->op = GNUNET_IDENTITY_rename (handle->identity_handle,
564 ego_entry->identifier, newname,
565 &do_finished, handle);
566 json_decref (data_js);
556 return; 567 return;
557 } 568 }
558 egoname = json_string_value (egoname_json); 569
559 for (ego_entry = handle->ego_head; 570 //Set subsystem
560 NULL != ego_entry; 571 subsys_json = json_object_get (data_js, GNUNET_REST_PARAM_SUBSYSTEM);
561 ego_entry = ego_entry->next) 572 if ((NULL != subsys_json) && json_is_string(subsys_json))
562 { 573 {
563 if (0 == strcasecmp (egoname, ego_entry->identifier)) 574 subsys = json_string_value (subsys_json);
575 if (0 >= strlen (subsys))
564 { 576 {
565 GNUNET_JSONAPI_document_delete (json_obj); 577 json_decref (data_js);
566 resp = GNUNET_REST_create_response (NULL); 578 handle->emsg = GNUNET_strdup("Invalid subsystem name");
567 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); 579 GNUNET_SCHEDULER_add_now (&do_error, handle);
568 cleanup_handle (handle);
569 return; 580 return;
570 } 581 }
582 GNUNET_asprintf (&handle->subsystem, "%s", subsys);
583 json_decref (data_js);
584 handle->response_code = MHD_HTTP_NO_CONTENT;
585 handle->op = GNUNET_IDENTITY_set (handle->identity_handle, handle->subsystem,
586 ego_entry->ego, &do_finished, handle);
587 return;
571 } 588 }
572 GNUNET_asprintf (&handle->name, "%s", egoname); 589 json_decref (data_js);
573 GNUNET_JSONAPI_document_delete (json_obj); 590 handle->emsg = GNUNET_strdup("Subsystem not provided");
574 handle->op = GNUNET_IDENTITY_create (handle->identity_handle, 591 GNUNET_SCHEDULER_add_now (&do_error, handle);
575 handle->name,
576 &do_finished,
577 handle);
578} 592}
579 593
580
581/** 594/**
582 * Handle ego edit request 595 * Handle identity POST request
583 * 596 *
584 * @param con rest connection handle 597 * @param con_handle the connection handle
585 * @param url the url that is requested 598 * @param url the url
586 * @param cls the RequestHandle 599 * @param cls the RequestHandle
587 */ 600 */
588static void 601void
589ego_edit_cont (struct GNUNET_REST_RequestHandle *con, 602ego_create (struct GNUNET_REST_RequestHandle *con_handle, const char* url,
590 const char *url, 603 void *cls)
591 void *cls)
592{ 604{
593 struct GNUNET_JSONAPI_Document *json_obj;
594 struct GNUNET_JSONAPI_Resource *json_res;
595 struct RequestHandle *handle = cls; 605 struct RequestHandle *handle = cls;
596 struct EgoEntry *ego_entry; 606 struct EgoEntry *ego_entry;
597 struct EgoEntry *ego_entry_tmp;
598 struct MHD_Response *resp; 607 struct MHD_Response *resp;
599 json_t *subsys_json; 608 json_t *egoname_json;
600 json_t *name_json;
601 json_t *data_js; 609 json_t *data_js;
602 json_error_t err; 610 json_error_t err;
603 const char *keystring; 611 const char* egoname;
604 const char *subsys; 612 char term_data[handle->data_size + 1];
605 const char *newname;
606 char term_data[handle->data_size+1];
607 int ego_exists = GNUNET_NO;
608 struct GNUNET_JSON_Specification docspec[] = {
609 GNUNET_JSON_spec_jsonapi_document (&json_obj),
610 GNUNET_JSON_spec_end()
611 };
612 613
613 if (strlen (GNUNET_REST_API_NS_IDENTITY) > strlen (handle->url)) 614 if (strlen (GNUNET_REST_API_NS_IDENTITY) != strlen (handle->url))
614 { 615 {
615 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID); 616 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_RESOURCE_INVALID);
616 GNUNET_SCHEDULER_add_now (&do_error, handle); 617 GNUNET_SCHEDULER_add_now (&do_error, handle);
617 return; 618 return;
618 } 619 }
619 620
620 keystring = &handle->url[strlen(GNUNET_REST_API_NS_IDENTITY)+1];
621
622 for (ego_entry = handle->ego_head;
623 NULL != ego_entry;
624 ego_entry = ego_entry->next)
625 {
626 if (0 != strcasecmp (keystring, ego_entry->keystring))
627 continue;
628 ego_exists = GNUNET_YES;
629 break;
630 }
631
632 if (GNUNET_NO == ego_exists)
633 {
634 resp = GNUNET_REST_create_response (NULL);
635 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
636 cleanup_handle (handle);
637 return;
638 }
639
640 if (0 >= handle->data_size) 621 if (0 >= handle->data_size)
641 { 622 {
642 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_NO_DATA); 623 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_NO_DATA);
643 GNUNET_SCHEDULER_add_now (&do_error, handle); 624 GNUNET_SCHEDULER_add_now (&do_error, handle);
644 return; 625 return;
645 } 626 }
646
647 term_data[handle->data_size] = '\0'; 627 term_data[handle->data_size] = '\0';
648 GNUNET_memcpy (term_data, handle->data, handle->data_size); 628 GNUNET_memcpy(term_data, handle->data, handle->data_size);
649 data_js = json_loads (term_data, 629 data_js = json_loads (term_data,
650 JSON_DECODE_ANY, 630 JSON_DECODE_ANY,
651 &err); 631 &err);
652 GNUNET_assert (NULL != data_js);
653 GNUNET_assert (GNUNET_OK ==
654 GNUNET_JSON_parse (data_js, docspec,
655 NULL, NULL));
656
657 json_decref (data_js);
658 632
659 if (NULL == json_obj) 633 if (NULL == data_js)
660 { 634 {
661 handle->emsg = GNUNET_strdup ("Data invalid"); 635 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
662 GNUNET_SCHEDULER_add_now (&do_error, handle); 636 GNUNET_SCHEDULER_add_now (&do_error, handle);
663 return; 637 return;
664 } 638 }
665 639 //instead of parse
666 if (1 != GNUNET_JSONAPI_document_resource_count (json_obj)) 640 if (!json_is_object(data_js))
667 { 641 {
668 GNUNET_JSONAPI_document_delete (json_obj); 642 json_decref (data_js);
669 handle->emsg = GNUNET_strdup ("Resource amount invalid"); 643 handle->emsg = GNUNET_strdup(GNUNET_REST_ERROR_DATA_INVALID);
670 GNUNET_SCHEDULER_add_now (&do_error, handle); 644 GNUNET_SCHEDULER_add_now (&do_error, handle);
671 return; 645 return;
672 } 646 }
673 json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
674 647
675 if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res, GNUNET_REST_JSONAPI_IDENTITY_EGO)) 648 if (1 != json_object_size (data_js))
676 { 649 {
677 GNUNET_JSONAPI_document_delete (json_obj); 650 json_decref (data_js);
678 handle->emsg = GNUNET_strdup ("Resource type invalid"); 651 handle->emsg = GNUNET_strdup("Provided resource count invalid");
679 GNUNET_SCHEDULER_add_now (&do_error, handle); 652 GNUNET_SCHEDULER_add_now (&do_error, handle);
680 return; 653 return;
681 } 654 }
682 655
683 //This is a rename 656 egoname_json = json_object_get (data_js, GNUNET_REST_PARAM_NAME);
684 name_json = GNUNET_JSONAPI_resource_read_attr (json_res, 657 if (!json_is_string(egoname_json))
685 GNUNET_REST_JSONAPI_IDENTITY_NEWNAME);
686 if ((NULL != name_json) && json_is_string (name_json))
687 { 658 {
688 newname = json_string_value (name_json); 659 json_decref (data_js);
689 for (ego_entry_tmp = handle->ego_head; 660 handle->emsg = GNUNET_strdup("No name provided");
690 NULL != ego_entry_tmp; 661 GNUNET_SCHEDULER_add_now (&do_error, handle);
691 ego_entry_tmp = ego_entry_tmp->next)
692 {
693 if (0 == strcasecmp (newname, ego_entry_tmp->identifier) &&
694 0 != strcasecmp (keystring, ego_entry_tmp->keystring))
695 {
696 //Ego with same name not allowed
697 GNUNET_JSONAPI_document_delete (json_obj);
698 resp = GNUNET_REST_create_response (NULL);
699 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
700 cleanup_handle (handle);
701 return;
702 }
703 }
704 handle->op = GNUNET_IDENTITY_rename (handle->identity_handle,
705 ego_entry->identifier,
706 newname,
707 &do_finished,
708 handle);
709 GNUNET_JSONAPI_document_delete (json_obj);
710 return; 662 return;
711 } 663 }
712 664 egoname = json_string_value (egoname_json);
713 //Set subsystem 665 if (0 >= strlen (egoname))
714 subsys_json = GNUNET_JSONAPI_resource_read_attr (json_res, GNUNET_REST_JSONAPI_IDENTITY_SUBSYSTEM);
715 if ( (NULL != subsys_json) && json_is_string (subsys_json))
716 { 666 {
717 subsys = json_string_value (subsys_json); 667 json_decref (data_js);
718 GNUNET_asprintf (&handle->subsys, "%s", subsys); 668 handle->emsg = GNUNET_strdup("No name provided");
719 GNUNET_JSONAPI_document_delete (json_obj); 669 GNUNET_SCHEDULER_add_now (&do_error, handle);
720 handle->op = GNUNET_IDENTITY_set (handle->identity_handle,
721 handle->subsys,
722 ego_entry->ego,
723 &do_finished,
724 handle);
725 return; 670 return;
726 } 671 }
727 GNUNET_JSONAPI_document_delete (json_obj); 672 for (ego_entry = handle->ego_head;
728 handle->emsg = GNUNET_strdup ("Subsystem not provided"); 673 NULL != ego_entry; ego_entry = ego_entry->next)
729 GNUNET_SCHEDULER_add_now (&do_error, handle); 674 {
675 if (0 == strcasecmp (egoname, ego_entry->identifier))
676 {
677 json_decref (data_js);
678 resp = GNUNET_REST_create_response (NULL);
679 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
680 cleanup_handle (handle);
681 return;
682 }
683 }
684 GNUNET_asprintf (&handle->name, "%s", egoname);
685 json_decref (data_js);
686 handle->response_code = MHD_HTTP_CREATED;
687 handle->op = GNUNET_IDENTITY_create (handle->identity_handle, handle->name,
688 &do_finished, handle);
730} 689}
731 690
691/**
692 * Handle identity DELETE request
693 *
694 * @param con_handle the connection handle
695 * @param url the url
696 * @param cls the RequestHandle
697 */
732void 698void
733ego_delete_cont (struct GNUNET_REST_RequestHandle *con_handle, 699ego_delete (struct GNUNET_REST_RequestHandle *con_handle, const char* url,
734 const char* url, 700 void *cls)
735 void *cls)
736{ 701{
737 const char *keystring; 702 const char *keystring;
738 struct EgoEntry *ego_entry; 703 struct EgoEntry *ego_entry;
704 struct GNUNET_HashCode key;
739 struct MHD_Response *resp; 705 struct MHD_Response *resp;
740 struct RequestHandle *handle = cls; 706 struct RequestHandle *handle = cls;
741 int ego_exists = GNUNET_NO; 707 int ego_exists = GNUNET_NO;
742 708
743 if (strlen (GNUNET_REST_API_NS_IDENTITY) >= strlen (handle->url)) 709 //if only one identity requested
710 GNUNET_CRYPTO_hash (GNUNET_REST_PARAM_PUBKEY,
711 strlen (GNUNET_REST_PARAM_PUBKEY), &key);
712 if ( GNUNET_NO
713 == GNUNET_CONTAINER_multihashmap_contains (
714 handle->rest_handle->url_param_map, &key))
744 { 715 {
745 handle->emsg = GNUNET_strdup (GNUNET_REST_ERROR_RESOURCE_INVALID); 716 handle->emsg = GNUNET_strdup("Missing parameter pubkey");
746 GNUNET_SCHEDULER_add_now (&do_error, handle); 717 GNUNET_SCHEDULER_add_now (&do_error, handle);
747 return; 718 return;
748 } 719 }
749 720
750 keystring = &handle->url[strlen(GNUNET_REST_API_NS_IDENTITY)+1]; 721 keystring = GNUNET_CONTAINER_multihashmap_get (
722 handle->rest_handle->url_param_map,&key);
751 for (ego_entry = handle->ego_head; 723 for (ego_entry = handle->ego_head;
752 NULL != ego_entry; 724 NULL != ego_entry; ego_entry = ego_entry->next)
753 ego_entry = ego_entry->next)
754 { 725 {
755 if (0 != strcasecmp (keystring, ego_entry->keystring)) 726 if (0 != strcasecmp (keystring, ego_entry->keystring))
756 continue; 727 continue;
@@ -764,14 +735,13 @@ ego_delete_cont (struct GNUNET_REST_RequestHandle *con_handle,
764 cleanup_handle (handle); 735 cleanup_handle (handle);
765 return; 736 return;
766 } 737 }
738 handle->response_code = MHD_HTTP_NO_CONTENT;
767 handle->op = GNUNET_IDENTITY_delete (handle->identity_handle, 739 handle->op = GNUNET_IDENTITY_delete (handle->identity_handle,
768 ego_entry->identifier, 740 ego_entry->identifier, &do_finished,
769 &do_finished, 741 handle);
770 handle);
771 742
772} 743}
773 744
774
775/** 745/**
776 * Respond to OPTIONS request 746 * Respond to OPTIONS request
777 * 747 *
@@ -780,18 +750,15 @@ ego_delete_cont (struct GNUNET_REST_RequestHandle *con_handle,
780 * @param cls the RequestHandle 750 * @param cls the RequestHandle
781 */ 751 */
782static void 752static void
783options_cont (struct GNUNET_REST_RequestHandle *con_handle, 753options_cont (struct GNUNET_REST_RequestHandle *con_handle, const char* url,
784 const char* url, 754 void *cls)
785 void *cls)
786{ 755{
787 struct MHD_Response *resp; 756 struct MHD_Response *resp;
788 struct RequestHandle *handle = cls; 757 struct RequestHandle *handle = cls;
789 758
790 //For now, independent of path return all options 759 //For now, independent of path return all options
791 resp = GNUNET_REST_create_response (NULL); 760 resp = GNUNET_REST_create_response (NULL);
792 MHD_add_response_header (resp, 761 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
793 "Access-Control-Allow-Methods",
794 allow_methods);
795 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 762 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
796 cleanup_handle (handle); 763 cleanup_handle (handle);
797 return; 764 return;
@@ -807,18 +774,17 @@ init_cont (struct RequestHandle *handle)
807{ 774{
808 struct GNUNET_REST_RequestHandlerError err; 775 struct GNUNET_REST_RequestHandlerError err;
809 static const struct GNUNET_REST_RequestHandler handlers[] = { 776 static const struct GNUNET_REST_RequestHandler handlers[] = {
810 {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_info_response}, 777 { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY, &ego_get },
811 {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create_cont}, 778 { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY, &ego_edit },
812 {MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_IDENTITY, &ego_edit_cont}, 779 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY, &ego_create },
813 {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_IDENTITY, &ego_delete_cont}, 780 { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_IDENTITY, &ego_delete },
814 {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont}, 781 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY, &options_cont },
815 GNUNET_REST_HANDLER_END 782 GNUNET_REST_HANDLER_END
816 }; 783 };
817 784
818 if (GNUNET_NO == GNUNET_JSONAPI_handle_request (handle->conndata_handle, 785 if (GNUNET_NO
819 handlers, 786 == GNUNET_REST_handle_request (handle->rest_handle, handlers, &err,
820 &err, 787 handle))
821 handle))
822 { 788 {
823 handle->response_code = err.error_code; 789 handle->response_code = err.error_code;
824 GNUNET_SCHEDULER_add_now (&do_error, handle); 790 GNUNET_SCHEDULER_add_now (&do_error, handle);
@@ -859,10 +825,8 @@ init_cont (struct RequestHandle *handle)
859 * must thus no longer be used 825 * must thus no longer be used
860 */ 826 */
861static void 827static void
862list_ego (void *cls, 828init_egos (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx,
863 struct GNUNET_IDENTITY_Ego *ego, 829 const char *identifier)
864 void **ctx,
865 const char *identifier)
866{ 830{
867 struct RequestHandle *handle = cls; 831 struct RequestHandle *handle = cls;
868 struct EgoEntry *ego_entry; 832 struct EgoEntry *ego_entry;
@@ -874,16 +838,16 @@ list_ego (void *cls,
874 init_cont (handle); 838 init_cont (handle);
875 return; 839 return;
876 } 840 }
877 if (ID_REST_STATE_INIT == handle->state) { 841 if (ID_REST_STATE_INIT == handle->state)
878 ego_entry = GNUNET_new (struct EgoEntry); 842 {
843 ego_entry = GNUNET_new(struct EgoEntry);
879 GNUNET_IDENTITY_ego_get_public_key (ego, &pk); 844 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
880 ego_entry->keystring = 845 ego_entry->keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
881 GNUNET_CRYPTO_ecdsa_public_key_to_string (&pk);
882 ego_entry->ego = ego; 846 ego_entry->ego = ego;
883 GNUNET_asprintf (&ego_entry->identifier, "%s", identifier); 847 GNUNET_asprintf (&ego_entry->identifier, "%s", identifier);
884 GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head,handle->ego_tail, ego_entry); 848 GNUNET_CONTAINER_DLL_insert_tail(handle->ego_head, handle->ego_tail,
849 ego_entry);
885 } 850 }
886
887} 851}
888 852
889/** 853/**
@@ -898,39 +862,30 @@ list_ego (void *cls,
898 * @return GNUNET_OK if request accepted 862 * @return GNUNET_OK if request accepted
899 */ 863 */
900static void 864static void
901rest_identity_process_request(struct GNUNET_REST_RequestHandle *conndata_handle, 865rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
902 GNUNET_REST_ResultProcessor proc, 866 GNUNET_REST_ResultProcessor proc, void *proc_cls)
903 void *proc_cls)
904{ 867{
905 struct RequestHandle *handle = GNUNET_new (struct RequestHandle); 868 struct RequestHandle *handle = GNUNET_new(struct RequestHandle);
906
907
908 869
870 handle->response_code = 0;
909 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; 871 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
910
911 handle->proc_cls = proc_cls; 872 handle->proc_cls = proc_cls;
912 handle->proc = proc; 873 handle->proc = proc;
913 handle->state = ID_REST_STATE_INIT; 874 handle->rest_handle = rest_handle;
914 handle->conndata_handle = conndata_handle; 875 handle->data = rest_handle->data;
915 handle->data = conndata_handle->data; 876 handle->data_size = rest_handle->data_size;
916 handle->data_size = conndata_handle->data_size; 877
917 handle->method = conndata_handle->method; 878 handle->url = GNUNET_strdup(rest_handle->url);
918 GNUNET_asprintf (&handle->url, "%s", conndata_handle->url); 879 if (handle->url[strlen (handle->url) - 1] == '/')
919 if (handle->url[strlen (handle->url)-1] == '/') 880 handle->url[strlen (handle->url) - 1] = '\0';
920 handle->url[strlen (handle->url)-1] = '\0'; 881 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
921 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 882
922 "Connecting...\n"); 883 handle->identity_handle = GNUNET_IDENTITY_connect (cfg, &init_egos, handle);
923 handle->identity_handle = GNUNET_IDENTITY_connect (cfg, 884
924 &list_ego, 885 handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
925 handle); 886 &do_error, handle);
926 handle->timeout_task = 887
927 GNUNET_SCHEDULER_add_delayed (handle->timeout, 888 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
928 &do_error,
929 handle);
930
931
932 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
933 "Connected\n");
934} 889}
935 890
936/** 891/**
@@ -947,27 +902,24 @@ libgnunet_plugin_rest_identity_init (void *cls)
947 902
948 cfg = cls; 903 cfg = cls;
949 if (NULL != plugin.cfg) 904 if (NULL != plugin.cfg)
950 return NULL; /* can only initialize once! */ 905 return NULL; /* can only initialize once! */
951 memset (&plugin, 0, sizeof (struct Plugin)); 906 memset (&plugin, 0, sizeof(struct Plugin));
952 plugin.cfg = cfg; 907 plugin.cfg = cfg;
953 api = GNUNET_new (struct GNUNET_REST_Plugin); 908 api = GNUNET_new(struct GNUNET_REST_Plugin);
954 api->cls = &plugin; 909 api->cls = &plugin;
955 api->name = GNUNET_REST_API_NS_IDENTITY; 910 api->name = GNUNET_REST_API_NS_IDENTITY;
956 api->process_request = &rest_identity_process_request; 911 api->process_request = &rest_process_request;
957 GNUNET_asprintf (&allow_methods, 912 GNUNET_asprintf (&allow_methods, "%s, %s, %s, %s, %s",
958 "%s, %s, %s, %s, %s", 913 MHD_HTTP_METHOD_GET,
959 MHD_HTTP_METHOD_GET, 914 MHD_HTTP_METHOD_POST,
960 MHD_HTTP_METHOD_POST, 915 MHD_HTTP_METHOD_PUT,
961 MHD_HTTP_METHOD_PUT, 916 MHD_HTTP_METHOD_DELETE,
962 MHD_HTTP_METHOD_DELETE, 917 MHD_HTTP_METHOD_OPTIONS);
963 MHD_HTTP_METHOD_OPTIONS); 918
964 919 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, _("Identity REST API initialized\n"));
965 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
966 _("Identity REST API initialized\n"));
967 return api; 920 return api;
968} 921}
969 922
970
971/** 923/**
972 * Exit point from the plugin. 924 * Exit point from the plugin.
973 * 925 *
@@ -979,13 +931,13 @@ libgnunet_plugin_rest_identity_done (void *cls)
979{ 931{
980 struct GNUNET_REST_Plugin *api = cls; 932 struct GNUNET_REST_Plugin *api = cls;
981 struct Plugin *plugin = api->cls; 933 struct Plugin *plugin = api->cls;
982
983 plugin->cfg = NULL; 934 plugin->cfg = NULL;
984 GNUNET_free_non_null (allow_methods); 935
985 GNUNET_free (api); 936 GNUNET_free_non_null(allow_methods);
986 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 937 GNUNET_free(api);
987 "Identity REST plugin is finished\n"); 938 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Identity REST plugin is finished\n");
988 return NULL; 939 return NULL;
989} 940}
990 941
991/* end of plugin_rest_gns.c */ 942/* end of plugin_rest_identity.c */
943
diff --git a/src/identity/test_plugin_identity_rest.sh b/src/identity/test_plugin_identity_rest.sh
new file mode 100755
index 000000000..d43f4206b
--- /dev/null
+++ b/src/identity/test_plugin_identity_rest.sh
@@ -0,0 +1,252 @@
1#!/usr/bin/bash
2
3#First, start gnunet-arm and the rest-service. Make sure, no identity exists
4
5link_to_api="http://localhost:7776/identity"
6wrong_link="http://localhost:7776/idenmmmy"
7
8#Test GET (multiple identities) for error when no identity exists
9
10echo "No test for subsystem available"
11echo "The next test case can be ignored if you have already added identities"
12cache="$(curl --silent "$link_to_api" | grep "error")"
13if [ "" == "$cache" ]
14then
15 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for GET request when missing identity\n"
16else
17 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for GET request when missing identity\n"
18fi
19
20#Test POST success code, error response code and error json
21echo "The next test case can be ignored if you have already added an identity with the name Test"
22cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":\"Test\"}" 2>&1 | grep "HTTP/1.1 201")"
23if [ "" == "$cache" ]
24then
25 echo -n -e "[\033[0;31m FAILURE\033[0m ] Error for good POST request\n"
26else
27 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Success for good POST request\n"
28fi
29
30cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":\"Test\"}" 2>&1 | grep "HTTP/1.1 409")"
31if [ "" == "$cache" ]
32then
33 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for duplicate name POST request\n"
34else
35 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for duplicate name POST request\n"
36fi
37
38cache="$(curl -v -X "POST" "$link_to_api" 2>&1 | grep "error")"
39if [ "" == "$cache" ]
40then
41 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for no data POST request\n"
42else
43 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for no data POST request\n"
44fi
45
46cache="$(curl -v -X "POST" "$link_to_api" --data "wrong" 2>&1 | grep "error")"
47if [ "" == "$cache" ]
48then
49 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong data POST request\n"
50else
51 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong data POST request\n"
52fi
53
54cache="$(curl -v -X "POST" "$link_to_api" --data "[{}]" 2>&1 | grep "error")"
55if [ "" == "$cache" ]
56then
57 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for json array input POST request\n"
58else
59 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for json array input POST request\n"
60fi
61
62cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":\"Test\",\"other\":\"Test\"}" 2>&1 | grep "error")"
63if [ "" == "$cache" ]
64then
65 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for multi element json POST request\n"
66else
67 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for multi element json POST request\n"
68fi
69
70cache="$(curl -v -X "POST" "$link_to_api" --data "{\"nam\":\"Test\"}" 2>&1 | grep "error")"
71if [ "" == "$cache" ]
72then
73 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong json POST request\n"
74else
75 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong json POST request\n"
76fi
77
78cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":123}" 2>&1 | grep "error")"
79if [ "" == "$cache" ]
80then
81 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong json type POST request\n"
82else
83 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong json type POST request\n"
84fi
85
86cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":""}" 2>&1 | grep "error")"
87if [ "" == "$cache" ]
88then
89 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for no name POST request\n"
90else
91 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for no name POST request\n"
92fi
93
94
95#Test GET (multiple identities) for success and error json
96cache="$(curl --silent "$link_to_api" | grep "error")"
97if [ "" == "$cache" ]
98then
99 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Success for good GET request (multiple identities)\n"
100else
101 echo -n -e "[\033[0;31m FAILURE\033[0m ] Error for good GET request (multiple identities)\n"
102fi
103
104
105id="$(gnunet-identity -d | grep "Test - " | sed "s/Test - //g")"
106#Test GET (one identity) for success and error json
107cache="$(curl --silent "${link_to_api}/$id" | grep "error")"
108if [ "" == "$cache" ]
109then
110 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Success for good GET request (one identity)\n"
111else
112 echo -n -e "[\033[0;31m FAILURE\033[0m ] Error for good GET request (one identity)\n"
113fi
114
115
116#Test DELETE success code, error response code and error json
117echo "Next tests for DELETE will probably fail when POST fails"
118cache="$(curl -v -X "DELETE" "${link_to_api}/$id" 2>&1 | grep "HTTP/1.1 404")"
119if [ "" == "$cache" ]
120then
121 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Success for good DELETE request\n"
122else
123 echo -n -e "[\033[0;31m FAILURE\033[0m ] Error for good DELETE request\n"
124fi
125
126curl --silent -X "POST" "$link_to_api" --data "{\"name\":\"Test\"}"
127id="$(gnunet-identity -d | grep "Test - " | sed "s/Test - //g")"
128
129cache="$(curl -v -X "DELETE" "${link_to_api}/df1" 2>&1 | grep "HTTP/1.1 404")"
130if [ "" == "$cache" ]
131then
132 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong DELETE request\n"
133else
134 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong DELETE request\n"
135fi
136
137#Test PUT success code, error response codes and error json
138cache="$(curl -v -X "PUT" "${link_to_api}/$id" --data "{\"newname\":\"NewTest\"}" 2>&1 | grep "HTTP/1.1 204")"
139if [ "" == "$cache" ]
140then
141 echo -n -e "[\033[0;31m FAILURE\033[0m ] Error for good PUT request\n"
142else
143 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Success for good PUT request\n"
144fi
145
146cache="$(curl -v -X "PUT" "${link_to_api}/${id}1" --data "{\"newname\":\"NewNewTest\"}" 2>&1 | grep "HTTP/1.1 404")"
147if [ "" == "$cache" ]
148then
149 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong identity PUT request\n"
150else
151 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong identity PUT request\n"
152fi
153
154cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "{\"newname\":\"NewTest\"}" 2>&1 | grep "error")"
155if [ "" == "$cache" ]
156then
157 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for duplicate name PUT request\n"
158else
159 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for duplicate name PUT request\n"
160fi
161
162cache="$(curl -v -X "PUT" "$link_to_api/$id" 2>&1 | grep "error")"
163if [ "" == "$cache" ]
164then
165 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for no data PUT request\n"
166else
167 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for no data PUT request\n"
168fi
169
170cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "wrong" 2>&1 | grep "error")"
171if [ "" == "$cache" ]
172then
173 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong data PUT request\n"
174else
175 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong data PUT request\n"
176fi
177
178cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "[{}]" 2>&1 | grep "error")"
179if [ "" == "$cache" ]
180then
181 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for json array input PUT request\n"
182else
183 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for json array input PUT request\n"
184fi
185
186cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "{\"newname\":\"Test\",\"other\":\"Test\"}" 2>&1 | grep "error")"
187if [ "" == "$cache" ]
188then
189 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for multi element json PUT request\n"
190else
191 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for multi element json PUT request\n"
192fi
193
194cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "{\"newnam\":\"Test\"}" 2>&1 | grep "error")"
195if [ "" == "$cache" ]
196then
197 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong json PUT request\n"
198else
199 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong json PUT request\n"
200fi
201
202cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "{\"newname\":123}" 2>&1 | grep "error")"
203if [ "" == "$cache" ]
204then
205 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong json type PUT request\n"
206else
207 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong json type PUT request\n"
208fi
209
210cache="$(curl -v -X "PUT" "$link_to_api/$id" --data "{\"newname\":""}" 2>&1 | grep "error")"
211if [ "" == "$cache" ]
212then
213 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for no name PUT request\n"
214else
215 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for no name PUT request\n"
216fi
217#TODO Missing subsystem test
218
219#Missing OPTIONS success - nothing can really go wrong here
220
221#Test wrong url
222cache="$(curl -v "$wrong_link" 2>&1 | grep "HTTP/1.1 404")"
223if [ "" == "$cache" ]
224then
225 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong url GET request \n"
226else
227 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong url GET request \n"
228fi
229
230cache="$(curl -X "PUT" -v "$wrong_link/$id" --data "{\"newname\":\"Testing\"}" 2>&1 | grep "HTTP/1.1 404")"
231if [ "" == "$cache" ]
232then
233 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong url GET request \n"
234else
235 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong url GET request \n"
236fi
237
238cache="$(curl -X "POST" -v "$wrong_link/$id" --data "{\"name\":\"Test\"}" 2>&1 | grep "HTTP/1.1 404")"
239if [ "" == "$cache" ]
240then
241 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong url POST request \n"
242else
243 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong url POST request \n"
244fi
245
246cache="$(curl -X "DELETE" -v "${wrong_link}/$id" 2>&1 | grep "HTTP/1.1 404")"
247if [ "" == "$cache" ]
248then
249 echo -n -e "[\033[0;31m FAILURE\033[0m ] Success for wrong url DELETE request \n"
250else
251 echo -n -e "[\033[0;32m SUCCESS\033[0m ] Error for wrong url DELETE request \n"
252fi
diff --git a/src/identity/test_plugin_rest_identity.sh b/src/identity/test_plugin_rest_identity.sh
new file mode 100755
index 000000000..b48becc45
--- /dev/null
+++ b/src/identity/test_plugin_rest_identity.sh
@@ -0,0 +1,216 @@
1#!/usr/bin/bash
2
3#First, start gnunet-arm and the rest-service. Make sure, no identity exists
4#Exit 0 means success, exit 1 means failed test
5
6#No test for subsystem available
7
8link_to_api="http://localhost:7776/identity"
9wrong_link="http://localhost:7776/idenmmmy"
10wrong_link2="http://localhost:7776/identityandmore"
11
12#Test GET (multiple identities) for error when no identity exists
13#The next test case can be ignored if you have already added identities
14cache="$(curl --silent "$link_to_api" | grep "error")"
15if [ "" == "$cache" ]
16then
17 exit 1
18fi
19
20#Test POST success code, error response code and error json
21#The next test case can be ignored if you have already added an identity with the name Test
22cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":\"Test\"}" 2>&1 | grep "HTTP/1.1 201")"
23if [ "" == "$cache" ]
24then
25 exit 1
26fi
27
28cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":\"Test\"}" 2>&1 | grep "HTTP/1.1 409")"
29if [ "" == "$cache" ]
30then
31 exit 1
32fi
33
34cache="$(curl -v -X "POST" "$link_to_api" 2>&1 | grep "error")"
35if [ "" == "$cache" ]
36then
37 exit 1
38fi
39
40cache="$(curl -v -X "POST" "$link_to_api" --data "wrong" 2>&1 | grep "error")"
41if [ "" == "$cache" ]
42then
43 exit 1
44fi
45
46cache="$(curl -v -X "POST" "$link_to_api" --data "[{}]" 2>&1 | grep "error")"
47if [ "" == "$cache" ]
48then
49 exit 1
50fi
51
52cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":\"Test\",\"other\":\"Test\"}" 2>&1 | grep "error")"
53if [ "" == "$cache" ]
54then
55 exit 1
56fi
57
58cache="$(curl -v -X "POST" "$link_to_api" --data "{\"nam\":\"Test\"}" 2>&1 | grep "error")"
59if [ "" == "$cache" ]
60then
61 exit 1
62fi
63
64cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":123}" 2>&1 | grep "error")"
65if [ "" == "$cache" ]
66then
67 exit 1
68fi
69
70cache="$(curl -v -X "POST" "$link_to_api" --data "{\"name\":""}" 2>&1 | grep "error")"
71if [ "" == "$cache" ]
72then
73 exit 1
74fi
75
76
77#Test GET (multiple identities) for success and error json
78cache="$(curl --silent "$link_to_api" | grep "error")"
79if [ "" != "$cache" ]
80then
81 exit 1
82fi
83
84
85id="$(gnunet-identity -d | grep "Test - " | sed "s/Test - //g")"
86#Test GET (one identity) for success and error json
87cache="$(curl --silent "${link_to_api}?pubkey=$id" | grep "error")"
88if [ "" != "$cache" ]
89then
90 exit 1
91fi
92
93
94#Test DELETE success code, error response code and error json
95#echo "Next tests for DELETE will probably fail when POST fails"
96cache="$(curl -v -X "DELETE" "${link_to_api}?pubkey=$id" 2>&1 | grep "HTTP/1.1 404")"
97if [ "" != "$cache" ]
98then
99 exit 1
100fi
101
102curl --silent -X "POST" "$link_to_api" --data "{\"name\":\"Test\"}"
103id="$(gnunet-identity -d | grep "Test - " | sed "s/Test - //g")"
104
105cache="$(curl -v -X "DELETE" "${link_to_api}?pubkey=df1" 2>&1 | grep "HTTP/1.1 404")"
106if [ "" == "$cache" ]
107then
108 exit 1
109fi
110
111cache="$(curl -v -X "DELETE" "${link_to_api}?pubke=$id" 2>&1 | grep "error")"
112if [ "" == "$cache" ]
113then
114 exit 1
115fi
116
117#Test PUT success code, error response codes and error json
118cache="$(curl -v -X "PUT" "${link_to_api}" --data "{\"newname\":\"NewTest\",\"pubkey\":\"${id}\"}" 2>&1 | grep "HTTP/1.1 204")"
119if [ "" == "$cache" ]
120then
121 exit 1
122fi
123
124cache="$(curl -v -X "PUT" "${link_to_api}" --data "{\"newname\":\"NewNewTest\",\"pubkey\":\"${id}1\"}" 2>&1 | grep "HTTP/1.1 404")"
125if [ "" == "$cache" ]
126then
127 exit 1
128fi
129
130# feature: you can rename your identity with its own name.
131# cache="$(curl -v -X "PUT" "$link_to_api" --data "{\"newname\":\"NewTest\",\"pubkey\":\"${id}\"}" 2>&1 | grep "error")"
132# if [ "" == "$cache" ]
133# then
134# exit 1
135# fi
136
137
138cache="$(curl -v -X "PUT" "$link_to_api" 2>&1 | grep "error")"
139if [ "" == "$cache" ]
140then
141 exit 1
142fi
143
144cache="$(curl -v -X "PUT" "$link_to_api" --data "wrong" 2>&1 | grep "error")"
145if [ "" == "$cache" ]
146then
147 exit 1
148fi
149
150cache="$(curl -v -X "PUT" "$link_to_api" --data "[{}]" 2>&1 | grep "error")"
151if [ "" == "$cache" ]
152then
153 exit 1
154fi
155
156cache="$(curl -v -X "PUT" "$link_to_api" --data "{\"newname\":\"Test\",\"other\":\"Test\",\"pubkey\":\"${id}\"}" 2>&1 | grep "error")"
157if [ "" == "$cache" ]
158then
159 exit 1
160fi
161
162cache="$(curl -v -X "PUT" "$link_to_api" --data "{\"newnam\":\"Test\",\"pubkey\":\"${id}\"}" 2>&1 | grep "error")"
163if [ "" == "$cache" ]
164then
165 exit 1
166fi
167
168cache="$(curl -v -X "PUT" "$link_to_api" --data "{\"newname\":\"Test\",\"pubke\":\"${id}\"}" 2>&1 | grep "error")"
169if [ "" == "$cache" ]
170then
171 exit 1
172fi
173
174cache="$(curl -v -X "PUT" "$link_to_api" --data "{\"newname\":123,\"pubkey\":\"${id}\"}" 2>&1 | grep "error")"
175if [ "" == "$cache" ]
176then
177 exit 1
178fi
179
180cache="$(curl -v -X "PUT" "$link_to_api" --data "{\"newname\":"",\"pubkey\":\"${id}\"}" 2>&1 | grep "error")"
181if [ "" == "$cache" ]
182then
183 exit 1
184fi
185#TODO Missing subsystem test
186
187#Missing OPTIONS success - nothing can really go wrong here
188
189#Test wrong url
190cache="$(curl -v "$wrong_link" 2>&1 | grep "HTTP/1.1 404")"
191if [ "" == "$cache" ]
192then
193 exit 1
194fi
195
196cache="$(curl -X "PUT" -v "$wrong_link" --data "{\"newname\":\"Testing\",\"pubkey\":\"${id}\"}" 2>&1 | grep "HTTP/1.1 404")"
197if [ "" == "$cache" ]
198then
199 exit 1
200fi
201
202cache="$(curl -X "POST" -v "$wrong_link?pubkey=$id" --data "{\"name\":\"Test\"}" 2>&1 | grep "HTTP/1.1 404")"
203if [ "" == "$cache" ]
204then
205 exit 1
206fi
207
208cache="$(curl -X "DELETE" -v "${wrong_link}?pubkey=$id" 2>&1 | grep "HTTP/1.1 404")"
209if [ "" == "$cache" ]
210then
211 exit 1
212fi
213
214gnunet-identity -D NewTest
215
216exit 0