fix result and query helper
[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 result where to extract data from
28   * @param int row to extract data from
29   * @param fname name (or prefix) of the fields to extract from
30   * @param[in, out] dst_size where to store size of result, may be NULL
31   * @param[out] dst where to store the result
32   * @return
33   *   #GNUNET_OK if all results could be extracted
34   *   #GNUNET_SYSERR if a result was invalid
35   */
36 static int
37 extract_varsize_blob (void *cls,
38                       MYSQL_RES * result,
39                       int row,
40                       const char *fname,
41                       size_t *dst_size,
42                       void *dst)
43 {
44   const char *res;
45   void *idst;
46   size_t len;
47
48   MYSQL_ROW rows;
49   MYSQL_FIELD *field;
50
51   rows = mysql_fetch_row (result);
52
53   field = mysql_fetch_field (result);
54
55   //If it's the correct field
56   if (field->name != fname)
57   {
58     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
59                 "Field '%s' does not exist in result",
60                 fname);
61
62     return GNUNET_SYSERR;
63   }
64
65
66   if (rows[row] == NULL)
67   {
68     return GNUNET_SYSERR;
69   }
70
71   res = rows[row];
72
73   len = strlen(res);
74
75   GNUNET_assert (NULL != res);
76   
77   *dst_size = len;
78   idst = GNUNET_malloc (len);
79   *((void **) dst) = idst;
80   memcpy (idst,
81           res,
82           len);
83
84   return GNUNET_OK;
85 }
86
87 /**
88   * Variable-size result expected
89   *
90   * @param[out] dst where to store the result, allocated
91   * @param[out] sptr where to store the size of @a dst
92   * @return array entru for the result specification to use
93   */
94 struct GNUNET_MY_ResultSpec
95 GNUNET_MY_result_spec_variable_size (void **dst,
96                                     size_t *ptr_size)
97 {
98   struct GNUNET_MY_ResultSpec res = {
99     &extract_varsize_blob,
100     NULL,
101     (void *)(dst),
102     0,
103     ptr_size
104   };
105
106   return res;
107 }
108
109 /**
110   * Extract data from a Mysql database @a result at row @a row
111   *
112   * @param cls closure
113   * @param result where to extract data from
114   * @param int row to extract data from
115   * @param fname name (or prefix) of the fields to extract from
116   * @param[in] dst_size desired size, never NULL
117   * @param[out] dst where to store the result
118   * @return
119   *  #GNUNET_OK if all results could be extracted
120   *  #GNUNET_SYSERR if a result was invalid(non-existing field or NULL)
121   *
122   */
123 static int
124 extract_fixed_blob (void *cls,
125                       MYSQL_RES * result,
126                       int row,
127                       const char * fname,
128                       size_t * dst_size,
129                       void *dst)
130 {
131   size_t len;
132   const char *res;
133
134   MYSQL_ROW rows;
135   MYSQL_FIELD * field;
136
137   rows = mysql_fetch_row (result);
138
139   field = mysql_fetch_field (result);
140
141   //If it's the correct field
142   if (field->name != fname)
143   {
144     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
145                 "Field '%s' does not exist in result",
146                 fname);
147
148     return GNUNET_SYSERR;
149   }
150
151
152   if (rows[row] == NULL)
153   {
154     return GNUNET_SYSERR;
155   }
156
157   res = rows[row];
158
159   len = strlen (res);
160   if (*dst_size != len)
161   {
162     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
163                 "Field '%s' has wrong size (got %u, expected %u)\n",
164                 fname,
165                 (unsigned int)len,
166                 (unsigned int) *dst_size);
167     return GNUNET_SYSERR;
168   }
169
170   GNUNET_assert (NULL != res);
171   
172   memcpy (dst,
173           res,
174           len);
175
176   return GNUNET_OK;
177 }
178 /**
179  * Fixed-size result expected.
180  *
181  * @param name name of the field in the table
182  * @param[out] dst where to store the result
183  * @param dst_size number of bytes in @a dst
184  * @return array entry for the result specification to use
185  */
186 struct GNUNET_MY_ResultSpec
187 GNUNET_MY_result_spec_fixed_size (void *ptr,
188                                   size_t ptr_size)
189 {
190   struct GNUNET_MY_ResultSpec res = { 
191     &extract_fixed_blob,
192     NULL,
193     (void *)(ptr),
194     ptr_size,
195     NULL 
196   };
197       
198   return res;
199 }
200
201 /**
202   * Extract data from a Mysql database @a result at row @a row
203   *
204   * @param cls closure
205   * @param result where to extract data from
206   * @param int row to extract data from
207   * @param fname name (or prefix) of the fields to extract from
208   * @param[in, out] dst_size where to store size of result, may be NULL
209   * @param[out] dst where to store the result
210   * @return
211   *   #GNUNET_OK if all results could be extracted
212   *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
213   */
214 static int
215 extract_rsa_public_key (void *cls,
216                         MYSQL_RES *result,
217                         int row,
218                         const char *fname,
219                         size_t *dst_size,
220                         void *dst)
221 {
222   struct GNUNET_CRYPTO_RsaPublicKey **pk = dst;
223   size_t len;
224   const char *res;
225
226   MYSQL_ROW rows;
227   MYSQL_FIELD * field;
228
229   *pk = NULL;
230
231   rows = mysql_fetch_row (result);
232
233   field = mysql_fetch_field (result);
234
235   //If it's the correct field
236   if (field->name != fname)
237   {
238     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
239                 "Field '%s' does not exist in result",
240                 fname);
241     return GNUNET_SYSERR;
242   }
243
244
245   if (rows[row] == NULL)
246   {
247     return GNUNET_SYSERR;
248   }
249
250   res = rows[row];
251
252   len = strlen (res);
253   
254   *pk = GNUNET_CRYPTO_rsa_public_key_decode (res, 
255                                             len);
256
257   if (NULL == *pk)
258   {
259     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
260                 "Field '%s' contains bogus value (fails to decode\n",
261                   fname);
262     return GNUNET_SYSERR;
263   }
264   return GNUNET_OK;
265 }
266
267 /**
268   * RSA public key expected
269   *
270   * @param name name of the field in the table
271   * @param[out] rsa where to store the result
272   * @return array entry for the result specification to use
273   */
274 struct GNUNET_MY_ResultSpec
275 GNUNET_MY_result_spec_rsa_public_key (struct GNUNET_CRYPTO_RsaPublicKey **rsa)
276 {
277   struct GNUNET_MY_ResultSpec res = {
278     &extract_rsa_public_key,
279     NULL,
280     (void *) rsa,
281     0,
282     NULL    
283   };
284
285   return res;
286 }
287
288 /**
289   * Extract data from a Mysql database @a result at row @a row.
290   *
291   * @param cls closure
292   * @param result where to extract data from
293   * @param int row to extract data from
294   * @param fname name (or prefix) of the fields to extract from
295   * @param[in,out] dst_size where to store size of result, may be NULL
296   * @param[out] dst where to store the result
297   * @return
298   *    #GNUNET_OK if all results could be extracted
299   *    #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
300   */
301 static int
302 extract_rsa_signature (void *cls,
303                       MYSQL_RES * result,
304                       int row, const char *fname,
305                       size_t * dst_size,
306                       void *dst)
307 {
308   struct GNUNET_CRYPTO_RsaSignature **sig = dst;
309   size_t len;
310   const char *res;
311
312   
313   MYSQL_ROW rows;
314   MYSQL_FIELD * field;
315
316   *sig = NULL;
317
318   rows = mysql_fetch_row (result);
319
320   field = mysql_fetch_field (result);
321
322   //If it's the correct field
323   if (field->name == fname)
324   {
325     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
326                 "Field '%s' does not exist in result",
327                 fname);
328     return GNUNET_SYSERR;
329   }
330
331
332   if (rows[row] == NULL)
333   {
334     return GNUNET_SYSERR;
335   }
336
337   res = rows[row];
338   len = strlen (res);
339
340   *sig = GNUNET_CRYPTO_rsa_signature_decode (res,
341                                             len);
342
343   if (NULL == *sig)
344   {
345     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
346                 "Field '%s' contains bogus value (fails to decode)\n",
347                 fname);
348     return GNUNET_SYSERR;
349   }
350
351   return GNUNET_OK;
352 }
353
354 /**
355   * RSA signature expected.
356   *
357   * @param[out] sig where to store the result;
358   * @return array entry for the result specification to use
359   */
360 struct GNUNET_MY_ResultSpec
361 GNUNET_MY_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig)
362 {
363   struct GNUNET_MY_ResultSpec res = 
364   {
365     &extract_rsa_signature,
366     NULL,
367     (void *)sig,
368     0,
369     NULL
370   };
371   return res;
372 }
373
374 /**
375   * Extract data from a Mysql database @a result at row @a row
376   *
377   * @param cls closure
378   * @param result where to extract data from
379   * @param int row to extract data from
380   * @param fname name (or prefix) of the fields to extract from
381   * @param[in, out] dst_size where to store size of result, may be NULL
382   * @param[out] dst where to store the result
383   * @return
384   *    #GNUNET_OK if all results could be extracted
385   *    #GNUNET_SYSERR if a result was invalid (non existing field or NULL)
386   */
387 static int
388 extract_string (void * cls,
389                 MYSQL_RES * result,
390                 int row,
391                 const char * fname,
392                 size_t *dst_size,
393                 void *dst)
394 {
395   char **str = dst;
396   size_t len;
397   const char *res;
398
399   MYSQL_ROW rows;
400   MYSQL_FIELD * field;
401
402   *str = NULL;
403
404   rows = mysql_fetch_row (result);
405
406   field = mysql_fetch_field (result);
407
408   //If it's the correct field
409   if (field == fname)
410   {
411     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
412                 "Field '%s' does not exist in result",
413                 fname);
414     return GNUNET_SYSERR;
415   }
416
417
418   if (rows[row] == NULL)
419   {
420     return GNUNET_SYSERR;
421   }
422
423   res = rows[row];
424   len = strlen (res);
425  
426   *str = GNUNET_strndup (res,
427                         len);
428
429   if (NULL == *str)
430   {
431     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
432                 "Field '%s' contains bogus value (fails to decode) \n",
433                 fname);
434     return GNUNET_SYSERR;
435   }
436   return GNUNET_OK;
437 }    
438 /**
439   * 0- terminated string exprected.
440   *
441   * @param[out] dst where to store the result, allocated
442   * @return array entry for the result specification to use
443   */
444 struct GNUNET_MY_ResultSpec
445 GNUNET_MY_result_spec_string (char **dst)
446 {
447   struct GNUNET_MY_ResultSpec res = {
448     &extract_string,
449     NULL,
450     (void *) dst,
451     0,
452     NULL
453   };
454   return res;
455 }
456
457 /**
458   * Absolute time expected
459   *
460   * @param name name of the field in the table
461   * @param[out] at where to store the result
462   * @return array entry for the result specification to use
463   */
464 struct GNUNET_MY_ResultSpec
465 GNUNET_MY_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at)
466 {
467   return GNUNET_MY_result_spec_uint64 (&at->abs_value_us);
468 }
469
470 /**
471   * Absolute time in network byte order expected
472   *
473   * @param[out] at where to store the result
474   * @return array entry for the result specification to use
475   */
476 struct GNUNET_MY_ResultSpec
477 GNUNET_MY_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at)
478 {
479   struct GNUNET_MY_ResultSpec res = 
480     GNUNET_MY_result_spec_auto_from_type (&at->abs_value_us__);
481     return res;
482 }
483
484 /**
485  * Extract data from a Postgres database @a result at row @a row.
486  *
487  * @param cls closure
488  * @param result where to extract data from
489  * @param int row to extract data from
490  * @param fname name (or prefix) of the fields to extract from
491  * @param[in,out] dst_size where to store size of result, may be NULL
492  * @param[out] dst where to store the result
493  * @return
494  *   #GNUNET_YES if all results could be extracted
495  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
496  */
497 static int
498 extract_uint16 (void *cls,
499               MYSQL_RES * result,
500               int row,
501               const char *fname,
502               size_t *dst_size,
503               void *dst)
504 {
505     //TO COMPLETE 
506   uint16_t *udst = dst;
507   const uint16_t *res;
508
509   MYSQL_ROW rows;
510   MYSQL_FIELD * field;
511
512   rows = mysql_fetch_row (result);
513
514   field = mysql_fetch_field (result);
515
516   //If it's the correct field
517   if (field->name == fname)
518   {
519     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
520                 "Field '%s' does not exist in result",
521                 fname);
522     return GNUNET_SYSERR;
523   }
524
525
526   if (rows[row] == NULL)
527   {
528     return GNUNET_SYSERR;
529   }
530
531   GNUNET_assert (NULL != dst);
532
533   if (sizeof (uint16_t) != *dst_size)
534   {
535     GNUNET_break (0);
536     return GNUNET_SYSERR;
537   }
538
539   res = (uint16_t) rows[row];
540   *udst = ntohs (*res);
541
542   return GNUNET_OK;
543 }
544
545 /**
546   * uint16_t expected
547   *
548   * @param[out] u16 where to store the result
549   * @return array entry for the result specification to use
550   */
551 struct GNUNET_MY_ResultSpec
552 GNUNET_MY_result_spec_uint16 (uint16_t *u16)
553 {
554   struct GNUNET_MY_ResultSpec res = {
555     &extract_uint16,
556     NULL,
557     (void *) u16,
558     sizeof (*u16),
559     NULL
560   };
561   return res;
562 }
563
564 /**
565   * Extrac data from a  MYSQL database @a result at row @a row
566   *
567   * @param cls closure
568   * @param result where to extract data from
569   * @param int row to extract data from
570   * @param fname name (or prefix) of the fields to extract from
571   * @param[in, out] dst_size where to store size of result, may be NULL
572   * @param[out] dst where to store the result
573   * @return
574   *      #GNUNET_OK if all results could be extracted
575   *      #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
576   */
577 static int
578 extract_uint32 (void *cls,
579                 MYSQL_RES * result,
580                 int row,
581                 const char *fname,
582                 size_t *dst_size,
583                 void *dst)
584 {
585   uint32_t *udst = dst;
586   const uint32_t *res;
587
588   MYSQL_ROW rows;
589   MYSQL_FIELD * field;
590
591   rows = mysql_fetch_row (result);
592
593   field = mysql_fetch_field (result);
594
595   //If it's the correct field
596   if (field->name == fname)
597   {
598     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
599                 "Field '%s' does not exist in result",
600                 fname);
601     return GNUNET_SYSERR;
602   }
603
604
605   if (rows[row] == NULL)
606   {
607     return GNUNET_SYSERR;
608   }
609
610   GNUNET_assert (NULL != dst);
611
612   if (sizeof (uint32_t) != *dst_size)
613   {
614     GNUNET_break (0);
615     return GNUNET_SYSERR;
616   }
617
618   res = (uint32_t) rows[row];
619
620   *udst = ntohl (*res);
621   return GNUNET_OK;
622 }
623
624 /**
625   * uint32_t expected
626   *
627   * @param[out] u32 where to store the result
628   * @return array entry for the result specification to use
629   */
630 struct GNUNET_MY_ResultSpec
631 GNUNET_MY_result_spec_uint32 (uint32_t *u32)
632 {
633   struct GNUNET_MY_ResultSpec res = {
634     &extract_uint32,
635     NULL,
636     (void *) u32,
637     sizeof (*u32),
638     NULL
639   };
640   return res;
641 }
642
643 /**
644   * Extract data from a MYSQL database @a result at row @a row
645   *
646   * @param cls closure
647   * @param result where to extract data from
648   * @param int row to extract data from
649   * @param fname name (or prefix) of the fields to extract from
650   * @param[in, out] dst_size where to store size of result, may be null
651   * @param[out] dst where to store the result
652   * @return
653   *    #GNUNET_OK if all results could be extracted
654   *    #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
655   */
656 static int
657 extract_uint64 (void *cls,
658                 MYSQL_RES * result,
659                 int row, 
660                 const char *fname,
661                 size_t *dst_size,
662                 void *dst)
663 {
664   uint64_t *udst = dst;
665   const uint64_t *res;
666
667   MYSQL_ROW rows;
668   MYSQL_FIELD * field;
669
670   rows = mysql_fetch_row (result);
671
672   field = mysql_fetch_field (result);
673
674   //If it's the correct field
675   if (field->name == fname)
676   {
677     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 
678                 "Field '%s' does not exist in result",
679                 fname);
680     return GNUNET_SYSERR;
681   }
682
683
684   if (rows[row] == NULL)
685   {
686     return GNUNET_SYSERR;
687   }
688
689   GNUNET_assert (NULL != dst);
690   if (sizeof (uint64_t) != *dst_size)
691   {
692       GNUNET_break (0);
693       return GNUNET_SYSERR;
694   }
695
696   res = (uint64_t) rows[row];
697   *udst = GNUNET_ntohll (*res);
698
699   return GNUNET_OK;
700 }
701
702
703 /**
704   * uint64_t expected.
705   *
706   * @param[out] u64 where to store the result
707   * @return array entry for the result specification to use
708   */
709 struct GNUNET_MY_ResultSpec
710 GNUNET_MY_result_spec_uint64 (uint64_t *u64)
711 {
712   struct GNUNET_MY_ResultSpec res = {
713     &extract_uint64,
714     NULL,
715     (void *) u64,
716     sizeof (*u64),
717     NULL
718   };
719   return res;
720 }
721
722 /* end of pq_result_helper.c */