NAMESTORE/JSON: fix parsing exp and flags
[oweals/gnunet.git] / src / sq / sq_result_helper.c
1
2 /*
3   This file is part of GNUnet
4   Copyright (C) 2017 GNUnet e.V.
5
6   GNUnet is free software: you can redistribute it and/or modify it
7   under the terms of the GNU Affero General Public License as published
8   by the Free Software Foundation, either version 3 of the License,
9   or (at your option) any later version.
10
11   GNUnet is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   Affero General Public License for more details.
15  
16   You should have received a copy of the GNU Affero General Public License
17   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19      SPDX-License-Identifier: AGPL3.0-or-later
20 */
21 /**
22  * @file sq/sq_result_helper.c
23  * @brief helper functions for queries
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_sq_lib.h"
28
29
30 /**
31  * Extract variable-sized binary data from a Postgres database @a result at row @a row.
32  *
33  * @param cls closure
34  * @param result where to extract data from
35  * @param column column to extract data from
36  * @param[in,out] dst_size where to store size of result, may be NULL
37  * @param[out] dst where to store the result (actually a `void **`)
38  * @return
39  *   #GNUNET_YES if all results could be extracted
40  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
41  */
42 static int
43 extract_var_blob (void *cls,
44                   sqlite3_stmt *result,
45                   unsigned int column,
46                   size_t *dst_size,
47                   void *dst)
48 {
49   int have;
50   const void *ret;
51   void **rdst = (void **) dst;
52
53   if (SQLITE_NULL ==
54       sqlite3_column_type (result,
55                            column))
56   {
57     *rdst = NULL;
58     *dst_size = 0;
59     return GNUNET_YES;
60   }
61
62   if (SQLITE_BLOB !=
63       sqlite3_column_type (result,
64                            column))
65   {
66     GNUNET_break (0);
67     return GNUNET_SYSERR;
68   }
69   /* sqlite manual says to invoke 'sqlite3_column_blob()'
70      before calling sqlite3_column_bytes() */
71   ret = sqlite3_column_blob (result,
72                              column);
73   have = sqlite3_column_bytes (result,
74                                column);
75   if (have < 0)
76   {
77     GNUNET_break (0);
78     return GNUNET_SYSERR;
79   }
80   *dst_size = have;
81   if (0 == have)
82   {
83     *rdst = NULL;
84     return GNUNET_OK;
85   }
86   *rdst = GNUNET_malloc (have);
87   GNUNET_memcpy (*rdst,
88                  ret,
89                  have);
90   return GNUNET_OK;
91 }
92
93
94 /**
95  * Cleanup memory allocated by #extract_var_blob().
96  *
97  * @param cls pointer to pointer of allocation
98  */
99 static void
100 clean_var_blob (void *cls)
101 {
102   void **dptr = (void **) cls;
103
104   if (NULL != *dptr)
105   {
106     GNUNET_free (*dptr);
107     *dptr = NULL;
108   }
109 }
110
111
112 /**
113  * Variable-size result expected.
114  *
115  * @param[out] dst where to store the result, allocated
116  * @param[out] sptr where to store the size of @a dst
117  * @return array entry for the result specification to use
118  */
119 struct GNUNET_SQ_ResultSpec
120 GNUNET_SQ_result_spec_variable_size (void **dst,
121                                      size_t *sptr)
122 {
123   struct GNUNET_SQ_ResultSpec rs = {
124     .conv = &extract_var_blob,
125     .cleaner = &clean_var_blob,
126     .dst = dst,
127     .cls = dst,
128     .result_size = sptr,
129     .num_params = 1
130   };
131
132   return rs;
133 }
134
135
136 /**
137  * Extract fixed-sized binary data from a Postgres database @a result at row @a row.
138  *
139  * @param cls closure
140  * @param result where to extract data from
141  * @param column column to extract data from
142  * @param[in,out] dst_size where to store size of result, may be NULL
143  * @param[out] dst where to store the result
144  * @return
145  *   #GNUNET_YES if all results could be extracted
146  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
147  */
148 static int
149 extract_fixed_blob (void *cls,
150                     sqlite3_stmt *result,
151                     unsigned int column,
152                     size_t *dst_size,
153                     void *dst)
154 {
155   int have;
156   const void *ret;
157
158   if ( (0 == *dst_size) &&
159        (SQLITE_NULL ==
160         sqlite3_column_type (result,
161                              column)) )
162   {
163     return GNUNET_YES;
164   }
165
166   if (SQLITE_BLOB !=
167       sqlite3_column_type (result,
168                            column))
169   {
170     GNUNET_break (0);
171     return GNUNET_SYSERR;
172   }
173   /* sqlite manual says to invoke 'sqlite3_column_blob()'
174      before calling sqlite3_column_bytes() */
175   ret = sqlite3_column_blob (result,
176                              column);
177   have = sqlite3_column_bytes (result,
178                                column);
179   if (*dst_size != have)
180   {
181     GNUNET_break (0);
182     return GNUNET_SYSERR;
183   }
184   GNUNET_memcpy (dst,
185                  ret,
186                  have);
187   return GNUNET_OK;
188 }
189
190
191 /**
192  * Fixed-size result expected.
193  *
194  * @param[out] dst where to store the result
195  * @param dst_size number of bytes in @a dst
196  * @return array entry for the result specification to use
197  */
198 struct GNUNET_SQ_ResultSpec
199 GNUNET_SQ_result_spec_fixed_size (void *dst,
200                                   size_t dst_size)
201 {
202   struct GNUNET_SQ_ResultSpec rs = {
203     .conv = &extract_fixed_blob,
204     .dst = dst,
205     .dst_size = dst_size,
206     .num_params = 1
207   };
208
209   return rs;
210 }
211
212
213 /**
214  * Extract fixed-sized binary data from a Postgres database @a result at row @a row.
215  *
216  * @param cls closure
217  * @param result where to extract data from
218  * @param column column to extract data from
219  * @param[in,out] dst_size where to store size of result, may be NULL
220  * @param[out] dst where to store the result
221  * @return
222  *   #GNUNET_YES if all results could be extracted
223  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
224  */
225 static int
226 extract_utf8_string (void *cls,
227                      sqlite3_stmt *result,
228                      unsigned int column,
229                      size_t *dst_size,
230                      void *dst)
231 {
232   const char *text;
233   char **rdst = dst;
234
235   if (SQLITE_NULL ==
236       sqlite3_column_type (result,
237                            column))
238   {
239     *rdst = NULL;
240     return GNUNET_OK;
241   }
242   if (SQLITE_TEXT !=
243       sqlite3_column_type (result,
244                            column))
245   {
246     GNUNET_break (0);
247     return GNUNET_SYSERR;
248   }
249   /* sqlite manual guarantees that 'sqlite3_column_text()'
250      is 0-terminated */
251   text = (const char *) sqlite3_column_text (result,
252                                              column);
253   if (NULL == text)
254   {
255     GNUNET_break (0);
256     return GNUNET_SYSERR;
257   }
258   *dst_size = strlen (text) + 1;
259   *rdst = GNUNET_strdup (text);
260   return GNUNET_OK;
261 }
262
263
264 /**
265  * Cleanup memory allocated by #extract_var_blob().
266  *
267  * @param cls pointer to pointer of allocation
268  */
269 static void
270 clean_utf8_string (void *cls)
271 {
272   char **dptr = (char **) cls;
273
274   if (NULL != *dptr)
275   {
276     GNUNET_free (*dptr);
277     *dptr = NULL;
278   }
279 }
280
281
282 /**
283  * 0-terminated string expected.
284  *
285  * @param[out] dst where to store the result, allocated
286  * @return array entry for the result specification to use
287  */
288 struct GNUNET_SQ_ResultSpec
289 GNUNET_SQ_result_spec_string (char **dst)
290 {
291   struct GNUNET_SQ_ResultSpec rs = {
292     .conv = &extract_utf8_string,
293     .cleaner = &clean_utf8_string,
294     .cls = dst,
295     .dst = dst,
296     .num_params = 1
297   };
298
299   return rs;
300 }
301
302
303 /**
304  * Extract data from a Postgres database @a result at row @a row.
305  *
306  * @param cls closure
307  * @param result where to extract data from
308  * @param column column to extract data from
309  * @param[in,out] dst_size where to store size of result, may be NULL
310  * @param[out] dst where to store the result
311  * @return
312  *   #GNUNET_YES if all results could be extracted
313  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
314  */
315 static int
316 extract_rsa_pub (void *cls,
317                  sqlite3_stmt *result,
318                  unsigned int column,
319                  size_t *dst_size,
320                  void *dst)
321 {
322   struct GNUNET_CRYPTO_RsaPublicKey **pk = dst;
323   int have;
324   const void *ret;
325
326   if (SQLITE_BLOB !=
327       sqlite3_column_type (result,
328                            column))
329   {
330     GNUNET_break (0);
331     return GNUNET_SYSERR;
332   }
333   /* sqlite manual says to invoke 'sqlite3_column_blob()'
334      before calling sqlite3_column_bytes() */
335   ret = sqlite3_column_blob (result,
336                              column);
337   have = sqlite3_column_bytes (result,
338                                column);
339   if (have < 0)
340   {
341     GNUNET_break (0);
342     return GNUNET_SYSERR;
343   }
344
345   *pk = GNUNET_CRYPTO_rsa_public_key_decode (ret,
346                                              have);
347   if (NULL == *pk)
348   {
349     GNUNET_break (0);
350     return GNUNET_SYSERR;
351   }
352   return GNUNET_OK;
353 }
354
355
356 /**
357  * Function called to clean up memory allocated
358  * by a #GNUNET_PQ_ResultConverter.
359  *
360  * @param cls closure
361  */
362 static void
363 clean_rsa_pub (void *cls)
364 {
365   struct GNUNET_CRYPTO_RsaPublicKey **pk = cls;
366
367   if (NULL != *pk)
368   {
369     GNUNET_CRYPTO_rsa_public_key_free (*pk);
370     *pk = NULL;
371   }
372 }
373
374
375 /**
376  * RSA public key expected.
377  *
378  * @param[out] rsa where to store the result
379  * @return array entry for the result specification to use
380  */
381 struct GNUNET_SQ_ResultSpec
382 GNUNET_SQ_result_spec_rsa_public_key (struct GNUNET_CRYPTO_RsaPublicKey **rsa)
383 {
384   struct GNUNET_SQ_ResultSpec rs = {
385     .conv = &extract_rsa_pub,
386     .cleaner = &clean_rsa_pub,
387     .dst = rsa,
388     .cls = rsa,
389     .num_params = 1
390   };
391
392   return rs;
393 }
394
395
396 /**
397  * Extract data from a Postgres database @a result at row @a row.
398  *
399  * @param cls closure
400  * @param result where to extract data from
401  * @param column column to extract data from
402  * @param[in,out] dst_size where to store size of result, may be NULL
403  * @param[out] dst where to store the result
404  * @return
405  *   #GNUNET_YES if all results could be extracted
406  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
407  */
408 static int
409 extract_rsa_sig (void *cls,
410                  sqlite3_stmt *result,
411                  unsigned int column,
412                  size_t *dst_size,
413                  void *dst)
414 {
415   struct GNUNET_CRYPTO_RsaSignature **sig = dst;
416   int have;
417   const void *ret;
418
419   if (SQLITE_BLOB !=
420       sqlite3_column_type (result,
421                            column))
422   {
423     GNUNET_break (0);
424     return GNUNET_SYSERR;
425   }
426   /* sqlite manual says to invoke 'sqlite3_column_blob()'
427      before calling sqlite3_column_bytes() */
428   ret = sqlite3_column_blob (result,
429                              column);
430   have = sqlite3_column_bytes (result,
431                                column);
432   if (have < 0)
433   {
434     GNUNET_break (0);
435     return GNUNET_SYSERR;
436   }
437
438   *sig = GNUNET_CRYPTO_rsa_signature_decode (ret,
439                                              have);
440   if (NULL == *sig)
441   {
442     GNUNET_break (0);
443     return GNUNET_SYSERR;
444   }
445   return GNUNET_OK;
446 }
447
448
449 /**
450  * Function called to clean up memory allocated
451  * by a #GNUNET_PQ_ResultConverter.
452  *
453  * @param cls result data to clean up
454  */
455 static void
456 clean_rsa_sig (void *cls)
457 {
458   struct GNUNET_CRYPTO_RsaSignature **sig = cls;
459
460   if (NULL != *sig)
461   {
462     GNUNET_CRYPTO_rsa_signature_free (*sig);
463     *sig = NULL;
464   }
465 }
466
467
468 /**
469  * RSA signature expected.
470  *
471  * @param[out] sig where to store the result;
472  * @return array entry for the result specification to use
473  */
474 struct GNUNET_SQ_ResultSpec
475 GNUNET_SQ_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig)
476 {
477   struct GNUNET_SQ_ResultSpec rs = {
478     .conv = &extract_rsa_sig,
479     .cleaner = &clean_rsa_sig,
480     .dst = sig,
481     .cls = sig,
482     .num_params = 1
483   };
484
485   return rs;
486 }
487
488
489 /**
490  * Extract absolute time value from a Postgres database @a result at row @a row.
491  *
492  * @param cls closure
493  * @param result where to extract data from
494  * @param column column to extract data from
495  * @param[in,out] dst_size where to store size of result, may be NULL
496  * @param[out] dst where to store the result
497  * @return
498  *   #GNUNET_YES if all results could be extracted
499  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
500  */
501 static int
502 extract_abs_time (void *cls,
503                   sqlite3_stmt *result,
504                   unsigned int column,
505                   size_t *dst_size,
506                   void *dst)
507 {
508   struct GNUNET_TIME_Absolute *u = dst;
509   struct GNUNET_TIME_Absolute t;
510
511   GNUNET_assert (sizeof (uint64_t) == *dst_size);
512   if (SQLITE_INTEGER !=
513       sqlite3_column_type (result,
514                            column))
515   {
516     GNUNET_break (0);
517     return GNUNET_SYSERR;
518   }
519   t.abs_value_us = (uint64_t) sqlite3_column_int64 (result,
520                                                     column);
521   if (INT64_MAX == t.abs_value_us)
522     t = GNUNET_TIME_UNIT_FOREVER_ABS;
523   *u = t;
524   return GNUNET_OK;
525 }
526
527
528 /**
529  * Absolute time expected.
530  *
531  * @param[out] at where to store the result
532  * @return array entry for the result specification to use
533  */
534 struct GNUNET_SQ_ResultSpec
535 GNUNET_SQ_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at)
536 {
537   struct GNUNET_SQ_ResultSpec rs = {
538     .conv = &extract_abs_time,
539     .dst = at,
540     .dst_size = sizeof (struct GNUNET_TIME_Absolute),
541     .num_params = 1
542   };
543
544   return rs;
545 }
546
547
548 /**
549  * Extract absolute time value in NBO from a Postgres database @a result at row @a row.
550  *
551  * @param cls closure
552  * @param result where to extract data from
553  * @param column column to extract data from
554  * @param[in,out] dst_size where to store size of result, may be NULL
555  * @param[out] dst where to store the result
556  * @return
557  *   #GNUNET_YES if all results could be extracted
558  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
559  */
560 static int
561 extract_abs_time_nbo (void *cls,
562                       sqlite3_stmt *result,
563                       unsigned int column,
564                       size_t *dst_size,
565                       void *dst)
566 {
567   struct GNUNET_TIME_AbsoluteNBO *u = dst;
568   struct GNUNET_TIME_Absolute t;
569
570   GNUNET_assert (sizeof (uint64_t) == *dst_size);
571   if (SQLITE_INTEGER !=
572       sqlite3_column_type (result,
573                            column))
574   {
575     GNUNET_break (0);
576     return GNUNET_SYSERR;
577   }
578   t.abs_value_us = (uint64_t) sqlite3_column_int64 (result,
579                                                     column);
580   if (INT64_MAX == t.abs_value_us)
581     t = GNUNET_TIME_UNIT_FOREVER_ABS;
582   *u = GNUNET_TIME_absolute_hton (t);
583   return GNUNET_OK;
584 }
585
586
587 /**
588  * Absolute time expected.
589  *
590  * @param[out] at where to store the result
591  * @return array entry for the result specification to use
592  */
593 struct GNUNET_SQ_ResultSpec
594 GNUNET_SQ_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at)
595 {
596   struct GNUNET_SQ_ResultSpec rs = {
597     .conv = &extract_abs_time_nbo,
598     .dst = at,
599     .dst_size = sizeof (struct GNUNET_TIME_AbsoluteNBO),
600     .num_params = 1
601   };
602
603   return rs;
604 }
605
606
607 /**
608  * Extract 16-bit integer from a Postgres database @a result at row @a row.
609  *
610  * @param cls closure
611  * @param result where to extract data from
612  * @param column column to extract data from
613  * @param[in,out] dst_size where to store size of result, may be NULL
614  * @param[out] dst where to store the result
615  * @return
616  *   #GNUNET_YES if all results could be extracted
617  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
618  */
619 static int
620 extract_uint16 (void *cls,
621                 sqlite3_stmt *result,
622                 unsigned int column,
623                 size_t *dst_size,
624                 void *dst)
625 {
626   uint64_t v;
627   uint16_t *u = dst;
628
629   GNUNET_assert (sizeof (uint16_t) == *dst_size);
630   if (SQLITE_INTEGER !=
631       sqlite3_column_type (result,
632                            column))
633   {
634     GNUNET_break (0);
635     return GNUNET_SYSERR;
636   }
637   v = (uint64_t) sqlite3_column_int64 (result,
638                                        column);
639   if (v > UINT16_MAX)
640   {
641     GNUNET_break (0);
642     return GNUNET_SYSERR;
643   }
644   *u = (uint16_t) v;
645   return GNUNET_OK;
646 }
647
648
649 /**
650  * uint16_t expected.
651  *
652  * @param[out] u16 where to store the result
653  * @return array entry for the result specification to use
654  */
655 struct GNUNET_SQ_ResultSpec
656 GNUNET_SQ_result_spec_uint16 (uint16_t *u16)
657 {
658   struct GNUNET_SQ_ResultSpec rs = {
659     .conv = &extract_uint16,
660     .dst = u16,
661     .dst_size = sizeof (uint16_t),
662     .num_params = 1
663   };
664
665   return rs;
666 }
667
668
669 /**
670  * Extract 32-bit integer from a Postgres database @a result at row @a row.
671  *
672  * @param cls closure
673  * @param result where to extract data from
674  * @param column column to extract data from
675  * @param[in,out] dst_size where to store size of result, may be NULL
676  * @param[out] dst where to store the result
677  * @return
678  *   #GNUNET_YES if all results could be extracted
679  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
680  */
681 static int
682 extract_uint32 (void *cls,
683                 sqlite3_stmt *result,
684                 unsigned int column,
685                 size_t *dst_size,
686                 void *dst)
687 {
688   uint64_t v;
689   uint32_t *u = dst;
690
691   GNUNET_assert (sizeof (uint32_t) == *dst_size);
692   if (SQLITE_INTEGER !=
693       sqlite3_column_type (result,
694                            column))
695   {
696     GNUNET_break (0);
697     return GNUNET_SYSERR;
698   }
699   v = (uint64_t) sqlite3_column_int64 (result,
700                                        column);
701   if (v > UINT32_MAX)
702   {
703     GNUNET_break (0);
704     return GNUNET_SYSERR;
705   }
706   *u = (uint32_t) v;
707   return GNUNET_OK;
708 }
709
710
711 /**
712  * uint32_t expected.
713  *
714  * @param[out] u32 where to store the result
715  * @return array entry for the result specification to use
716  */
717 struct GNUNET_SQ_ResultSpec
718 GNUNET_SQ_result_spec_uint32 (uint32_t *u32)
719 {
720   struct GNUNET_SQ_ResultSpec rs = {
721     .conv = &extract_uint32,
722     .dst = u32,
723     .dst_size = sizeof (uint32_t),
724     .num_params = 1
725   };
726
727   return rs;
728 }
729
730
731 /**
732  * Extract 64-bit integer from a Postgres database @a result at row @a row.
733  *
734  * @param cls closure
735  * @param result where to extract data from
736  * @param column column to extract data from
737  * @param[in,out] dst_size where to store size of result, may be NULL
738  * @param[out] dst where to store the result
739  * @return
740  *   #GNUNET_YES if all results could be extracted
741  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
742  */
743 static int
744 extract_uint64 (void *cls,
745                 sqlite3_stmt *result,
746                 unsigned int column,
747                 size_t *dst_size,
748                 void *dst)
749 {
750   uint64_t *u = dst;
751
752   GNUNET_assert (sizeof (uint64_t) == *dst_size);
753   if (SQLITE_INTEGER !=
754       sqlite3_column_type (result,
755                            column))
756   {
757     GNUNET_break (0);
758     return GNUNET_SYSERR;
759   }
760   *u = (uint64_t) sqlite3_column_int64 (result,
761                                         column);
762   return GNUNET_OK;
763 }
764
765
766 /**
767  * uint64_t expected.
768  *
769  * @param[out] u64 where to store the result
770  * @return array entry for the result specification to use
771  */
772 struct GNUNET_SQ_ResultSpec
773 GNUNET_SQ_result_spec_uint64 (uint64_t *u64)
774 {
775   struct GNUNET_SQ_ResultSpec rs = {
776     .conv = &extract_uint64,
777     .dst = u64,
778     .dst_size = sizeof (uint64_t),
779     .num_params = 1
780   };
781
782   return rs;
783 }
784
785
786 /* end of sq_result_helper.c */