Fix for #4553
[oweals/gnunet.git] / src / my / my_result_helper.c
1  /*
2   This file is part of GNUnet
3   Copyright (C) 2014, 2015, 2016 GNUnet e.V.
4   GNUnet is free software; you can redistribute it and/or modify it under the
5   terms of the GNU General Public License as published by the Free Software
6   Foundation; either version 3, or (at your option) any later version.
7   GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
8   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
9   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
10   You should have received a copy of the GNU General Public License along with
11   GNUnet; see the file COPYING.  If not, If not, see <http://www.gnu.org/licenses/>
12 */
13 /**
14  * @file my/my_result_helper.c
15  * @brief functions to extract result values
16  * @author Christophe Genevey
17  */
18
19 #include "platform.h"
20 #include "gnunet_util_lib.h"
21 #include "gnunet_my_lib.h"
22
23 /**
24   * extract data from a Mysql database @a result at row @a row
25   *
26   * @param cls closure
27   * @param qp data about the query 
28   * @param result mysql result
29   * @return
30   *   #GNUNET_OK if all results could be extracted
31   *   #GNUNET_SYSERR if a result was invalid
32   */
33
34 static int
35 extract_varsize_blob (void *cls,
36                       struct GNUNET_MY_ResultSpec *rs,
37                       MYSQL_BIND *results)
38 {
39   size_t len;
40   void *idst;
41   char * res;
42
43   if (results->is_null)
44   {
45     return GNUNET_SYSERR;
46   }
47
48   len = results->buffer_length;
49   res = results->buffer;
50
51   GNUNET_assert (NULL != res);
52
53   rs->dst_size = len;
54
55   idst = GNUNET_malloc (len);
56   *(void **)rs->dst = idst;
57
58   memcpy (idst,
59           res,
60           len);
61
62  return GNUNET_OK;
63 }
64
65 /**
66   * Variable-size result expected
67   *
68   * @param[out] dst where to store the result, allocated
69   * @param[out] sptr where to store the size of @a dst
70   * @return array entru for the result specification to use
71   */
72 struct GNUNET_MY_ResultSpec
73 GNUNET_MY_result_spec_variable_size (void **dst,
74                                     size_t *ptr_size)
75 {
76   struct GNUNET_MY_ResultSpec res = 
77   {
78     &extract_varsize_blob,
79     NULL,
80     (void *)(dst),
81     0,
82     ptr_size
83   };
84
85   return res;
86 }
87
88 /**
89   * Extract data from a Mysql database @a result at row @a row
90   *
91   * @param cls closure
92   * @param result where to extract data from
93   * @param int row to extract data from
94   * @param fname name (or prefix) of the fields to extract from
95   * @param[in] dst_size desired size, never NULL
96   * @param[out] dst where to store the result
97   * @return
98   *  #GNUNET_OK if all results could be extracted
99   *  #GNUNET_SYSERR if a result was invalid(non-existing field or NULL)
100   *
101   */
102 static int
103 extract_fixed_blob (void *cls,
104                     struct GNUNET_MY_ResultSpec *rs,
105                     MYSQL_BIND *results)
106 {
107   size_t len;
108   const char *res;
109
110   if (results->is_null)
111   {
112     return GNUNET_SYSERR;
113   }
114
115   len = results->buffer_length;
116   if (rs->dst_size != len)
117   {
118     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
119                 "Results has wrong size (got %u, expected %u)\n",
120                 (unsigned int)len,
121                 (unsigned int)rs->dst_size);
122     return GNUNET_SYSERR;
123   }
124
125   res = results->buffer;
126
127   GNUNET_assert (NULL != res);
128   memcpy (rs->dst,
129           res,
130           len);
131   
132   return GNUNET_OK;
133 }
134 /**
135  * Fixed-size result expected.
136  *
137  * @param name name of the field in the table
138  * @param[out] dst where to store the result
139  * @param dst_size number of bytes in @a dst
140  * @return array entry for the result specification to use
141  */
142 struct GNUNET_MY_ResultSpec
143 GNUNET_MY_result_spec_fixed_size (void *ptr,
144                                   size_t ptr_size)
145 {
146   struct GNUNET_MY_ResultSpec res = 
147   { 
148     &extract_fixed_blob,
149     NULL,
150     (void *)(ptr),
151     ptr_size,
152     NULL 
153   };
154       
155   return res;
156 }
157
158 /**
159   * Extract data from a Mysql database @a result at row @a row
160   *
161   * @param cls closure
162   * @param result where to extract data from
163   * @param int row to extract data from
164   * @param fname name (or prefix) of the fields to extract from
165   * @param[in, out] dst_size where to store size of result, may be NULL
166   * @param[out] dst where to store the result
167   * @return
168   *   #GNUNET_OK if all results could be extracted
169   *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
170   */
171 static int
172 extract_rsa_public_key (void *cls,
173                        struct GNUNET_MY_ResultSpec *rs,
174                         MYSQL_BIND *results)
175
176 {
177   struct GNUNET_CRYPTO_RsaPublicKey **pk = rs->dst;
178   
179   size_t len;
180   const char *res;
181
182   if (results->is_null)
183   {
184     return GNUNET_SYSERR;
185   }
186
187   len = results->buffer_length;
188   res = results->buffer;
189
190   *pk = GNUNET_CRYPTO_rsa_public_key_decode (res,
191                                             len);
192
193   if (NULL == *pk)
194   {
195     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
196                 "Results contains bogus value (fail to decode)\n");
197     return GNUNET_SYSERR;
198   }
199
200   return GNUNET_OK;
201 }
202
203 /**
204   * RSA public key expected
205   *
206   * @param name name of the field in the table
207   * @param[out] rsa where to store the result
208   * @return array entry for the result specification to use
209   */
210 struct GNUNET_MY_ResultSpec
211 GNUNET_MY_result_spec_rsa_public_key (struct GNUNET_CRYPTO_RsaPublicKey **rsa)
212 {
213   struct GNUNET_MY_ResultSpec res = {
214     &extract_rsa_public_key,
215     NULL,
216     (void *) rsa,
217     0,
218     NULL    
219   };
220
221   return res;
222 }
223
224 /**
225   * Extract data from a Mysql database @a result at row @a row.
226   *
227   * @param cls closure
228   * @param result where to extract data from
229   * @param int row to extract data from
230   * @param fname name (or prefix) of the fields to extract from
231   * @param[in,out] dst_size where to store size of result, may be NULL
232   * @param[out] dst where to store the result
233   * @return
234   *    #GNUNET_OK if all results could be extracted
235   *    #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
236   */
237 static int
238 extract_rsa_signature (void *cls,
239                       struct GNUNET_MY_ResultSpec *rs,
240                       MYSQL_BIND *results)
241 {
242   struct GNUNET_CRYPTO_RsaSignature **sig = rs->dst;
243   size_t len;
244   const char *res;
245
246   if (results->is_null)
247   {
248     return GNUNET_SYSERR;
249   }
250
251   len = results->buffer_length;
252   res = results->buffer;
253
254   *sig = GNUNET_CRYPTO_rsa_signature_decode (res,
255                                             len);
256
257   if (NULL != *sig)
258   {
259     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
260                 "Resuls contains bogus value (fails to decode)\n");
261     return GNUNET_SYSERR;
262   }
263
264   return GNUNET_OK;
265 }
266
267 /**
268   * RSA signature expected.
269   *
270   * @param[out] sig where to store the result;
271   * @return array entry for the result specification to use
272   */
273 struct GNUNET_MY_ResultSpec
274 GNUNET_MY_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig)
275 {
276   struct GNUNET_MY_ResultSpec res = 
277   {
278     &extract_rsa_signature,
279     NULL,
280     (void *)sig,
281     0,
282     NULL
283   };
284   return res;
285 }
286
287 /**
288   * Extract data from a Mysql database @a result at row @a row
289   *
290   * @param cls closure
291   * @param result where to extract data from
292   * @param int row to extract data from
293   * @param fname name (or prefix) of the fields to extract from
294   * @param[in, out] dst_size where to store size of result, may be NULL
295   * @param[out] dst where to store the result
296   * @return
297   *    #GNUNET_OK if all results could be extracted
298   *    #GNUNET_SYSERR if a result was invalid (non existing field or NULL)
299   */
300 static int
301 extract_string (void * cls,
302                 struct GNUNET_MY_ResultSpec *rs,
303                 MYSQL_BIND *results)
304 {
305   char **str = rs->dst;
306   size_t len;
307   const char *res;
308
309   *str = NULL;
310
311   if (results->is_null)
312   {
313     return GNUNET_SYSERR;
314   }
315
316   len = results->buffer_length;
317   res = results->buffer;
318
319   *str = GNUNET_strndup (res,
320                         len);
321
322   if (NULL == *str)
323   {
324     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
325                 "Results contains bogus value (fail to decode)\n");
326     return GNUNET_SYSERR;
327   }
328   return GNUNET_OK;
329 }    
330 /**
331   * 0- terminated string exprected.
332   *
333   * @param[out] dst where to store the result, allocated
334   * @return array entry for the result specification to use
335   */
336 struct GNUNET_MY_ResultSpec
337 GNUNET_MY_result_spec_string (char **dst)
338 {
339   struct GNUNET_MY_ResultSpec res = {
340     &extract_string,
341     NULL,
342     (void *) dst,
343     0,
344     NULL
345   };
346   return res;
347 }
348
349 /**
350   * Absolute time expected
351   *
352   * @param name name of the field in the table
353   * @param[out] at where to store the result
354   * @return array entry for the result specification to use
355   */
356 struct GNUNET_MY_ResultSpec
357 GNUNET_MY_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at)
358 {
359   return GNUNET_MY_result_spec_uint64 (&at->abs_value_us);
360 }
361
362 /**
363   * Absolute time in network byte order expected
364   *
365   * @param[out] at where to store the result
366   * @return array entry for the result specification to use
367   */
368 struct GNUNET_MY_ResultSpec
369 GNUNET_MY_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at)
370 {
371   struct GNUNET_MY_ResultSpec res = 
372     GNUNET_MY_result_spec_auto_from_type (&at->abs_value_us__);
373     return res;
374 }
375
376 /**
377  * Extract data from a Postgres database @a result at row @a row.
378  *
379  * @param cls closure
380  * @param result where to extract data from
381  * @param int row to extract data from
382  * @param fname name (or prefix) of the fields to extract from
383  * @param[in,out] dst_size where to store size of result, may be NULL
384  * @param[out] dst where to store the result
385  * @return
386  *   #GNUNET_YES if all results could be extracted
387  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
388  */
389 static int
390 extract_uint16 (void *cls,
391                 struct GNUNET_MY_ResultSpec *rs,
392                 MYSQL_BIND *results)
393
394   uint16_t *udst = rs->dst;
395   const uint16_t *res;
396
397   if(results->is_null)
398   {
399     return GNUNET_SYSERR;
400   }
401
402   GNUNET_assert (NULL != rs->dst);
403   if (sizeof (uint16_t) != rs->dst_size)
404   {
405     GNUNET_break (0);
406     return GNUNET_SYSERR;
407   }
408
409   res = (uint16_t *)results->buffer;
410   *udst = ntohs (*res);
411
412   return GNUNET_OK;
413 }
414
415 /**
416   * uint16_t expected
417   *
418   * @param[out] u16 where to store the result
419   * @return array entry for the result specification to use
420   */
421 struct GNUNET_MY_ResultSpec
422 GNUNET_MY_result_spec_uint16 (uint16_t *u16)
423 {
424   struct GNUNET_MY_ResultSpec res = {
425     &extract_uint16,
426     NULL,
427     (void *) u16,
428     sizeof (*u16),
429     NULL
430   };
431   return res;
432 }
433
434 /**
435   * Extrac data from a  MYSQL database @a result at row @a row
436   *
437   * @param cls closure
438   * @param result where to extract data from
439   * @param int row to extract data from
440   * @param fname name (or prefix) of the fields to extract from
441   * @param[in, out] dst_size where to store size of result, may be NULL
442   * @param[out] dst where to store the result
443   * @return
444   *      #GNUNET_OK if all results could be extracted
445   *      #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
446   */
447 static int
448 extract_uint32 (void *cls,
449                 struct GNUNET_MY_ResultSpec *rs,
450                 MYSQL_BIND *results)
451 {
452   uint32_t *udst = rs->dst;
453   const uint32_t *res;
454
455   if(results->is_null)
456   {
457     return GNUNET_SYSERR;
458   }
459
460   GNUNET_assert (NULL != rs->dst);
461   if (sizeof (uint32_t) != rs->dst_size)
462   {
463     GNUNET_break (0);
464     return GNUNET_SYSERR;
465   }
466
467   res = (uint32_t *)results->buffer;
468
469   *udst = ntohl (*res);
470   
471   return GNUNET_OK;
472 }
473
474 /**
475   * uint32_t expected
476   *
477   * @param[out] u32 where to store the result
478   * @return array entry for the result specification to use
479   */
480 struct GNUNET_MY_ResultSpec
481 GNUNET_MY_result_spec_uint32 (uint32_t *u32)
482 {
483   struct GNUNET_MY_ResultSpec res = {
484     &extract_uint32,
485     NULL,
486     (void *) u32,
487     sizeof (*u32),
488     NULL
489   };
490   return res;
491 }
492
493 /**
494   * Extract data from a MYSQL database @a result at row @a row
495   *
496   * @param cls closure
497   * @param result where to extract data from
498   * @param int row to extract data from
499   * @param fname name (or prefix) of the fields to extract from
500   * @param[in, out] dst_size where to store size of result, may be null
501   * @param[out] dst where to store the result
502   * @return
503   *    #GNUNET_OK if all results could be extracted
504   *    #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
505   */
506 static int
507 extract_uint64 (void *cls,
508                 struct GNUNET_MY_ResultSpec *rs,
509                 MYSQL_BIND *results)
510 {
511   uint64_t *udst = rs->dst;
512   const uint64_t *res;
513
514   if (results->is_null)
515   {
516     return GNUNET_SYSERR;
517   }
518
519   GNUNET_assert (NULL != rs->dst);
520   if (sizeof (uint64_t) != rs->dst_size)
521   {
522     GNUNET_break (0);
523     return GNUNET_SYSERR;
524   }
525
526   res = (uint64_t *)results->buffer;
527   *udst = GNUNET_ntohll (*res);
528
529   return GNUNET_OK;
530 }
531
532
533 /**
534   * uint64_t expected.
535   *
536   * @param[out] u64 where to store the result
537   * @return array entry for the result specification to use
538   */
539 struct GNUNET_MY_ResultSpec
540 GNUNET_MY_result_spec_uint64 (uint64_t *u64)
541 {
542   struct GNUNET_MY_ResultSpec res = {
543     &extract_uint64,
544     NULL,
545     (void *) u64,
546     sizeof (*u64),
547     NULL
548   };
549   return res;
550 }
551
552 /* end of pq_result_helper.c */