REST/NAMESTORE: rework API
authorSchanzenbach, Martin <mschanzenbach@posteo.de>
Tue, 30 Apr 2019 13:56:16 +0000 (15:56 +0200)
committerSchanzenbach, Martin <mschanzenbach@posteo.de>
Tue, 30 Apr 2019 13:56:16 +0000 (15:56 +0200)
src/include/gnunet_json_lib.h
src/json/json_generator.c
src/json/json_gnsrecord.c
src/namestore/plugin_rest_namestore.c

index 640ffa35a66ce6a6d70e61d80b7b66ce5e07c6d3..c8f09d4e4de1b333b82f896266907826b8b4e8c6 100644 (file)
@@ -11,7 +11,7 @@
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Affero General Public License for more details.
+
   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
@@ -329,7 +329,9 @@ GNUNET_JSON_spec_rsa_signature (const char *name,
  * @return JSON Specification
  */
 struct GNUNET_JSON_Specification
-GNUNET_JSON_spec_gnsrecord_data (struct GNUNET_GNSRECORD_Data **gnsrecord_object);
+GNUNET_JSON_spec_gnsrecord (struct GNUNET_GNSRECORD_Data **rd,
+                            unsigned int *rd_count,
+                            char **name);
 
 
 /* ****************** Generic generator interface ******************* */
@@ -415,8 +417,9 @@ GNUNET_JSON_from_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *sig);
  * @return corresponding JSON encoding
  */
 json_t *
-GNUNET_JSON_from_gns_record (const char* rname,
-                               const struct GNUNET_GNSRECORD_Data *rd);
+GNUNET_JSON_from_gnsrecord (const char* rname,
+                            const struct GNUNET_GNSRECORD_Data *rd,
+                            unsigned int rd_count);
 
 /* ******************* Helpers for MHD upload handling ******************* */
 
index 0b25013e34ed06471737ab3278337b88db513928..de6898da6e194e35f4c66e6f8dc66a85a3462989 100644 (file)
@@ -11,7 +11,7 @@
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Affero General Public License for more details.
+
   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
@@ -160,58 +160,56 @@ GNUNET_JSON_from_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *sig)
 }
 
 /**
- * Convert Gns record to JSON.
+ * Convert GNS record to JSON.
  *
  * @param rname name of record
  * @param rd record data
  * @return corresponding JSON encoding
  */
 json_t *
-GNUNET_JSON_from_gns_record (const char* rname,
-                            const struct GNUNET_GNSRECORD_Data *rd)
+GNUNET_JSON_from_gnsrecord (const char* rname,
+                            const struct GNUNET_GNSRECORD_Data *rd,
+                            unsigned int rd_count)
 {
   struct GNUNET_TIME_Absolute expiration_time;
   const char *expiration_time_str;
   const char *record_type_str;
   char *value_str;
-  json_t *ret;
-  int flags;
-
-  value_str = GNUNET_GNSRECORD_value_to_string(rd->record_type,rd->data,rd->data_size);
-  expiration_time = GNUNET_GNSRECORD_record_get_expiration_time(1, rd);
-  expiration_time_str = GNUNET_STRINGS_absolute_time_to_string(expiration_time);
-  flags = (int)rd->flags; //maybe necessary
-  record_type_str = GNUNET_GNSRECORD_number_to_typename(rd->record_type);
-
-  // ? for possible NULL values
-  if (NULL != rname)
+  json_t *data;
+  json_t *record;
+  json_t *records;
+
+  data = json_object ();
+  json_object_set_new (data,
+                       "record_name",
+                       json_string (rname));
+  records = json_array ();
+  for (int i = 0; i < rd_count; i++)
   {
-    ret = json_pack ("{s:s?,s:s?,s:s?,s:i,s:s?}",
-                    "value",
-                    value_str,
-                    "record_type",
-                    record_type_str,
-                    "expiration_time",
-                    expiration_time_str,
-                    "flag",
-                    flags,
-                    "record_name",
-                    rname);
+    value_str = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
+                                                  rd[i].data,
+                                                  rd[i].data_size);
+    expiration_time = GNUNET_GNSRECORD_record_get_expiration_time(1, &rd[i]);
+    expiration_time_str = GNUNET_STRINGS_absolute_time_to_string (expiration_time);
+    record_type_str = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Packing %s %s %s %d\n",
+                value_str, record_type_str, expiration_time_str, rd[i].flags);
+    record = json_pack ("{s:s,s:s,s:s,s:i}",
+                        "value",
+                        value_str,
+                        "record_type",
+                        record_type_str,
+                        "expiration_time",
+                        expiration_time_str,
+                        "flag",
+                        rd[i].flags);
+    GNUNET_assert (NULL != record);
+    GNUNET_free (value_str);
+    json_array_append_new (records, record);
   }
-  else
-  {
-    ret = json_pack ("{s:s?,s:s?,s:s?,s:i}",
-                    "value",
-                    value_str,
-                    "record_type",
-                    record_type_str,
-                    "expiration_time",
-                    expiration_time_str,
-                    "flag",
-                    flags);
-  }
-  GNUNET_free_non_null(value_str);
-  return ret;
+  json_object_set_new (data, "data", records);
+  return data;
 }
 
 
index cbdc0ff91a0a879fcac978e0e0cc2c4603c83e61..eef9e0e79afd3e5fd2938bc14cd65fd089963326 100644 (file)
 #include "gnunet_json_lib.h"
 
 #define GNUNET_JSON_GNSRECORD_VALUE "value"
+#define GNUNET_JSON_GNSRECORD_RECORD_DATA "data"
 #define GNUNET_JSON_GNSRECORD_TYPE "record_type"
 #define GNUNET_JSON_GNSRECORD_EXPIRATION_TIME "expiration_time"
 #define GNUNET_JSON_GNSRECORD_FLAG "flag"
 #define GNUNET_JSON_GNSRECORD_RECORD_NAME "record_name"
 #define GNUNET_JSON_GNSRECORD_NEVER "never"
 
+struct GnsRecordInfo
+{
+  char **name;
+
+  unsigned int *rd_count;
+
+  struct GNUNET_GNSRECORD_Data **rd;
+};
+
+
+static void
+cleanup_recordinfo (struct GnsRecordInfo *gnsrecord_info)
+{
+  if (NULL != gnsrecord_info)
+  {
+    if (NULL != *(gnsrecord_info->rd))
+    {
+      for (int i = 0; i < *(gnsrecord_info->rd_count); i++)
+      {
+        if (NULL != (*(gnsrecord_info->rd))[i].data)
+          GNUNET_free ((char *) (*(gnsrecord_info->rd))[i].data);
+      }
+      GNUNET_free (*(gnsrecord_info->rd));
+      *(gnsrecord_info->rd) = NULL;
+    }
+    if (NULL != *(gnsrecord_info->name))
+      GNUNET_free (*(gnsrecord_info->name));
+    *(gnsrecord_info->name) = NULL;
+    GNUNET_free (gnsrecord_info);
+  }
+
+}
+
 
 /**
  * Parse given JSON object to gns record
  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
  */
 static int
-parse_gnsrecordobject (void *cls,
-                       json_t *root,
-                       struct GNUNET_JSON_Specification *spec)
+parse_record (json_t *data, struct GNUNET_GNSRECORD_Data *rd)
 {
-  struct GNUNET_GNSRECORD_Data *gnsrecord_object;
   struct GNUNET_TIME_Absolute abs_expiration_time;
   struct GNUNET_TIME_Relative rel_expiration_time;
-  int unpack_state=0;
   const char *value;
-  const char *expiration_time;
   const char *record_type;
-  const char *name;
+  const char *expiration_time;
   int flag;
-  void *rdata = NULL;
-  size_t rdata_size;
+  int unpack_state = 0;
 
-  GNUNET_assert(NULL != root);
-  if(!json_is_object(root))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Error json is not array nor object!\n");
-    return GNUNET_SYSERR;
-  }
   //interpret single gns record
-  unpack_state = json_unpack(root,
-                             "{s:s, s:s, s:s, s?:i, s:s!}",
-                             GNUNET_JSON_GNSRECORD_VALUE, &value,
-                             GNUNET_JSON_GNSRECORD_TYPE, &record_type,
-                             GNUNET_JSON_GNSRECORD_EXPIRATION_TIME, &expiration_time,
-                             GNUNET_JSON_GNSRECORD_FLAG, &flag,
-                             GNUNET_JSON_GNSRECORD_RECORD_NAME, &name);
+  unpack_state = json_unpack (data,
+                              "{s:s, s:s, s:s, s?:i!}",
+                              GNUNET_JSON_GNSRECORD_VALUE,
+                              &value,
+                              GNUNET_JSON_GNSRECORD_TYPE,
+                              &record_type,
+                              GNUNET_JSON_GNSRECORD_EXPIRATION_TIME,
+                              &expiration_time,
+                              GNUNET_JSON_GNSRECORD_FLAG,
+                              &flag);
   if (0 != unpack_state)
   {
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
-               "Error json object has a wrong format!\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Error gnsdata object has a wrong format!\n");
     return GNUNET_SYSERR;
   }
-  gnsrecord_object = GNUNET_new (struct GNUNET_GNSRECORD_Data);
-  gnsrecord_object->record_type = GNUNET_GNSRECORD_typename_to_number(record_type);
-  if (UINT32_MAX == gnsrecord_object->record_type)
+  rd->record_type = GNUNET_GNSRECORD_typename_to_number (record_type);
+  if (UINT32_MAX == rd->record_type)
   {
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,"Unsupported type\n");
-    GNUNET_free(gnsrecord_object);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Unsupported type\n");
     return GNUNET_SYSERR;
   }
-  if (GNUNET_OK
-      != GNUNET_GNSRECORD_string_to_value (gnsrecord_object->record_type,
-                                           value,
-                                           &rdata,
-                                           &rdata_size))
+  if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (rd->record_type,
+                                                     value,
+                                                     (void**)&rd->data,
+                                                     &rd->data_size))
   {
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,"Value invalid for record type\n");
-    GNUNET_free(gnsrecord_object);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Value invalid for record type\n");
     return GNUNET_SYSERR;
   }
 
-  gnsrecord_object->data = rdata;
-  gnsrecord_object->data_size = rdata_size;
-
   if (0 == strcmp (expiration_time, GNUNET_JSON_GNSRECORD_NEVER))
   {
-    gnsrecord_object->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
+    rd->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
   }
-  else if (GNUNET_OK
-           == GNUNET_STRINGS_fancy_time_to_absolute (expiration_time,
-                                                     &abs_expiration_time))
+  else if (GNUNET_OK ==
+           GNUNET_STRINGS_fancy_time_to_absolute (expiration_time,
+                                                  &abs_expiration_time))
   {
-    gnsrecord_object->expiration_time = abs_expiration_time.abs_value_us;
+    rd->expiration_time = abs_expiration_time.abs_value_us;
   }
-  else if (GNUNET_OK
-           == GNUNET_STRINGS_fancy_time_to_relative (expiration_time,
-                                                     &rel_expiration_time))
+  else if (GNUNET_OK ==
+           GNUNET_STRINGS_fancy_time_to_relative (expiration_time,
+                                                  &rel_expiration_time))
   {
-    gnsrecord_object->expiration_time = rel_expiration_time.rel_value_us;
+    rd->expiration_time = rel_expiration_time.rel_value_us;
   }
   else
   {
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Expiration time invalid\n");
-    GNUNET_free_non_null(rdata);
-    GNUNET_free(gnsrecord_object);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Expiration time invalid\n");
     return GNUNET_SYSERR;
   }
-  gnsrecord_object->flags = (enum GNUNET_GNSRECORD_Flags)flag;
-  *(struct GNUNET_GNSRECORD_Data **) spec->ptr = gnsrecord_object;
+  rd->flags = (enum GNUNET_GNSRECORD_Flags) flag;
   return GNUNET_OK;
 }
 
+
 /**
- * Cleanup data left from parsing RSA public key.
+ * Parse given JSON object to gns record
  *
  * @param cls closure, NULL
- * @param[out] spec where to free the data
+ * @param root the json object representing data
+ * @param spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
  */
-static void
-clean_gnsrecordobject (void *cls, struct GNUNET_JSON_Specification *spec)
+static int
+parse_record_data (struct GnsRecordInfo *gnsrecord_info, json_t *data)
 {
-  struct GNUNET_GNSRECORD_Data **gnsrecord_object;
-  gnsrecord_object = (struct GNUNET_GNSRECORD_Data **) spec->ptr;
-  if (NULL != *gnsrecord_object)
+  GNUNET_assert (NULL != data);
+  if (! json_is_array (data))
   {
-    if (NULL != (*gnsrecord_object)->data)
-      GNUNET_free((char*)(*gnsrecord_object)->data);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Error gns record data JSON is not an array!\n");
+    return GNUNET_SYSERR;
+  }
+  *(gnsrecord_info->rd_count) = json_array_size (data);
+  *(gnsrecord_info->rd) = GNUNET_malloc (sizeof (struct GNUNET_GNSRECORD_Data) *
+                                         json_array_size (data));
+  size_t index;
+  json_t *value;
+  json_array_foreach (data, index, value)
+  {
+    if (GNUNET_OK != parse_record (value, &(*(gnsrecord_info->rd))[index]))
+      return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
 
-    GNUNET_free(*gnsrecord_object);
-    *gnsrecord_object = NULL;
+
+static int
+parse_gnsrecordobject (void *cls,
+                       json_t *root,
+                       struct GNUNET_JSON_Specification *spec)
+{
+  struct GnsRecordInfo *gnsrecord_info;
+  int unpack_state = 0;
+  const char *name;
+  json_t *data;
+
+  GNUNET_assert (NULL != root);
+  if (! json_is_object (root))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Error record JSON is not an object!\n");
+    return GNUNET_SYSERR;
+  }
+  //interpret single gns record
+  unpack_state = json_unpack (root,
+                              "{s:s, s:o!}",
+                              GNUNET_JSON_GNSRECORD_RECORD_NAME,
+                              &name,
+                              GNUNET_JSON_GNSRECORD_RECORD_DATA,
+                              &data);
+  if (0 != unpack_state)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Error namestore records object has a wrong format!\n");
+    return GNUNET_SYSERR;
   }
+  gnsrecord_info = (struct GnsRecordInfo *) spec->ptr;
+  *(gnsrecord_info->name) = GNUNET_strdup (name);
+  return parse_record_data (gnsrecord_info, data);
 }
 
+
+/**
+ * Cleanup data left from parsing the record.
+ *
+ * @param cls closure, NULL
+ * @param[out] spec where to free the data
+ */
+static void
+clean_gnsrecordobject (void *cls, struct GNUNET_JSON_Specification *spec)
+{
+  struct GnsRecordInfo *gnsrecord_info = (struct GnsRecordInfo *) spec->ptr;
+  cleanup_recordinfo (gnsrecord_info);
+}
+
+
 /**
  * JSON Specification for GNS Records.
  *
@@ -159,17 +235,21 @@ clean_gnsrecordobject (void *cls, struct GNUNET_JSON_Specification *spec)
  * @return JSON Specification
  */
 struct GNUNET_JSON_Specification
-GNUNET_JSON_spec_gnsrecord_data (struct GNUNET_GNSRECORD_Data **gnsrecord_object)
+GNUNET_JSON_spec_gnsrecord (struct GNUNET_GNSRECORD_Data **rd,
+                            unsigned int *rd_count,
+                            char **name)
 {
-  struct GNUNET_JSON_Specification ret = {
-    .parser = &parse_gnsrecordobject,
-    .cleaner = &clean_gnsrecordobject,
-    .cls = NULL,
-    .field = NULL,
-    .ptr = gnsrecord_object,
-    .ptr_size = 0,
-    .size_ptr = NULL
-  };
-  *gnsrecord_object = NULL;
+  struct GnsRecordInfo *gnsrecord_info = GNUNET_new (struct GnsRecordInfo);
+  gnsrecord_info->rd = rd;
+  gnsrecord_info->name = name;
+  gnsrecord_info->rd_count = rd_count;
+  struct GNUNET_JSON_Specification ret = {.parser = &parse_gnsrecordobject,
+                                          .cleaner = &clean_gnsrecordobject,
+                                          .cls = NULL,
+                                          .field = NULL,
+                                          .ptr = (struct GnsRecordInfo *)
+                                            gnsrecord_info,
+                                          .ptr_size = 0,
+                                          .size_ptr = NULL};
   return ret;
 }
index 46e5a590fda8a1673b86c9d9e7f516a9d82802db..39b21c233ab79dba7c1032afa2ce4dabc171872f 100644 (file)
  */
 #define GNUNET_REST_IDENTITY_NOT_FOUND "No identity found"
 
-/**
- * Error message No default zone specified
- */
-#define GNUNET_REST_NAMESTORE_NO_DEFAULT_ZONE "No default zone specified"
 
 /**
  * Error message Failed request
@@ -142,6 +138,11 @@ struct RequestHandle
    */
   struct GNUNET_GNSRECORD_Data *rd;
 
+  /**
+   * Number of records in rd
+   */
+  unsigned int rd_count;
+
   /**
    * NAMESTORE Operation
    */
@@ -263,8 +264,11 @@ cleanup_handle (void *cls)
     GNUNET_free (handle->emsg);
   if (NULL != handle->rd)
   {
-    if (NULL != handle->rd->data)
-      GNUNET_free ((void *) handle->rd->data);
+    for (int i = 0; i < handle->rd_count; i++)
+    {
+      if (NULL != handle->rd[i].data)
+        GNUNET_free ((void *) handle->rd[i].data);
+    }
     GNUNET_free (handle->rd);
   }
   if (NULL != handle->timeout_task)
@@ -484,68 +488,13 @@ namestore_list_iteration (void *cls,
 
   if (NULL == handle->resp_object)
     handle->resp_object = json_array ();
-
-  for (unsigned int i = 0; i < rd_len; i++)
-  {
-    if ((GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) &&
-        (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT)))
-      continue;
-
-    record_obj = GNUNET_JSON_from_gns_record (rname, &rd[i]);
-
-    if (NULL == record_obj)
-      continue;
-
-    json_array_append (handle->resp_object, record_obj);
-    json_decref (record_obj);
-  }
-
+  record_obj = GNUNET_JSON_from_gnsrecord (rname,
+                                           rd,
+                                           rd_len);
+  json_array_append_new (handle->resp_object, record_obj);
   GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, 1);
 }
 
-/**
- * @param cls closure
- * @param ego ego handle
- * @param ctx context for application to store data for this ego
- *                 (during the lifetime of this process, initially NULL)
- * @param identifier identifier assigned by the user for this ego,
- *                   NULL if the user just deleted the ego and it
- *                   must thus no longer be used
- */
-static void
-default_ego_get (void *cls,
-                 struct GNUNET_IDENTITY_Ego *ego,
-                 void **ctx,
-                 const char *identifier)
-{
-  struct RequestHandle *handle = cls;
-  handle->op = NULL;
-
-  if (ego == NULL)
-  {
-    handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_NO_DEFAULT_ZONE);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
-
-  handle->list_it =
-    GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
-                                           handle->zone_pkey,
-                                           &namestore_iteration_error,
-                                           handle,
-                                           &namestore_list_iteration,
-                                           handle,
-                                           &namestore_list_finished,
-                                           handle);
-  if (NULL == handle->list_it)
-  {
-    handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-}
-
 
 /**
  * Handle namestore GET request
@@ -581,18 +530,8 @@ namestore_get (struct GNUNET_REST_RequestHandle *con_handle,
     }
   }
   if (NULL != ego_entry)
-  {
     handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-  }
 
-  if (NULL == handle->zone_pkey)
-  {
-    handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
-                                      "namestore",
-                                      &default_ego_get,
-                                      handle);
-    return;
-  }
   handle->list_it =
     GNUNET_NAMESTORE_zone_iteration_start (handle->ns_handle,
                                            handle->zone_pkey,
@@ -611,48 +550,6 @@ namestore_get (struct GNUNET_REST_RequestHandle *con_handle,
 }
 
 
-/**
- * @param cls closure
- * @param ego ego handle
- * @param ctx context for application to store data for this ego
- *                 (during the lifetime of this process, initially NULL)
- * @param identifier identifier assigned by the user for this ego,
- *                   NULL if the user just deleted the ego and it
- *                   must thus no longer be used
- */
-static void
-default_ego_post (void *cls,
-                  struct GNUNET_IDENTITY_Ego *ego,
-                  void **ctx,
-                  const char *identifier)
-{
-  struct RequestHandle *handle = cls;
-  handle->op = NULL;
-
-  if (ego == NULL)
-  {
-    handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_NO_DEFAULT_ZONE);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
-
-  handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
-                                                   handle->zone_pkey,
-                                                   handle->record_name,
-                                                   1,
-                                                   handle->rd,
-                                                   &create_finished,
-                                                   handle);
-  if (NULL == handle->add_qe)
-  {
-    handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-}
-
-
 static void
 ns_lookup_error_cb (void *cls)
 {
@@ -670,14 +567,15 @@ ns_lookup_cb (void *cls,
               const struct GNUNET_GNSRECORD_Data *rd)
 {
   struct RequestHandle *handle = cls;
-  struct GNUNET_GNSRECORD_Data rd_new[rd_count + 1];
+  struct GNUNET_GNSRECORD_Data rd_new[rd_count + handle->rd_count];
   for (int i = 0; i < rd_count; i++)
     rd_new[i] = rd[i];
-  rd_new[rd_count] = *handle->rd;
+  for (int j = 0; j < handle->rd_count; j++)
+    rd_new[rd_count + j] = handle->rd[j];
   handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
                                                    handle->zone_pkey,
                                                    handle->record_name,
-                                                   rd_count + 1,
+                                                   rd_count + handle->rd_count,
                                                    rd_new,
                                                    &create_finished,
                                                    handle);
@@ -703,16 +601,12 @@ namestore_add (struct GNUNET_REST_RequestHandle *con_handle,
                void *cls)
 {
   struct RequestHandle *handle = cls;
-  struct GNUNET_GNSRECORD_Data *gns_record;
   struct EgoEntry *ego_entry;
   char *egoname;
   json_t *data_js;
-  json_t *name_json;
   json_error_t err;
-  char term_data[handle->rest_handle->data_size + 1];
 
-  struct GNUNET_JSON_Specification gnsspec[] =
-    {GNUNET_JSON_spec_gnsrecord_data (&gns_record), GNUNET_JSON_spec_end ()};
+  char term_data[handle->rest_handle->data_size + 1];
 
   if (0 >= handle->rest_handle->data_size)
   {
@@ -725,26 +619,9 @@ namestore_add (struct GNUNET_REST_RequestHandle *con_handle,
                  handle->rest_handle->data,
                  handle->rest_handle->data_size);
   data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
+  struct GNUNET_JSON_Specification gnsspec[] =
+    {GNUNET_JSON_spec_gnsrecord (&handle->rd, &handle->rd_count, &handle->record_name), GNUNET_JSON_spec_end ()};
   if (GNUNET_OK != GNUNET_JSON_parse (data_js, gnsspec, NULL, NULL))
-  {
-    handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_INVALID_DATA);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    GNUNET_JSON_parse_free (gnsspec);
-    json_decref (data_js);
-    return;
-  }
-  handle->rd = gns_record;
-
-  name_json = json_object_get (data_js, "record_name");
-  if (! json_is_string (name_json))
-  {
-    handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_INVALID_DATA);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    json_decref (data_js);
-    return;
-  }
-  handle->record_name = GNUNET_strdup (json_string_value (name_json));
-  if (NULL == handle->record_name)
   {
     handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_INVALID_DATA);
     GNUNET_SCHEDULER_add_now (&do_error, handle);
@@ -778,17 +655,7 @@ namestore_add (struct GNUNET_REST_RequestHandle *con_handle,
     }
   }
   if (NULL != ego_entry)
-  {
     handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-  }
-  if (NULL == handle->zone_pkey)
-  {
-    handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
-                                      "namestore",
-                                      &default_ego_post,
-                                      handle);
-    return;
-  }
   handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle,
                                                     handle->zone_pkey,
                                                     handle->record_name,
@@ -805,48 +672,6 @@ namestore_add (struct GNUNET_REST_RequestHandle *con_handle,
 }
 
 
-/**
- * @param cls closure
- * @param ego ego handle
- * @param ctx context for application to store data for this ego
- *                 (during the lifetime of this process, initially NULL)
- * @param identifier identifier assigned by the user for this ego,
- *                   NULL if the user just deleted the ego and it
- *                   must thus no longer be used
- */
-static void
-default_ego_delete (void *cls,
-                    struct GNUNET_IDENTITY_Ego *ego,
-                    void **ctx,
-                    const char *identifier)
-{
-  struct RequestHandle *handle = cls;
-  handle->op = NULL;
-
-  if (ego == NULL)
-  {
-    handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_NO_DEFAULT_ZONE);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego);
-
-  handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
-                                                   handle->zone_pkey,
-                                                   handle->record_name,
-                                                   0,
-                                                   NULL,
-                                                   &del_finished,
-                                                   handle);
-  if (NULL == handle->add_qe)
-  {
-    handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-}
-
-
 /**
  * Handle namestore DELETE request
  *
@@ -882,9 +707,7 @@ namestore_delete (struct GNUNET_REST_RequestHandle *con_handle,
     }
   }
   if (NULL != ego_entry)
-  {
     handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
-  }
 
   GNUNET_CRYPTO_hash ("record_name", strlen ("record_name"), &key);
   if (GNUNET_NO ==
@@ -897,15 +720,6 @@ namestore_delete (struct GNUNET_REST_RequestHandle *con_handle,
   handle->record_name = GNUNET_strdup (
     GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map, &key));
 
-  if (NULL == handle->zone_pkey)
-  {
-    handle->op = GNUNET_IDENTITY_get (handle->identity_handle,
-                                      "namestore",
-                                      &default_ego_delete,
-                                      handle);
-    return;
-  }
-
   handle->add_qe = GNUNET_NAMESTORE_records_store (handle->ns_handle,
                                                    handle->zone_pkey,
                                                    handle->record_name,