1/* 2 * Copyright (C) 2009-2010 Julien BLACHE <jb@jblache.org> 3 * 4 * Some code included below is in the public domain, check comments 5 * in the file. 6 * 7 * Pieces of code adapted from mt-daapd: 8 * Copyright (C) 2003-2007 Ron Pedde (ron@pedde.com) 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 */ 24 25#ifdef HAVE_CONFIG_H 26# include <config.h> 27#endif 28 29#include <stdlib.h> 30#include <string.h> 31#include <errno.h> 32#include <stdint.h> 33#include <limits.h> 34#include <sys/param.h> 35 36#include <unistr.h> 37#include <uniconv.h> 38 39#include "logger.h" 40#include "misc.h" 41 42 43int 44safe_atoi32(const char *str, int32_t *val) 45{ 46 char *end; 47 long intval; 48 49 errno = 0; 50 intval = strtol(str, &end, 10); 51 52 if (((errno == ERANGE) && ((intval == LONG_MAX) || (intval == LONG_MIN))) 53 || ((errno != 0) && (intval == 0))) 54 { 55 DPRINTF(E_DBG, L_MISC, "Invalid integer in string (%s): %s\n", str, strerror(errno)); 56 57 return -1; 58 } 59 60 if (end == str) 61 { 62 DPRINTF(E_DBG, L_MISC, "No integer found in string (%s)\n", str); 63 64 return -1; 65 } 66 67 if (intval > INT32_MAX) 68 { 69 DPRINTF(E_DBG, L_MISC, "Integer value too large (%s)\n", str); 70 71 return -1; 72 } 73 74 *val = (int32_t)intval; 75 76 return 0; 77} 78 79int 80safe_atou32(const char *str, uint32_t *val) 81{ 82 char *end; 83 unsigned long intval; 84 85 errno = 0; 86 intval = strtoul(str, &end, 10); 87 88 if (((errno == ERANGE) && (intval == ULONG_MAX)) 89 || ((errno != 0) && (intval == 0))) 90 { 91 DPRINTF(E_DBG, L_MISC, "Invalid integer in string (%s): %s\n", str, strerror(errno)); 92 93 return -1; 94 } 95 96 if (end == str) 97 { 98 DPRINTF(E_DBG, L_MISC, "No integer found in string (%s)\n", str); 99 100 return -1; 101 } 102 103 if (intval > UINT32_MAX) 104 { 105 DPRINTF(E_DBG, L_MISC, "Integer value too large (%s)\n", str); 106 107 return -1; 108 } 109 110 *val = (uint32_t)intval; 111 112 return 0; 113} 114 115int 116safe_hextou32(const char *str, uint32_t *val) 117{ 118 char *end; 119 unsigned long intval; 120 121 /* A hex shall begin with 0x */ 122 if (strncmp(str, "0x", 2) != 0) 123 return safe_atou32(str, val); 124 125 errno = 0; 126 intval = strtoul(str, &end, 16); 127 128 if (((errno == ERANGE) && (intval == ULONG_MAX)) 129 || ((errno != 0) && (intval == 0))) 130 { 131 DPRINTF(E_DBG, L_MISC, "Invalid integer in string (%s): %s\n", str, strerror(errno)); 132 133 return -1; 134 } 135 136 if (end == str) 137 { 138 DPRINTF(E_DBG, L_MISC, "No integer found in string (%s)\n", str); 139 140 return -1; 141 } 142 143 if (intval > UINT32_MAX) 144 { 145 DPRINTF(E_DBG, L_MISC, "Integer value too large (%s)\n", str); 146 147 return -1; 148 } 149 150 *val = (uint32_t)intval; 151 152 return 0; 153} 154 155int 156safe_atoi64(const char *str, int64_t *val) 157{ 158 char *end; 159 long long intval; 160 161 errno = 0; 162 intval = strtoll(str, &end, 10); 163 164 if (((errno == ERANGE) && ((intval == LLONG_MAX) || (intval == LLONG_MIN))) 165 || ((errno != 0) && (intval == 0))) 166 { 167 DPRINTF(E_DBG, L_MISC, "Invalid integer in string (%s): %s\n", str, strerror(errno)); 168 169 return -1; 170 } 171 172 if (end == str) 173 { 174 DPRINTF(E_DBG, L_MISC, "No integer found in string (%s)\n", str); 175 176 return -1; 177 } 178 179 if (intval > INT64_MAX) 180 { 181 DPRINTF(E_DBG, L_MISC, "Integer value too large (%s)\n", str); 182 183 return -1; 184 } 185 186 *val = (int64_t)intval; 187 188 return 0; 189} 190 191int 192safe_atou64(const char *str, uint64_t *val) 193{ 194 char *end; 195 unsigned long long intval; 196 197 errno = 0; 198 intval = strtoull(str, &end, 10); 199 200 if (((errno == ERANGE) && (intval == ULLONG_MAX)) 201 || ((errno != 0) && (intval == 0))) 202 { 203 DPRINTF(E_DBG, L_MISC, "Invalid integer in string (%s): %s\n", str, strerror(errno)); 204 205 return -1; 206 } 207 208 if (end == str) 209 { 210 DPRINTF(E_DBG, L_MISC, "No integer found in string (%s)\n", str); 211 212 return -1; 213 } 214 215 if (intval > UINT64_MAX) 216 { 217 DPRINTF(E_DBG, L_MISC, "Integer value too large (%s)\n", str); 218 219 return -1; 220 } 221 222 *val = (uint64_t)intval; 223 224 return 0; 225} 226 227int 228safe_hextou64(const char *str, uint64_t *val) 229{ 230 char *end; 231 unsigned long long intval; 232 233 errno = 0; 234 intval = strtoull(str, &end, 16); 235 236 if (((errno == ERANGE) && (intval == ULLONG_MAX)) 237 || ((errno != 0) && (intval == 0))) 238 { 239 DPRINTF(E_DBG, L_MISC, "Invalid integer in string (%s): %s\n", str, strerror(errno)); 240 241 return -1; 242 } 243 244 if (end == str) 245 { 246 DPRINTF(E_DBG, L_MISC, "No integer found in string (%s)\n", str); 247 248 return -1; 249 } 250 251 if (intval > UINT64_MAX) 252 { 253 DPRINTF(E_DBG, L_MISC, "Integer value too large (%s)\n", str); 254 255 return -1; 256 } 257 258 *val = (uint64_t)intval; 259 260 return 0; 261} 262 263 264/* Key/value functions */ 265int 266keyval_add_size(struct keyval *kv, const char *name, const char *value, size_t size) 267{ 268 struct onekeyval *okv; 269 const char *val; 270 271 /* Check for duplicate key names */ 272 val = keyval_get(kv, name); 273 if (val) 274 { 275 /* Same value, fine */ 276 if (strcmp(val, value) == 0) 277 return 0; 278 else /* Different value, bad */ 279 return -1; 280 } 281 282 okv = (struct onekeyval *)malloc(sizeof(struct onekeyval)); 283 if (!okv) 284 { 285 DPRINTF(E_LOG, L_MISC, "Out of memory for new keyval\n"); 286 287 return -1; 288 } 289 290 okv->name = strdup(name); 291 if (!okv->name) 292 { 293 DPRINTF(E_LOG, L_MISC, "Out of memory for new keyval name\n"); 294 295 free(okv); 296 return -1; 297 } 298 299 okv->value = (char *)malloc(size + 1); 300 if (!okv->value) 301 { 302 DPRINTF(E_LOG, L_MISC, "Out of memory for new keyval value\n"); 303 304 free(okv->name); 305 free(okv); 306 return -1; 307 } 308 309 memcpy(okv->value, value, size); 310 okv->value[size] = '\0'; 311 312 okv->next = NULL; 313 314 if (!kv->head) 315 kv->head = okv; 316 317 if (kv->tail) 318 kv->tail->next = okv; 319 320 kv->tail = okv; 321 322 return 0; 323} 324 325int 326keyval_add(struct keyval *kv, const char *name, const char *value) 327{ 328 return keyval_add_size(kv, name, value, strlen(value)); 329} 330 331void 332keyval_remove(struct keyval *kv, const char *name) 333{ 334 struct onekeyval *okv; 335 struct onekeyval *pokv; 336 337 for (pokv = NULL, okv = kv->head; okv; pokv = okv, okv = okv->next) 338 { 339 if (strcasecmp(okv->name, name) == 0) 340 break; 341 } 342 343 if (!okv) 344 return; 345 346 if (okv == kv->head) 347 kv->head = okv->next; 348 349 if (okv == kv->tail) 350 kv->tail = pokv; 351 352 if (pokv) 353 pokv->next = okv->next; 354 355 free(okv->name); 356 free(okv->value); 357 free(okv); 358} 359 360const char * 361keyval_get(struct keyval *kv, const char *name) 362{ 363 struct onekeyval *okv; 364 365 for (okv = kv->head; okv; okv = okv->next) 366 { 367 if (strcasecmp(okv->name, name) == 0) 368 return okv->value; 369 } 370 371 return NULL; 372} 373 374void 375keyval_clear(struct keyval *kv) 376{ 377 struct onekeyval *hokv; 378 struct onekeyval *okv; 379 380 hokv = kv->head; 381 382 for (okv = hokv; hokv; okv = hokv) 383 { 384 hokv = okv->next; 385 386 free(okv->name); 387 free(okv->value); 388 free(okv); 389 } 390 391 kv->head = NULL; 392 kv->tail = NULL; 393} 394 395 396char * 397m_realpath(const char *pathname) 398{ 399 char buf[PATH_MAX]; 400 char *ret; 401 402 ret = realpath(pathname, buf); 403 if (!ret) 404 return NULL; 405 406 ret = strdup(buf); 407 if (!ret) 408 { 409 DPRINTF(E_LOG, L_MISC, "Out of memory for realpath\n"); 410 411 return NULL; 412 } 413 414 return ret; 415} 416 417char * 418unicode_fixup_string(char *str) 419{ 420 uint8_t *ret; 421 size_t len; 422 423 if (!str) 424 return NULL; 425 426 len = strlen(str); 427 428 /* String is valid UTF-8 */ 429 if (!u8_check((uint8_t *)str, len)) 430 { 431 if (len >= 3) 432 { 433 /* Check for and strip byte-order mark */ 434 if (memcmp("\xef\xbb\xbf", str, 3) == 0) 435 memmove(str, str + 3, len - 3 + 1); 436 } 437 438 return str; 439 } 440 441 ret = u8_conv_from_encoding("ascii", iconveh_question_mark, str, len, NULL, NULL, &len); 442 if (!ret) 443 { 444 DPRINTF(E_LOG, L_MISC, "Could not convert string '%s' to UTF-8: %s\n", str, strerror(errno)); 445 446 return NULL; 447 } 448 449 return (char *)ret; 450} 451 452uint32_t 453djb_hash(void *data, size_t len) 454{ 455 unsigned char *bytes = data; 456 uint32_t hash = 5381; 457 458 while (len--) 459 { 460 hash = ((hash << 5) + hash) + *bytes; 461 bytes++; 462 } 463 464 return hash; 465} 466 467 468static unsigned char b64_decode_table[256]; 469 470char * 471b64_decode(const char *b64) 472{ 473 char *str; 474 const unsigned char *iptr; 475 unsigned char *optr; 476 unsigned char c; 477 int len; 478 int i; 479 480 if (b64_decode_table[0] == 0) 481 { 482 memset(b64_decode_table, 0xff, sizeof(b64_decode_table)); 483 484 /* Base64 encoding: A-Za-z0-9+/ */ 485 for (i = 0; i < 26; i++) 486 { 487 b64_decode_table['A' + i] = i; 488 b64_decode_table['a' + i] = i + 26; 489 } 490 491 for (i = 0; i < 10; i++) 492 b64_decode_table['0' + i] = i + 52; 493 494 b64_decode_table['+'] = 62; 495 b64_decode_table['/'] = 63; 496 497 /* Stop on '=' */ 498 b64_decode_table['='] = 100; /* > 63 */ 499 } 500 501 len = strlen(b64); 502 503 str = (char *)malloc(len); 504 if (!str) 505 return NULL; 506 507 memset(str, 0, len); 508 509 iptr = (const unsigned char *)b64; 510 optr = (unsigned char *)str; 511 i = 0; 512 513 while (len) 514 { 515 if (*iptr == '=') 516 break; 517 518 c = b64_decode_table[*iptr]; 519 if (c > 63) 520 { 521 iptr++; 522 len--; 523 continue; 524 } 525 526 switch (i) 527 { 528 case 0: 529 optr[0] = c << 2; 530 break; 531 case 1: 532 optr[0] |= c >> 4; 533 optr[1] = c << 4; 534 break; 535 case 2: 536 optr[1] |= c >> 2; 537 optr[2] = c << 6; 538 break; 539 case 3: 540 optr[2] |= c; 541 break; 542 } 543 544 i++; 545 if (i == 4) 546 { 547 optr += 3; 548 i = 0; 549 } 550 551 len--; 552 iptr++; 553 } 554 555 return str; 556} 557 558static const char b64_encode_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 559 560static void 561b64_encode_block(uint8_t *in, char *out, int len) 562{ 563 out[0] = b64_encode_table[in[0] >> 2]; 564 565 out[2] = out[3] = '='; 566 567 if (len == 1) 568 out[1] = b64_encode_table[((in[0] & 0x03) << 4)]; 569 else 570 { 571 out[1] = b64_encode_table[((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)]; 572 573 if (len == 2) 574 out[2] = b64_encode_table[((in[1] & 0x0f) << 2)]; 575 else 576 { 577 out[2] = b64_encode_table[((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)]; 578 out[3] = b64_encode_table[in[2] & 0x3f]; 579 } 580 } 581} 582 583static void 584b64_encode_full_block(uint8_t *in, char *out) 585{ 586 out[0] = b64_encode_table[in[0] >> 2]; 587 out[1] = b64_encode_table[((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)]; 588 out[2] = b64_encode_table[((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)]; 589 out[3] = b64_encode_table[in[2] & 0x3f]; 590} 591 592char * 593b64_encode(uint8_t *in, size_t len) 594{ 595 char *encoded; 596 char *out; 597 598 /* 3 in chars -> 4 out chars */ 599 encoded = (char *)malloc(len + (len / 3) + 4 + 1); 600 if (!encoded) 601 return NULL; 602 603 out = encoded; 604 605 while (len >= 3) 606 { 607 b64_encode_full_block(in, out); 608 609 len -= 3; 610 in += 3; 611 out += 4; 612 } 613 614 if (len > 0) 615 { 616 b64_encode_block(in, out, len); 617 out += 4; 618 } 619 620 out[0] = '\0'; 621 622 return encoded; 623} 624 625/* 626 * MurmurHash2, 64-bit versions, by Austin Appleby 627 * 628 * Code released under the public domain, as per 629 * <http://murmurhash.googlepages.com/> 630 * as of 2010-01-03. 631 */ 632 633#if SIZEOF_VOID_P == 8 /* 64bit platforms */ 634 635uint64_t 636murmur_hash64(const void *key, int len, uint32_t seed) 637{ 638 const int r = 47; 639 const uint64_t m = 0xc6a4a7935bd1e995; 640 641 const uint64_t *data; 642 const uint64_t *end; 643 const unsigned char *data_tail; 644 uint64_t h; 645 uint64_t k; 646 647 h = seed ^ (len * m); 648 data = (const uint64_t *)key; 649 end = data + (len / 8); 650 651 while (data != end) 652 { 653 k = *data++; 654 655 k *= m; 656 k ^= k >> r; 657 k *= m; 658 659 h ^= k; 660 h *= m; 661 } 662 663 data_tail = (const unsigned char *)data; 664 665 switch (len & 7) 666 { 667 case 7: 668 h ^= (uint64_t)(data_tail[6]) << 48; 669 case 6: 670 h ^= (uint64_t)(data_tail[5]) << 40; 671 case 5: 672 h ^= (uint64_t)(data_tail[4]) << 32; 673 case 4: 674 h ^= (uint64_t)(data_tail[3]) << 24; 675 case 3: 676 h ^= (uint64_t)(data_tail[2]) << 16; 677 case 2: 678 h ^= (uint64_t)(data_tail[1]) << 8; 679 case 1: 680 h ^= (uint64_t)(data_tail[0]); 681 h *= m; 682 } 683 684 h ^= h >> r; 685 h *= m; 686 h ^= h >> r; 687 688 return h; 689} 690 691#elif SIZEOF_VOID_P == 4 /* 32bit platforms */ 692 693uint64_t 694murmur_hash64(const void *key, int len, uint32_t seed) 695{ 696 const int r = 24; 697 const uint32_t m = 0x5bd1e995; 698 699 const uint32_t *data; 700 const unsigned char *data_tail; 701 uint32_t k1; 702 uint32_t h1; 703 uint32_t k2; 704 uint32_t h2; 705 706 uint64_t h; 707 708 h1 = seed ^ len; 709 h2 = 0; 710 711 data = (const uint32_t *)key; 712 713 while (len >= 8) 714 { 715 k1 = *data++; 716 k1 *= m; k1 ^= k1 >> r; k1 *= m; 717 h1 *= m; h1 ^= k1; 718 719 k2 = *data++; 720 k2 *= m; k2 ^= k2 >> r; k2 *= m; 721 h2 *= m; h2 ^= k2; 722 723 len -= 8; 724 } 725 726 if (len >= 4) 727 { 728 k1 = *data++; 729 k1 *= m; k1 ^= k1 >> r; k1 *= m; 730 h1 *= m; h1 ^= k1; 731 len -= 4; 732 } 733 734 data_tail = (const unsigned char *)data; 735 736 switch(len) 737 { 738 case 3: 739 h2 ^= (uint32_t)(data_tail[2]) << 16; 740 case 2: 741 h2 ^= (uint32_t)(data_tail[1]) << 8; 742 case 1: 743 h2 ^= (uint32_t)(data_tail[0]); 744 h2 *= m; 745 }; 746 747 h1 ^= h2 >> 18; h1 *= m; 748 h2 ^= h1 >> 22; h2 *= m; 749 h1 ^= h2 >> 17; h1 *= m; 750 h2 ^= h1 >> 19; h2 *= m; 751 752 h = h1; 753 h = (h << 32) | h2; 754 755 return h; 756} 757 758#else 759# error Platform not supported 760#endif 761