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