allow empty/NULL context message
[oweals/gnunet.git] / src / jsonapi / jsonapi.c
index 7bc4c05e5d8ee161c68d0e07da9c183fb0ebcecd..53ff64694e386d4b0e4f6fd7c5712a5b7924b1b1 100644 (file)
  */
 #include "platform.h"
 #include "gnunet_json_lib.h"
-
-#define GNUNET_JSONAPI_JSONAPI_KEY_DATA "data"
-
-#define GNUNET_JSONAPI_JSONAPI_KEY_ID "id"
-
-#define GNUNET_JSONAPI_JSONAPI_KEY_TYPE "type"
-
-struct GNUNET_JSONAPI_Resource
-{
-  /**
-   * DLL
-   */
-  struct GNUNET_JSONAPI_Resource *next;
-
-  /**
-   * DLL
-   */
-  struct GNUNET_JSONAPI_Resource *prev;
-
-  /**
-   * Resource content
-   */
-  json_t *res_obj;
-};
-
-
-struct GNUNET_JSONAPI_Object
-{
-  /**
-   * DLL Resource
-   */
-  struct GNUNET_JSONAPI_Resource *res_list_head;
-
-  /**
-   * DLL Resource
-   */
-  struct GNUNET_JSONAPI_Resource *res_list_tail;
-
-  /**
-   * num resources
-   */
-  int res_count;
-};
-
+#include "gnunet_rest_lib.h"
 
 /**
- * JSON API
- */
-
-
-/**
- * Create a JSON API resource
- *
- * @param type the JSON API resource type
- * @param id the JSON API resource id
- * @return a new JSON API resource or NULL on error.
+ * TODO move this to jsonapi-utils
  */
-struct GNUNET_JSONAPI_Resource*
-GNUNET_JSONAPI_resource_new (const char *type, const char *id)
-{
-  struct GNUNET_JSONAPI_Resource *res;
-
-  if ( (NULL == type) || (0 == strlen (type)) )
-    return NULL;
-  if ( (NULL == id) || (0 == strlen (id)) )
-    return NULL;
-
-  res = GNUNET_new (struct GNUNET_JSONAPI_Resource);
-  res->prev = NULL;
-  res->next = NULL;
-
-  res->res_obj = json_object ();
-
-  json_object_set_new (res->res_obj, GNUNET_JSONAPI_JSONAPI_KEY_ID, json_string (id));
-  json_object_set_new (res->res_obj, GNUNET_JSONAPI_JSONAPI_KEY_TYPE, json_string (type));
-
-  return res;
-}
-
-
 
 /**
- * Add a JSON API attribute
+ * Check rest request for validity
  *
- * @param res the JSON resource
- * @param key the key for the attribute
- * @param json the json_t attribute to add
- * @return #GNUNET_OK if added successfully
- *         #GNUNET_SYSERR if not
+ * @param req handle to the request
+ * @return GNUNET_OK if valid
  */
 int
-GNUNET_JSONAPI_resource_add_attr (const struct GNUNET_JSONAPI_Resource *resource,
-                                       const char* key,
-                                       json_t *json)
+GNUNET_JSONAPI_check_request_acceptable (struct GNUNET_REST_RequestHandle *req)
 {
-  if ( (NULL == resource) ||
-       (NULL == key) ||
-       (NULL == json) )
-    return GNUNET_SYSERR;
-  json_object_set (resource->res_obj, key, json);
+  //TODO
   return GNUNET_OK;
 }
 
 /**
- * Read a JSON API attribute
+ * Check rest request for validity
  *
- * @param res the JSON resource
- * @param key the key for the attribute
- * @return the json_t object
+ * @param req handle to the request
+ * @return GNUNET_OK if valid
  */
-json_t*
-GNUNET_JSONAPI_resource_read_attr (const struct GNUNET_JSONAPI_Resource *resource,
-                                       const char* key)
-{
-  if ( (NULL == resource) ||
-       (NULL == key))
-    return NULL;
-  return json_object_get (resource->res_obj, key);
-}
-
 int
-check_resource_attr_str (const struct GNUNET_JSONAPI_Resource *resource,
-                         const char* key,
-                         const char* attr)
+GNUNET_JSONAPI_check_request_supported (struct GNUNET_REST_RequestHandle *req)
 {
-  json_t *value;
-  if ( (NULL == resource) ||
-       (NULL == key) ||
-       (NULL == attr))
-    return GNUNET_NO;
-  value = json_object_get (resource->res_obj, key);
-  if (NULL == value)
-    return GNUNET_NO;
-  if (!json_is_string (value) ||
-      (0 != strcmp (attr, json_string_value(value))))
-  {
-    return GNUNET_NO;
-  }
-  return GNUNET_YES;
-}
-
-/**
- * Check a JSON API resource id
- *
- * @param res the JSON resource
- * @param id the expected id
- * @return GNUNET_YES if id matches
- */
-int
-GNUNET_JSONAPI_resource_check_id (const struct GNUNET_JSONAPI_Resource *resource,
-                                       const char* id)
-{
-  return check_resource_attr_str (resource, GNUNET_JSONAPI_JSONAPI_KEY_ID, id);
-}
-
-/**
- * Check a JSON API resource id
- *
- * @param res the JSON resource
- * @return the resource id
- */
-json_t*
-GNUNET_JSONAPI_resource_get_id (const struct GNUNET_JSONAPI_Resource *resource)
-{
-  return GNUNET_JSONAPI_resource_read_attr (resource, GNUNET_JSONAPI_JSONAPI_KEY_ID);
-}
-
-/**
- * Check a JSON API resource type
- *
- * @param res the JSON resource
- * @param type the expected type
- * @return GNUNET_YES if id matches
- */
-int
-GNUNET_JSONAPI_resource_check_type (const struct GNUNET_JSONAPI_Resource *resource,
-                                         const char* type)
-{
-  return check_resource_attr_str (resource, GNUNET_JSONAPI_JSONAPI_KEY_TYPE, type);
+  //TODO
+  return GNUNET_OK;
 }
 
 /**
- * Get a JSON API object resource count
+ * Handle jsonapi rest request. Checks request headers for jsonapi compliance
  *
- * @param resp the JSON API object
- * @return the number of resources
+ * @param req rest request handle
+ * @param handler rest request handlers
+ * @param cls closure
+ * @return GNUNET_OK if successful
  */
 int
-GNUNET_JSONAPI_object_resource_count (struct GNUNET_JSONAPI_Object *resp)
-{
-  return resp->res_count;
-}
-
-/**
- * Get a JSON API object resource by index
- *
- * @param resp the JSON API object
- * @param num the number of the resource
- * @return the resource
- */
-struct GNUNET_JSONAPI_Resource*
-GNUNET_JSONAPI_object_get_resource (struct GNUNET_JSONAPI_Object *resp,
-                                        int num)
-{
-  struct GNUNET_JSONAPI_Resource *res;
-  int i;
-
-  if ((0 == resp->res_count) ||
-      (num >= resp->res_count))
-    return NULL;
-  res = resp->res_list_head;
-  for (i = 0; i < num; i++)
-  {
-    res = res->next;
-  }
-  return res;
-}
-
-/**
- * Delete a JSON API resource
- *
- * @param res the JSON resource
- * @param result Pointer where the resource should be stored
- */
-void
-GNUNET_JSONAPI_resource_delete (struct GNUNET_JSONAPI_Resource *resource)
-{
-  json_decref (resource->res_obj);
-  GNUNET_free (resource);
-  resource = NULL;
-}
-
-/**
- * Delete a JSON API primary data
- *
- * @param type the JSON API resource type
- * @param id the JSON API resource id
- * @return a new JSON API resource or NULL on error.
- */
-void
-GNUNET_JSONAPI_object_delete (struct GNUNET_JSONAPI_Object *resp)
-{
-  struct GNUNET_JSONAPI_Resource *res;
-  struct GNUNET_JSONAPI_Resource *res_next;
-
-  for (res = resp->res_list_head;
-       res != NULL;)
-  {
-    res_next = res->next;
-    GNUNET_CONTAINER_DLL_remove (resp->res_list_head,
-                                 resp->res_list_tail,
-                                 res);
-    GNUNET_JSONAPI_resource_delete (res);
-    res = res_next;
-  }
-  GNUNET_free (resp);
-  resp = NULL;
-}
-
-/**
- * Create a JSON API primary data
- *
- * @return a new JSON API resource or NULL on error.
- */
-struct GNUNET_JSONAPI_Object*
-GNUNET_JSONAPI_jsonapi_object_new ()
-{
-  struct GNUNET_JSONAPI_Object *result;
-
-  result = GNUNET_new (struct GNUNET_JSONAPI_Object);
-  result->res_count = 0;
-  return result;
-}
-
-/**
- * Add a JSON API object to primary data
- *
- * @param data The JSON API data to add to
- * @param res the JSON API resource to add
- * @return the new number of resources
- */
-void
-GNUNET_JSONAPI_object_resource_add (struct GNUNET_JSONAPI_Object *resp,
-                                         struct GNUNET_JSONAPI_Resource *res)
-{
-  GNUNET_CONTAINER_DLL_insert (resp->res_list_head,
-                               resp->res_list_tail,
-                               res);
-
-  resp->res_count++;
-}
-
-static void
-add_json_resource (struct GNUNET_JSONAPI_Object *obj,
-                   const json_t *res_json)
-{
-  struct GNUNET_JSONAPI_Resource *res;
-  const char *type_json;
-
-  struct GNUNET_JSON_Specification dspec[] = {
-    GNUNET_JSON_spec_string (GNUNET_JSONAPI_JSONAPI_KEY_TYPE, &type_json),
-    GNUNET_JSON_spec_end()
-  };
-
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_JSON_parse (res_json, dspec,
-                                    NULL, NULL));
-  GNUNET_JSON_parse_free (dspec);
-  res = GNUNET_new (struct GNUNET_JSONAPI_Resource);
-  res->next = NULL;
-  res->prev = NULL;
-  res->res_obj = json_deep_copy (res_json);
-  GNUNET_JSONAPI_object_resource_add (obj, res);
-}
-
-/**
- * Parse given JSON object to RSA public key.
- *
- * @param cls closure, NULL
- * @param root the json object representing data
- * @param[out] spec where to write the data
- * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
- */
-static int
-parse_jsonapiobject (void *cls,
-                     json_t *root,
-                     struct GNUNET_JSON_Specification *spec)
+GNUNET_JSONAPI_handle_request (struct GNUNET_REST_RequestHandle *handle,
+                               const struct GNUNET_REST_RequestHandler *handlers,
+                               struct GNUNET_REST_RequestHandlerError *err,
+                               void *cls)
 {
-  struct GNUNET_JSONAPI_Object *result;
-  json_t *data_json;
-  int res_count = 0;
-  int i;
-
-  struct GNUNET_JSON_Specification jsonapispec[] = {
-    GNUNET_JSON_spec_json (GNUNET_JSONAPI_JSONAPI_KEY_DATA, &data_json),
-    GNUNET_JSON_spec_end()
-  };
-  if (GNUNET_OK !=
-                 GNUNET_JSON_parse (root, jsonapispec,
-                                    NULL, NULL) || (NULL == data_json))
+  if (GNUNET_OK != GNUNET_JSONAPI_check_request_acceptable (handle))
   {
+    err->error_code = MHD_HTTP_NOT_ACCEPTABLE;
     return GNUNET_SYSERR;
   }
-
-  result = GNUNET_new (struct GNUNET_JSONAPI_Object);
-  result->res_count = 0;
-  if (json_is_object (data_json))
-    add_json_resource (result, data_json);
-  else if (json_is_array (data_json))
-  {
-    res_count = json_array_size (data_json);
-    for (i = 0; i < res_count; i++)
-      add_json_resource (result, json_array_get (data_json, i));
-  }
-  if (0 == result->res_count)
+  if (GNUNET_OK != GNUNET_JSONAPI_check_request_supported (handle))
   {
-    GNUNET_free (result);
-    GNUNET_JSON_parse_free (jsonapispec);
+    err->error_code = MHD_HTTP_UNSUPPORTED_MEDIA_TYPE;
     return GNUNET_SYSERR;
   }
-  *(struct GNUNET_JSONAPI_Object **) spec->ptr = result;
-  GNUNET_JSON_parse_free (jsonapispec);
-  return GNUNET_OK;
-}
-
-
-/**
- * Cleanup data left from parsing RSA public key.
- *
- * @param cls closure, NULL
- * @param[out] spec where to free the data
- */
-static void
-clean_jsonapiobject (void *cls,
-                     struct GNUNET_JSON_Specification *spec)
-{
-  struct GNUNET_JSONAPI_Object **jsonapi_obj;
-  jsonapi_obj = (struct GNUNET_JSONAPI_Object **) spec->ptr;
-  if (NULL != *jsonapi_obj)
-  {
-    GNUNET_JSONAPI_object_delete (*jsonapi_obj);
-    *jsonapi_obj = NULL;
-  }
-}
-
-/**
- * Add a JSON API resource to primary data
- *
- * @param data The JSON API data to add to
- * @param res the JSON API resource to add
- * @return the new number of resources
- */
-void
-GNUNET_JSONAPI_data_resource_remove (struct GNUNET_JSONAPI_Object *resp,
-                                          struct GNUNET_JSONAPI_Resource *res)
-{
-  GNUNET_CONTAINER_DLL_remove (resp->res_list_head,
-                               resp->res_list_tail,
-                              res);
-  resp->res_count--;
-}
-
-/**
- * String serialze jsonapi primary data
- *
- * @param data the JSON API primary data
- * @param result where to store the result
- * @return GNUNET_SYSERR on error else GNUNET_OK
- */
-int
-GNUNET_JSONAPI_data_serialize (const struct GNUNET_JSONAPI_Object *resp,
-                                    char **result)
-{
-  struct GNUNET_JSONAPI_Resource *res;
-  json_t *root_json;
-  json_t *res_arr;
-
-  if ((NULL == resp))
-    return GNUNET_SYSERR;
-
-  root_json = json_object ();
-  res_arr = json_array ();
-  for (res = resp->res_list_head;
-       res != NULL;
-       res = res->next)
-  {
-    json_array_append (res_arr, res->res_obj);
-  }
-  json_object_set (root_json, GNUNET_JSONAPI_JSONAPI_KEY_DATA, res_arr);
-  *result = json_dumps (root_json, JSON_INDENT(2));
-  json_decref (root_json);
-  json_decref (res_arr);
-  return GNUNET_OK;
-}
-
-/**
- * JSON object.
- *
- * @param name name of the JSON field
- * @param[out] jsonp where to store the JSON found under @a name
- */
-struct GNUNET_JSON_Specification
-GNUNET_JSON_spec_jsonapi (struct GNUNET_JSONAPI_Object **jsonapi_object)
-{
-  struct GNUNET_JSON_Specification ret = {
-    .parser = &parse_jsonapiobject,
-    .cleaner = &clean_jsonapiobject,
-    .cls = NULL,
-    .field = NULL,
-    .ptr = jsonapi_object,
-    .ptr_size = 0,
-    .size_ptr = NULL
-  };
-  *jsonapi_object = NULL;
-  return ret;
+  return GNUNET_REST_handle_request (handle, handlers, err, cls);
 }