Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2014-2023 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 3, or (at your option) any later version.
8 :
9 : TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 : WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 : A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 :
13 : You should have received a copy of the GNU General Public License along with
14 : TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
15 : */
16 : /**
17 : * @file util.c
18 : * @brief Common utility functions
19 : * @author Sree Harsha Totakura <sreeharsha@totakura.in>
20 : * @author Florian Dold
21 : * @author Benedikt Mueller
22 : * @author Christian Grothoff
23 : */
24 : #include "platform.h"
25 : #include "taler_util.h"
26 : #include "taler_attributes.h"
27 : #include <gnunet/gnunet_json_lib.h>
28 : #include <unistr.h>
29 :
30 :
31 : const char *
32 224983 : TALER_b2s (const void *buf,
33 : size_t buf_size)
34 : {
35 : static TALER_THREAD_LOCAL char ret[9];
36 : struct GNUNET_HashCode hc;
37 : char *tmp;
38 :
39 224983 : GNUNET_CRYPTO_hash (buf,
40 : buf_size,
41 : &hc);
42 224983 : tmp = GNUNET_STRINGS_data_to_string_alloc (&hc,
43 : sizeof (hc));
44 224983 : GNUNET_memcpy (ret,
45 : tmp,
46 : 8);
47 224983 : GNUNET_free (tmp);
48 224983 : ret[8] = '\0';
49 224983 : return ret;
50 : }
51 :
52 :
53 : void
54 93010 : TALER_denom_fee_set_hton (struct TALER_DenomFeeSetNBOP *nbo,
55 : const struct TALER_DenomFeeSet *fees)
56 : {
57 93010 : TALER_amount_hton (&nbo->withdraw,
58 : &fees->withdraw);
59 93010 : TALER_amount_hton (&nbo->deposit,
60 : &fees->deposit);
61 93010 : TALER_amount_hton (&nbo->refresh,
62 : &fees->refresh);
63 93010 : TALER_amount_hton (&nbo->refund,
64 : &fees->refund);
65 93010 : }
66 :
67 :
68 : void
69 0 : TALER_denom_fee_set_ntoh (struct TALER_DenomFeeSet *fees,
70 : const struct TALER_DenomFeeSetNBOP *nbo)
71 : {
72 0 : TALER_amount_ntoh (&fees->withdraw,
73 : &nbo->withdraw);
74 0 : TALER_amount_ntoh (&fees->deposit,
75 : &nbo->deposit);
76 0 : TALER_amount_ntoh (&fees->refresh,
77 : &nbo->refresh);
78 0 : TALER_amount_ntoh (&fees->refund,
79 : &nbo->refund);
80 0 : }
81 :
82 :
83 : void
84 127 : TALER_global_fee_set_hton (struct TALER_GlobalFeeSetNBOP *nbo,
85 : const struct TALER_GlobalFeeSet *fees)
86 : {
87 127 : TALER_amount_hton (&nbo->history,
88 : &fees->history);
89 127 : TALER_amount_hton (&nbo->account,
90 : &fees->account);
91 127 : TALER_amount_hton (&nbo->purse,
92 : &fees->purse);
93 127 : }
94 :
95 :
96 : void
97 0 : TALER_global_fee_set_ntoh (struct TALER_GlobalFeeSet *fees,
98 : const struct TALER_GlobalFeeSetNBOP *nbo)
99 : {
100 0 : TALER_amount_ntoh (&fees->history,
101 : &nbo->history);
102 0 : TALER_amount_ntoh (&fees->account,
103 : &nbo->account);
104 0 : TALER_amount_ntoh (&fees->purse,
105 : &nbo->purse);
106 0 : }
107 :
108 :
109 : void
110 161 : TALER_wire_fee_set_hton (struct TALER_WireFeeSetNBOP *nbo,
111 : const struct TALER_WireFeeSet *fees)
112 : {
113 161 : TALER_amount_hton (&nbo->wire,
114 : &fees->wire);
115 161 : TALER_amount_hton (&nbo->closing,
116 : &fees->closing);
117 161 : }
118 :
119 :
120 : void
121 0 : TALER_wire_fee_set_ntoh (struct TALER_WireFeeSet *fees,
122 : const struct TALER_WireFeeSetNBOP *nbo)
123 : {
124 0 : TALER_amount_ntoh (&fees->wire,
125 : &nbo->wire);
126 0 : TALER_amount_ntoh (&fees->closing,
127 : &nbo->closing);
128 0 : }
129 :
130 :
131 : int
132 0 : TALER_global_fee_set_cmp (const struct TALER_GlobalFeeSet *f1,
133 : const struct TALER_GlobalFeeSet *f2)
134 : {
135 : int ret;
136 :
137 0 : ret = TALER_amount_cmp (&f1->history,
138 : &f2->history);
139 0 : if (0 != ret)
140 0 : return ret;
141 0 : ret = TALER_amount_cmp (&f1->account,
142 : &f2->account);
143 0 : if (0 != ret)
144 0 : return ret;
145 0 : ret = TALER_amount_cmp (&f1->purse,
146 : &f2->purse);
147 0 : if (0 != ret)
148 0 : return ret;
149 0 : return 0;
150 : }
151 :
152 :
153 : int
154 4 : TALER_wire_fee_set_cmp (const struct TALER_WireFeeSet *f1,
155 : const struct TALER_WireFeeSet *f2)
156 : {
157 : int ret;
158 :
159 4 : ret = TALER_amount_cmp (&f1->wire,
160 : &f2->wire);
161 4 : if (0 != ret)
162 0 : return ret;
163 4 : ret = TALER_amount_cmp (&f1->closing,
164 : &f2->closing);
165 4 : if (0 != ret)
166 2 : return ret;
167 2 : return 0;
168 : }
169 :
170 :
171 : enum GNUNET_GenericReturnValue
172 24904 : TALER_denom_fee_check_currency (
173 : const char *currency,
174 : const struct TALER_DenomFeeSet *fees)
175 : {
176 24904 : if (GNUNET_YES !=
177 24904 : TALER_amount_is_currency (&fees->withdraw,
178 : currency))
179 : {
180 0 : GNUNET_break (0);
181 0 : return GNUNET_NO;
182 : }
183 24904 : if (GNUNET_YES !=
184 24904 : TALER_amount_is_currency (&fees->deposit,
185 : currency))
186 : {
187 0 : GNUNET_break (0);
188 0 : return GNUNET_NO;
189 : }
190 24904 : if (GNUNET_YES !=
191 24904 : TALER_amount_is_currency (&fees->refresh,
192 : currency))
193 : {
194 0 : GNUNET_break (0);
195 0 : return GNUNET_NO;
196 : }
197 24904 : if (GNUNET_YES !=
198 24904 : TALER_amount_is_currency (&fees->refund,
199 : currency))
200 : {
201 0 : GNUNET_break (0);
202 0 : return GNUNET_NO;
203 : }
204 24904 : return GNUNET_OK;
205 : }
206 :
207 :
208 : /**
209 : * Dump character in the low range into @a buf
210 : * following RFC 8785.
211 : *
212 : * @param[in,out] buf buffer to modify
213 : * @param val value to dump
214 : */
215 : static void
216 3 : lowdump (struct GNUNET_Buffer *buf,
217 : unsigned char val)
218 : {
219 : char scratch[7];
220 :
221 3 : switch (val)
222 : {
223 0 : case 0x8:
224 0 : GNUNET_buffer_write (buf,
225 : "\\b",
226 : 2);
227 0 : break;
228 0 : case 0x9:
229 0 : GNUNET_buffer_write (buf,
230 : "\\t",
231 : 2);
232 0 : break;
233 0 : case 0xA:
234 0 : GNUNET_buffer_write (buf,
235 : "\\n",
236 : 2);
237 0 : break;
238 0 : case 0xC:
239 0 : GNUNET_buffer_write (buf,
240 : "\\f",
241 : 2);
242 0 : break;
243 0 : case 0xD:
244 0 : GNUNET_buffer_write (buf,
245 : "\\r",
246 : 2);
247 0 : break;
248 3 : default:
249 3 : GNUNET_snprintf (scratch,
250 : sizeof (scratch),
251 : "\\u%04x",
252 : (unsigned int) val);
253 3 : GNUNET_buffer_write (buf,
254 : scratch,
255 : 6);
256 3 : break;
257 : }
258 3 : }
259 :
260 :
261 : size_t
262 627 : TALER_rfc8785encode (char **inp)
263 : {
264 627 : struct GNUNET_Buffer buf = { 0 };
265 627 : size_t left = strlen (*inp) + 1;
266 : size_t olen;
267 627 : char *in = *inp;
268 627 : const char *pos = in;
269 :
270 627 : GNUNET_buffer_prealloc (&buf,
271 : left + 40);
272 627 : buf.warn_grow = 0; /* disable, + 40 is just a wild guess */
273 : while (1)
274 50998 : {
275 51625 : int mbl = u8_mblen ((unsigned char *) pos,
276 : left);
277 : unsigned char val;
278 :
279 51625 : if (0 == mbl)
280 627 : break;
281 50998 : val = (unsigned char) *pos;
282 50998 : if ( (1 == mbl) &&
283 : (val <= 0x1F) )
284 : {
285 : /* Should not happen, as input is produced by
286 : * JSON stringification */
287 0 : GNUNET_break (0);
288 0 : lowdump (&buf,
289 : val);
290 : }
291 50998 : else if ( (1 == mbl) && ('\\' == *pos) )
292 : {
293 8 : switch (*(pos + 1))
294 : {
295 1 : case '\\':
296 1 : mbl = 2;
297 1 : GNUNET_buffer_write (&buf,
298 : pos,
299 : mbl);
300 1 : break;
301 3 : case 'u':
302 : {
303 : unsigned int num;
304 : uint32_t n32;
305 : unsigned char res[8];
306 : size_t rlen;
307 :
308 3 : GNUNET_assert ( (1 ==
309 : sscanf (pos + 2,
310 : "%4x",
311 : &num)) ||
312 : (1 ==
313 : sscanf (pos + 2,
314 : "%4X",
315 : &num)) );
316 3 : mbl = 6;
317 3 : n32 = (uint32_t) num;
318 3 : rlen = sizeof (res);
319 3 : u32_to_u8 (&n32,
320 : 1,
321 : res,
322 : &rlen);
323 3 : if ( (1 == rlen) &&
324 3 : (res[0] <= 0x1F) )
325 : {
326 3 : lowdump (&buf,
327 3 : res[0]);
328 : }
329 : else
330 : {
331 0 : GNUNET_buffer_write (&buf,
332 : (const char *) res,
333 : rlen);
334 : }
335 : }
336 3 : break;
337 4 : default:
338 4 : mbl = 2;
339 4 : GNUNET_buffer_write (&buf,
340 : pos,
341 : mbl);
342 4 : break;
343 : }
344 : }
345 : else
346 : {
347 50990 : GNUNET_buffer_write (&buf,
348 : pos,
349 : mbl);
350 : }
351 50998 : left -= mbl;
352 50998 : pos += mbl;
353 : }
354 :
355 : /* 0-terminate buffer */
356 627 : GNUNET_buffer_write (&buf,
357 : "",
358 : 1);
359 627 : GNUNET_free (in);
360 627 : *inp = GNUNET_buffer_reap (&buf,
361 : &olen);
362 627 : return olen;
363 : }
364 :
365 :
366 : /**
367 : * Hash normalized @a j JSON object or array and
368 : * store the result in @a hc.
369 : *
370 : * @param j JSON to hash
371 : * @param[out] hc where to write the hash
372 : */
373 : void
374 410 : TALER_json_hash (const json_t *j,
375 : struct GNUNET_HashCode *hc)
376 : {
377 : char *cstr;
378 : size_t clen;
379 :
380 410 : cstr = json_dumps (j,
381 : JSON_COMPACT | JSON_SORT_KEYS);
382 410 : GNUNET_assert (NULL != cstr);
383 410 : clen = TALER_rfc8785encode (&cstr);
384 410 : GNUNET_CRYPTO_hash (cstr,
385 : clen,
386 : hc);
387 410 : GNUNET_free (cstr);
388 410 : }
389 :
390 :
391 : #ifdef __APPLE__
392 : char *
393 : strchrnul (const char *s,
394 : int c)
395 : {
396 : char *value;
397 : value = strchr (s,
398 : c);
399 : if (NULL == value)
400 : value = &s[strlen (s)];
401 : return value;
402 : }
403 :
404 :
405 : #endif
406 :
407 :
408 : /* end of util.c */
|