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