-fix json and namestore
[oweals/gnunet.git] / src / json / json_gnsrecord.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009-2013 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 /**
20  * @file json/json_gnsrecord.c
21  * @brief JSON handling of GNS record data
22  * @author Philippe Buschmann
23  */
24 #include "platform.h"
25 #include "gnunet_util_lib.h"
26 #include "gnunet_json_lib.h"
27
28 #define GNUNET_JSON_GNSRECORD_VALUE "value"
29 #define GNUNET_JSON_GNSRECORD_TYPE "type"
30 #define GNUNET_JSON_GNSRECORD_EXPIRATION_TIME "expiration_time"
31 #define GNUNET_JSON_GNSRECORD_FLAG "flag"
32 #define GNUNET_JSON_GNSRECORD_LABEL "label"
33 #define GNUNET_JSON_GNSRECORD_NEVER "never"
34
35
36 /**
37  * Parse given JSON object to gns record
38  *
39  * @param cls closure, NULL
40  * @param root the json object representing data
41  * @param spec where to write the data
42  * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
43  */
44 static int
45 parse_gnsrecordobject (void *cls,
46                        json_t *root,
47                        struct GNUNET_JSON_Specification *spec)
48 {
49   struct GNUNET_GNSRECORD_Data *gnsrecord_object;
50   struct GNUNET_TIME_Absolute abs_expiration_time;
51   int unpack_state=0;
52   const char *value;
53   const char *expiration_time;
54   const char *record_type;
55   const char *label;
56   int flag;
57   void *rdata;
58   size_t rdata_size;
59
60   GNUNET_assert(NULL != root);
61   if(!json_is_object(root))
62   {
63     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
64                 "Error json is not array nor object!\n");
65     return GNUNET_SYSERR;
66   }
67   //interpret single gns record
68   unpack_state = json_unpack(root,
69                              "{s:s, s:s, s:s, s?:i, s:s!}",
70                              GNUNET_JSON_GNSRECORD_VALUE, &value,
71                              GNUNET_JSON_GNSRECORD_TYPE, &record_type,
72                              GNUNET_JSON_GNSRECORD_EXPIRATION_TIME, &expiration_time,
73                              GNUNET_JSON_GNSRECORD_FLAG, &flag,
74                              GNUNET_JSON_GNSRECORD_LABEL, &label);
75   if (GNUNET_SYSERR == unpack_state)
76   {
77     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
78                "Error json object has a wrong format!\n");
79     return GNUNET_SYSERR;
80   }
81   gnsrecord_object = GNUNET_new (struct GNUNET_GNSRECORD_Data);
82   gnsrecord_object->record_type = GNUNET_GNSRECORD_typename_to_number(record_type);
83   if (UINT32_MAX == gnsrecord_object->record_type)
84   {
85     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,"Unsupported type");
86     return GNUNET_SYSERR;
87   }
88   if (GNUNET_OK
89       != GNUNET_GNSRECORD_string_to_value (gnsrecord_object->record_type,
90                                            value,
91                                            &rdata,
92                                            &rdata_size))
93   {
94     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,"Value invalid for record type");
95     return GNUNET_SYSERR;
96   }
97
98   gnsrecord_object->data = rdata;
99   gnsrecord_object->data_size = rdata_size;
100
101   if (0 == strcmp (expiration_time, GNUNET_JSON_GNSRECORD_NEVER))
102   {
103     gnsrecord_object->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
104   }
105   else if (GNUNET_OK
106       == GNUNET_STRINGS_fancy_time_to_absolute (expiration_time,
107                                                 &abs_expiration_time))
108   {
109     gnsrecord_object->expiration_time = abs_expiration_time.abs_value_us;
110   }
111   else
112   {
113     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Expiration time invalid");
114     return GNUNET_SYSERR;
115   }
116   // check if flag is a valid enum value
117   if ((GNUNET_GNSRECORD_RF_NONE != flag)
118       && (GNUNET_GNSRECORD_RF_PRIVATE != flag)
119       && (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION != flag)
120       && (GNUNET_GNSRECORD_RF_SHADOW_RECORD) != flag)
121   {
122     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Flag invalid");
123     return GNUNET_SYSERR;
124   }
125   gnsrecord_object->flags = (enum GNUNET_GNSRECORD_Flags)flag;
126   *(struct GNUNET_GNSRECORD_Data **) spec->ptr = gnsrecord_object;
127   return GNUNET_OK;
128 }
129
130 /**
131  * Cleanup data left from parsing RSA public key.
132  *
133  * @param cls closure, NULL
134  * @param[out] spec where to free the data
135  */
136 static void
137 clean_gnsrecordobject (void *cls, struct GNUNET_JSON_Specification *spec)
138 {
139   struct GNUNET_GNSRECORD_Data **gnsrecord_object;
140   gnsrecord_object = (struct GNUNET_GNSRECORD_Data **) spec->ptr;
141   if (NULL != *gnsrecord_object)
142   {
143     if (NULL != (*gnsrecord_object)->data)
144       GNUNET_free((char*)(*gnsrecord_object)->data);
145
146     GNUNET_free(*gnsrecord_object);
147     *gnsrecord_object = NULL;
148   }
149 }
150
151 /**
152  * JSON Specification for GNS Records.
153  *
154  * @param gnsrecord_object struct of GNUNET_GNSRECORD_Data to fill
155  * @return JSON Specification
156  */
157 struct GNUNET_JSON_Specification
158 GNUNET_JSON_spec_gnsrecord_data (struct GNUNET_GNSRECORD_Data **gnsrecord_object)
159 {
160   struct GNUNET_JSON_Specification ret = {
161     .parser = &parse_gnsrecordobject,
162     .cleaner = &clean_gnsrecordobject,
163     .cls = NULL,
164     .field = NULL,
165     .ptr = gnsrecord_object,
166     .ptr_size = 0,
167     .size_ptr = NULL
168   };
169   *gnsrecord_object = NULL;
170   return ret;
171 }