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