dbus-string.c revision 05a4ad6994919b352b5229d0b1b0a8ebebe2a42f
1/* -*- mode: C; c-file-style: "gnu" -*- */ 2/* dbus-string.c String utility class (internal to D-BUS implementation) 3 * 4 * Copyright (C) 2002 Red Hat, Inc. 5 * 6 * Licensed under the Academic Free License version 1.2 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 */ 23 24#include "dbus-internals.h" 25#include "dbus-string.h" 26/* we allow a system header here, for speed/convenience */ 27#include <string.h> 28 29/** 30 * @defgroup DBusString string class 31 * @ingroup DBusInternals 32 * @brief DBusString data structure 33 * 34 * Types and functions related to DBusString. DBusString is intended 35 * to be a string class that makes it hard to mess up security issues 36 * (and just in general harder to write buggy code). It should be 37 * used (or extended and then used) rather than the libc stuff in 38 * string.h. The string class is a bit inconvenient at spots because 39 * it handles out-of-memory failures and tries to be extra-robust. 40 * 41 * A DBusString has a maximum length set at initialization time; this 42 * can be used to ensure that a buffer doesn't get too big. The 43 * _dbus_string_lengthen() method checks for overflow, and for max 44 * length being exceeded. 45 * 46 * Try to avoid conversion to a plain C string, i.e. add methods on 47 * the string object instead, only convert to C string when passing 48 * things out to the public API. In particular, no sprintf, strcpy, 49 * strcat, any of that should be used. The GString feature of 50 * accepting negative numbers for "length of string" is also absent, 51 * because it could keep us from detecting bogus huge lengths. i.e. if 52 * we passed in some bogus huge length it would be taken to mean 53 * "current length of string" instead of "broken crack" 54 */ 55 56/** 57 * @defgroup DBusStringInternals DBusString implementation details 58 * @ingroup DBusInternals 59 * @brief DBusString implementation details 60 * 61 * The guts of DBusString. 62 * 63 * @{ 64 */ 65 66/** 67 * @brief Internals of DBusString. 68 * 69 * DBusString internals. DBusString is an opaque objects, it must be 70 * used via accessor functions. 71 */ 72typedef struct 73{ 74 unsigned char *str; /**< String data, plus nul termination */ 75 int len; /**< Length without nul */ 76 int allocated; /**< Allocated size of data */ 77 int max_length; /**< Max length of this string. */ 78 unsigned int constant : 1; /**< String data is not owned by DBusString */ 79 unsigned int locked : 1; /**< DBusString has been locked and can't be changed */ 80 unsigned int invalid : 1; /**< DBusString is invalid (e.g. already freed) */ 81} DBusRealString; 82 83/** 84 * Checks a bunch of assertions about a string object 85 * 86 * @param real the DBusRealString 87 */ 88#define DBUS_GENERIC_STRING_PREAMBLE(real) _dbus_assert ((real) != NULL); _dbus_assert (!(real)->invalid); _dbus_assert ((real)->len >= 0); _dbus_assert ((real)->allocated >= 0); _dbus_assert ((real)->max_length >= 0); _dbus_assert ((real)->len <= (real)->allocated); _dbus_assert ((real)->len <= (real)->max_length) 89 90/** 91 * Checks assertions about a string object that needs to be 92 * modifiable - may not be locked or const. Also declares 93 * the "real" variable pointing to DBusRealString. 94 * @param str the string 95 */ 96#define DBUS_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \ 97 DBUS_GENERIC_STRING_PREAMBLE (real); \ 98 _dbus_assert (!(real)->constant); \ 99 _dbus_assert (!(real)->locked) 100 101/** 102 * Checks assertions about a string object that may be locked but 103 * can't be const. i.e. a string object that we can free. Also 104 * declares the "real" variable pointing to DBusRealString. 105 * 106 * @param str the string 107 */ 108#define DBUS_LOCKED_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \ 109 DBUS_GENERIC_STRING_PREAMBLE (real); \ 110 _dbus_assert (!(real)->constant) 111 112/** 113 * Checks assertions about a string that may be const or locked. Also 114 * declares the "real" variable pointing to DBusRealString. 115 * @param str the string. 116 */ 117#define DBUS_CONST_STRING_PREAMBLE(str) const DBusRealString *real = (DBusRealString*) str; \ 118 DBUS_GENERIC_STRING_PREAMBLE (real) 119 120/** @} */ 121 122/** 123 * @addtogroup DBusString 124 * @{ 125 */ 126 127/** Assert that the string's memory is 8-byte aligned. 128 * 129 * @todo Currently we just hope libc returns 8-byte aligned memory 130 * (which is true for GNU libc), but really we need to ensure it by 131 * allocating 8 extra bytes and keeping an "align_offset : 3" field 132 * in DBusString, or something along those lines. 133 */ 134#define ASSERT_8_BYTE_ALIGNED(s) \ 135 _dbus_assert (_DBUS_ALIGN_ADDRESS (((const DBusRealString*)s)->str, 8) == ((const DBusRealString*)s)->str) 136 137/** 138 * Initializes a string. The maximum length may be _DBUS_INT_MAX for 139 * no maximum. The string starts life with zero length. 140 * The string must eventually be freed with _dbus_string_free(). 141 * 142 * @todo the max length feature is useless, because it looks 143 * to the app like out of memory, and the app might try 144 * to "recover" - but recovery in this case is impossible, 145 * as we can't ever "get more memory" - so should delete the 146 * max length feature I think. 147 * 148 * @todo we could make this init routine not alloc any memory and 149 * return void, would simplify a lot of code, however it might 150 * complexify things elsewhere because _dbus_string_get_data() 151 * etc. could suddenly fail as they'd need to alloc new memory. 152 * 153 * @param str memory to hold the string 154 * @param max_length the maximum size of the string 155 * @returns #TRUE on success 156 */ 157dbus_bool_t 158_dbus_string_init (DBusString *str, 159 int max_length) 160{ 161 DBusRealString *real; 162 163 _dbus_assert (str != NULL); 164 _dbus_assert (max_length >= 0); 165 166 _dbus_assert (sizeof (DBusString) == sizeof (DBusRealString)); 167 168 real = (DBusRealString*) str; 169 170 /* It's very important not to touch anything 171 * other than real->str if we're going to fail, 172 * since we also use this function to reset 173 * an existing string, e.g. in _dbus_string_steal_data() 174 */ 175 176#define INITIAL_ALLOC 2 177 178 real->str = dbus_malloc (INITIAL_ALLOC); 179 if (real->str == NULL) 180 return FALSE; 181 182 real->allocated = INITIAL_ALLOC; 183 real->len = 0; 184 real->str[real->len] = '\0'; 185 186 real->max_length = max_length; 187 real->constant = FALSE; 188 real->locked = FALSE; 189 real->invalid = FALSE; 190 191 ASSERT_8_BYTE_ALIGNED (str); 192 193 return TRUE; 194} 195 196/** 197 * Initializes a constant string. The value parameter is not copied 198 * (should be static), and the string may never be modified. 199 * It is safe but not necessary to call _dbus_string_free() 200 * on a const string. 201 * 202 * @param str memory to use for the string 203 * @param value a string to be stored in str (not copied!!!) 204 */ 205void 206_dbus_string_init_const (DBusString *str, 207 const char *value) 208{ 209 _dbus_string_init_const_len (str, value, 210 strlen (value)); 211} 212 213/** 214 * Initializes a constant string with a length. The value parameter is 215 * not copied (should be static), and the string may never be 216 * modified. It is safe but not necessary to call _dbus_string_free() 217 * on a const string. 218 * 219 * @param str memory to use for the string 220 * @param value a string to be stored in str (not copied!!!) 221 * @param len the length to use 222 */ 223void 224_dbus_string_init_const_len (DBusString *str, 225 const char *value, 226 int len) 227{ 228 DBusRealString *real; 229 230 _dbus_assert (str != NULL); 231 _dbus_assert (value != NULL); 232 233 real = (DBusRealString*) str; 234 235 real->str = (char*) value; 236 real->len = len; 237 real->allocated = real->len; 238 real->max_length = real->len; 239 real->constant = TRUE; 240 real->invalid = FALSE; 241 242 /* We don't require const strings to be 8-byte aligned as the 243 * memory is coming from elsewhere. 244 */ 245} 246 247/** 248 * Frees a string created by _dbus_string_init(). 249 * 250 * @param str memory where the string is stored. 251 */ 252void 253_dbus_string_free (DBusString *str) 254{ 255 DBusRealString *real = (DBusRealString*) str; 256 DBUS_GENERIC_STRING_PREAMBLE (real); 257 258 if (real->constant) 259 return; 260 dbus_free (real->str); 261 262 real->invalid = TRUE; 263} 264 265/** 266 * Locks a string such that any attempts to change the string 267 * will result in aborting the program. Also, if the string 268 * is wasting a lot of memory (allocation is larger than what 269 * the string is really using), _dbus_string_lock() will realloc 270 * the string's data to "compact" it. 271 * 272 * @param str the string to lock. 273 */ 274void 275_dbus_string_lock (DBusString *str) 276{ 277 DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */ 278 279 real->locked = TRUE; 280 281 /* Try to realloc to avoid excess memory usage, since 282 * we know we won't change the string further 283 */ 284#define MAX_WASTE 24 285 if (real->allocated > (real->len + MAX_WASTE)) 286 { 287 char *new_str; 288 int new_allocated; 289 290 new_allocated = real->len + 1; 291 292 new_str = dbus_realloc (real->str, new_allocated); 293 if (new_str != NULL) 294 { 295 real->str = new_str; 296 real->allocated = new_allocated; 297 ASSERT_8_BYTE_ALIGNED (str); 298 } 299 } 300} 301 302/** 303 * Gets the raw character buffer from the string. The returned buffer 304 * will be nul-terminated, but note that strings may contain binary 305 * data so there may be extra nul characters prior to the termination. 306 * This function should be little-used, extend DBusString or add 307 * stuff to dbus-sysdeps.c instead. It's an error to use this 308 * function on a const string. 309 * 310 * @param str the string 311 * @param data_return place to store the returned data 312 */ 313void 314_dbus_string_get_data (DBusString *str, 315 char **data_return) 316{ 317 DBUS_STRING_PREAMBLE (str); 318 _dbus_assert (data_return != NULL); 319 320 *data_return = real->str; 321} 322 323/** 324 * Gets the raw character buffer from a const string. 325 * 326 * @param str the string 327 * @param data_return location to store returned data 328 */ 329void 330_dbus_string_get_const_data (const DBusString *str, 331 const char **data_return) 332{ 333 DBUS_CONST_STRING_PREAMBLE (str); 334 _dbus_assert (data_return != NULL); 335 336 *data_return = real->str; 337} 338 339/** 340 * Gets a sub-portion of the raw character buffer from the 341 * string. The "len" field is required simply for error 342 * checking, to be sure you don't try to use more 343 * string than exists. The nul termination of the 344 * returned buffer remains at the end of the entire 345 * string, not at start + len. 346 * 347 * @param str the string 348 * @param data_return location to return the buffer 349 * @param start byte offset to return 350 * @param len length of segment to return 351 */ 352void 353_dbus_string_get_data_len (DBusString *str, 354 char **data_return, 355 int start, 356 int len) 357{ 358 DBUS_STRING_PREAMBLE (str); 359 _dbus_assert (data_return != NULL); 360 _dbus_assert (start >= 0); 361 _dbus_assert (len >= 0); 362 _dbus_assert ((start + len) <= real->len); 363 364 *data_return = real->str + start; 365} 366 367/** 368 * const version of _dbus_string_get_data_len(). 369 * 370 * @param str the string 371 * @param data_return location to return the buffer 372 * @param start byte offset to return 373 * @param len length of segment to return 374 */ 375void 376_dbus_string_get_const_data_len (const DBusString *str, 377 const char **data_return, 378 int start, 379 int len) 380{ 381 DBUS_CONST_STRING_PREAMBLE (str); 382 _dbus_assert (data_return != NULL); 383 _dbus_assert (start >= 0); 384 _dbus_assert (len >= 0); 385 _dbus_assert ((start + len) <= real->len); 386 387 *data_return = real->str + start; 388} 389 390/** 391 * Gets the byte at the given position. 392 * 393 * @param str the string 394 * @param start the position 395 * @returns the byte at that position 396 */ 397char 398_dbus_string_get_byte (const DBusString *str, 399 int start) 400{ 401 DBUS_CONST_STRING_PREAMBLE (str); 402 _dbus_assert (start < real->len); 403 404 return real->str[start]; 405} 406 407/** 408 * Like _dbus_string_get_data(), but removes the 409 * gotten data from the original string. The caller 410 * must free the data returned. This function may 411 * fail due to lack of memory, and return #FALSE. 412 * 413 * @param str the string 414 * @param data_return location to return the buffer 415 * @returns #TRUE on success 416 */ 417dbus_bool_t 418_dbus_string_steal_data (DBusString *str, 419 char **data_return) 420{ 421 DBUS_STRING_PREAMBLE (str); 422 _dbus_assert (data_return != NULL); 423 424 *data_return = real->str; 425 426 /* reset the string */ 427 if (!_dbus_string_init (str, real->max_length)) 428 { 429 /* hrm, put it back then */ 430 real->str = *data_return; 431 *data_return = NULL; 432 return FALSE; 433 } 434 435 return TRUE; 436} 437 438/** 439 * Like _dbus_string_get_data_len(), but removes the gotten data from 440 * the original string. The caller must free the data returned. This 441 * function may fail due to lack of memory, and return #FALSE. 442 * The returned string is nul-terminated and has length len. 443 * 444 * @param str the string 445 * @param data_return location to return the buffer 446 * @param start the start of segment to steal 447 * @param len the length of segment to steal 448 * @returns #TRUE on success 449 */ 450dbus_bool_t 451_dbus_string_steal_data_len (DBusString *str, 452 char **data_return, 453 int start, 454 int len) 455{ 456 DBusString dest; 457 458 DBUS_STRING_PREAMBLE (str); 459 _dbus_assert (data_return != NULL); 460 _dbus_assert (start >= 0); 461 _dbus_assert (len >= 0); 462 _dbus_assert ((start + len) <= real->len); 463 464 if (!_dbus_string_init (&dest, real->max_length)) 465 return FALSE; 466 467 if (!_dbus_string_move_len (str, start, len, &dest, 0)) 468 { 469 _dbus_string_free (&dest); 470 return FALSE; 471 } 472 473 if (!_dbus_string_steal_data (&dest, data_return)) 474 { 475 _dbus_string_free (&dest); 476 return FALSE; 477 } 478 479 _dbus_string_free (&dest); 480 return TRUE; 481} 482 483/** 484 * Gets the length of a string (not including nul termination). 485 * 486 * @returns the length. 487 */ 488int 489_dbus_string_get_length (const DBusString *str) 490{ 491 DBUS_CONST_STRING_PREAMBLE (str); 492 493 return real->len; 494} 495 496static dbus_bool_t 497set_length (DBusRealString *real, 498 int new_length) 499{ 500 /* Note, we are setting the length without nul termination */ 501 502 /* exceeding max length is the same as failure to allocate memory */ 503 if (new_length > real->max_length) 504 return FALSE; 505 506 while (new_length >= real->allocated) 507 { 508 int new_allocated; 509 char *new_str; 510 511 new_allocated = 2 + real->allocated * 2; 512 if (new_allocated < real->allocated) 513 return FALSE; /* overflow */ 514 515 new_str = dbus_realloc (real->str, new_allocated); 516 if (new_str == NULL) 517 return FALSE; 518 519 real->str = new_str; 520 real->allocated = new_allocated; 521 522 ASSERT_8_BYTE_ALIGNED (real); 523 } 524 525 real->len = new_length; 526 real->str[real->len] = '\0'; 527 528 return TRUE; 529} 530 531/** 532 * Makes a string longer by the given number of bytes. Checks whether 533 * adding additional_length to the current length would overflow an 534 * integer, and checks for exceeding a string's max length. 535 * The new bytes are not initialized, other than nul-terminating 536 * the end of the string. The uninitialized bytes may contain 537 * unexpected nul bytes or other junk. 538 * 539 * @param str a string 540 * @param additional_length length to add to the string. 541 * @returns #TRUE on success. 542 */ 543dbus_bool_t 544_dbus_string_lengthen (DBusString *str, 545 int additional_length) 546{ 547 DBUS_STRING_PREAMBLE (str); 548 _dbus_assert (additional_length >= 0); 549 550 if ((real->len + additional_length) < real->len) 551 return FALSE; /* overflow */ 552 553 return set_length (real, 554 real->len + additional_length); 555} 556 557/** 558 * Makes a string shorter by the given number of bytes. 559 * 560 * @param str a string 561 * @param length_to_remove length to remove from the string. 562 */ 563void 564_dbus_string_shorten (DBusString *str, 565 int length_to_remove) 566{ 567 DBUS_STRING_PREAMBLE (str); 568 _dbus_assert (length_to_remove >= 0); 569 _dbus_assert (length_to_remove <= real->len); 570 571 set_length (real, 572 real->len - length_to_remove); 573} 574 575/** 576 * Sets the length of a string. Can be used to truncate or lengthen 577 * the string. If the string is lengthened, the function may fail and 578 * return #FALSE. Newly-added bytes are not initialized, as with 579 * _dbus_string_lengthen(). 580 * 581 * @param str a string 582 * @param length new length of the string. 583 * @returns #FALSE on failure. 584 */ 585dbus_bool_t 586_dbus_string_set_length (DBusString *str, 587 int length) 588{ 589 DBUS_STRING_PREAMBLE (str); 590 _dbus_assert (length >= 0); 591 592 return set_length (real, length); 593} 594 595/** 596 * Align the length of a string to a specific alignment (typically 4 or 8) 597 * by appending nul bytes to the string. 598 * 599 * @param str a string 600 * @param alignment the alignment 601 * @returns #FALSE if no memory 602 */ 603dbus_bool_t 604_dbus_string_align_length (DBusString *str, 605 int alignment) 606{ 607 int new_len; 608 int delta; 609 DBUS_STRING_PREAMBLE (str); 610 _dbus_assert (alignment >= 1); 611 _dbus_assert (alignment <= 16); /* arbitrary */ 612 613 new_len = _DBUS_ALIGN_VALUE (real->len, alignment); 614 615 delta = new_len - real->len; 616 _dbus_assert (delta >= 0); 617 618 if (delta == 0) 619 return TRUE; 620 621 if (!set_length (real, new_len)) 622 return FALSE; 623 624 memset (real->str + (new_len - delta), 625 '\0', delta); 626 627 return TRUE; 628} 629 630static dbus_bool_t 631append (DBusRealString *real, 632 const char *buffer, 633 int buffer_len) 634{ 635 if (buffer_len == 0) 636 return TRUE; 637 638 if (!_dbus_string_lengthen ((DBusString*)real, buffer_len)) 639 return FALSE; 640 641 memcpy (real->str + (real->len - buffer_len), 642 buffer, 643 buffer_len); 644 645 return TRUE; 646} 647 648/** 649 * Appends a nul-terminated C-style string to a DBusString. 650 * 651 * @param str the DBusString 652 * @param buffer the nul-terminated characters to append 653 * @returns #FALSE if not enough memory. 654 */ 655dbus_bool_t 656_dbus_string_append (DBusString *str, 657 const char *buffer) 658{ 659 int buffer_len; 660 661 DBUS_STRING_PREAMBLE (str); 662 _dbus_assert (buffer != NULL); 663 664 buffer_len = strlen (buffer); 665 666 return append (real, buffer, buffer_len); 667} 668 669/** 670 * Appends block of bytes with the given length to a DBusString. 671 * 672 * @param str the DBusString 673 * @param buffer the bytes to append 674 * @param len the number of bytes to append 675 * @returns #FALSE if not enough memory. 676 */ 677dbus_bool_t 678_dbus_string_append_len (DBusString *str, 679 const char *buffer, 680 int len) 681{ 682 DBUS_STRING_PREAMBLE (str); 683 _dbus_assert (buffer != NULL); 684 _dbus_assert (len >= 0); 685 686 return append (real, buffer, len); 687} 688 689/** 690 * Appends a single byte to the string, returning #FALSE 691 * if not enough memory. 692 * 693 * @param str the string 694 * @param byte the byte to append 695 * @returns #TRUE on success 696 */ 697dbus_bool_t 698_dbus_string_append_byte (DBusString *str, 699 unsigned char byte) 700{ 701 DBUS_STRING_PREAMBLE (str); 702 703 if (!set_length (real, real->len + 1)) 704 return FALSE; 705 706 real->str[real->len-1] = byte; 707 708 return TRUE; 709} 710 711/** 712 * Appends a single Unicode character, encoding the character 713 * in UTF-8 format. 714 * 715 * @param str the string 716 * @param ch the Unicode character 717 */ 718dbus_bool_t 719_dbus_string_append_unichar (DBusString *str, 720 dbus_unichar_t ch) 721{ 722 int len; 723 int first; 724 int i; 725 char *out; 726 727 DBUS_STRING_PREAMBLE (str); 728 729 /* this code is from GLib but is pretty standard I think */ 730 731 len = 0; 732 733 if (ch < 0x80) 734 { 735 first = 0; 736 len = 1; 737 } 738 else if (ch < 0x800) 739 { 740 first = 0xc0; 741 len = 2; 742 } 743 else if (ch < 0x10000) 744 { 745 first = 0xe0; 746 len = 3; 747 } 748 else if (ch < 0x200000) 749 { 750 first = 0xf0; 751 len = 4; 752 } 753 else if (ch < 0x4000000) 754 { 755 first = 0xf8; 756 len = 5; 757 } 758 else 759 { 760 first = 0xfc; 761 len = 6; 762 } 763 764 if (!set_length (real, real->len + len)) 765 return FALSE; 766 767 out = real->str + (real->len - len); 768 769 for (i = len - 1; i > 0; --i) 770 { 771 out[i] = (ch & 0x3f) | 0x80; 772 ch >>= 6; 773 } 774 out[0] = ch | first; 775 776 return TRUE; 777} 778 779static void 780delete (DBusRealString *real, 781 int start, 782 int len) 783{ 784 if (len == 0) 785 return; 786 787 memmove (real->str + start, real->str + start + len, real->len - (start + len)); 788 real->len -= len; 789 real->str[real->len] = '\0'; 790} 791 792/** 793 * Deletes a segment of a DBusString with length len starting at 794 * start. (Hint: to clear an entire string, setting length to 0 795 * with _dbus_string_set_length() is easier.) 796 * 797 * @param str the DBusString 798 * @param start where to start deleting 799 * @param len the number of bytes to delete 800 */ 801void 802_dbus_string_delete (DBusString *str, 803 int start, 804 int len) 805{ 806 DBUS_STRING_PREAMBLE (str); 807 _dbus_assert (start >= 0); 808 _dbus_assert (len >= 0); 809 _dbus_assert ((start + len) <= real->len); 810 811 delete (real, start, len); 812} 813 814static dbus_bool_t 815open_gap (int len, 816 DBusRealString *dest, 817 int insert_at) 818{ 819 if (len == 0) 820 return TRUE; 821 822 if (!set_length (dest, dest->len + len)) 823 return FALSE; 824 825 memmove (dest->str + insert_at + len, 826 dest->str + insert_at, 827 dest->len - len - insert_at); 828 829 return TRUE; 830} 831 832static dbus_bool_t 833copy (DBusRealString *source, 834 int start, 835 int len, 836 DBusRealString *dest, 837 int insert_at) 838{ 839 if (len == 0) 840 return TRUE; 841 842 if (!open_gap (len, dest, insert_at)) 843 return FALSE; 844 845 memcpy (dest->str + insert_at, 846 source->str + start, 847 len); 848 849 return TRUE; 850} 851 852/** 853 * Checks assertions for two strings we're copying a segment between, 854 * and declares real_source/real_dest variables. 855 * 856 * @param source the source string 857 * @param start the starting offset 858 * @param dest the dest string 859 * @param insert_at where the copied segment is inserted 860 */ 861#define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at) \ 862 DBusRealString *real_source = (DBusRealString*) source; \ 863 DBusRealString *real_dest = (DBusRealString*) dest; \ 864 _dbus_assert ((source) != (dest)); \ 865 DBUS_GENERIC_STRING_PREAMBLE (real_source); \ 866 DBUS_GENERIC_STRING_PREAMBLE (real_dest); \ 867 _dbus_assert (!real_dest->constant); \ 868 _dbus_assert (!real_dest->locked); \ 869 _dbus_assert ((start) >= 0); \ 870 _dbus_assert ((start) <= real_source->len); \ 871 _dbus_assert ((insert_at) >= 0); \ 872 _dbus_assert ((insert_at) <= real_dest->len) 873 874/** 875 * Moves the end of one string into another string. Both strings 876 * must be initialized, valid strings. 877 * 878 * @param source the source string 879 * @param start where to chop off the source string 880 * @param dest the destination string 881 * @param insert_at where to move the chopped-off part of source string 882 * @returns #FALSE if not enough memory 883 */ 884dbus_bool_t 885_dbus_string_move (DBusString *source, 886 int start, 887 DBusString *dest, 888 int insert_at) 889{ 890 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 891 892 if (!copy (real_source, start, 893 real_source->len - start, 894 real_dest, 895 insert_at)) 896 return FALSE; 897 898 delete (real_source, start, 899 real_source->len - start); 900 901 return TRUE; 902} 903 904/** 905 * Like _dbus_string_move(), but does not delete the section 906 * of the source string that's copied to the dest string. 907 * 908 * @param source the source string 909 * @param start where to start copying the source string 910 * @param dest the destination string 911 * @param insert_at where to place the copied part of source string 912 * @returns #FALSE if not enough memory 913 */ 914dbus_bool_t 915_dbus_string_copy (const DBusString *source, 916 int start, 917 DBusString *dest, 918 int insert_at) 919{ 920 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 921 922 return copy (real_source, start, 923 real_source->len - start, 924 real_dest, 925 insert_at); 926} 927 928/** 929 * Like _dbus_string_move(), but can move a segment from 930 * the middle of the source string. 931 * 932 * @param source the source string 933 * @param start first byte of source string to move 934 * @param len length of segment to move 935 * @param dest the destination string 936 * @param insert_at where to move the bytes from the source string 937 * @returns #FALSE if not enough memory 938 */ 939dbus_bool_t 940_dbus_string_move_len (DBusString *source, 941 int start, 942 int len, 943 DBusString *dest, 944 int insert_at) 945 946{ 947 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 948 _dbus_assert (len >= 0); 949 _dbus_assert ((start + len) <= real_source->len); 950 951 if (!copy (real_source, start, len, 952 real_dest, 953 insert_at)) 954 return FALSE; 955 956 delete (real_source, start, 957 len); 958 959 return TRUE; 960} 961 962/** 963 * Like _dbus_string_copy(), but can copy a segment from the middle of 964 * the source string. 965 * 966 * @param source the source string 967 * @param start where to start copying the source string 968 * @param len length of segment to copy 969 * @param dest the destination string 970 * @param insert_at where to place the copied segment of source string 971 * @returns #FALSE if not enough memory 972 */ 973dbus_bool_t 974_dbus_string_copy_len (const DBusString *source, 975 int start, 976 int len, 977 DBusString *dest, 978 int insert_at) 979{ 980 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 981 _dbus_assert (len >= 0); 982 _dbus_assert ((start + len) <= real_source->len); 983 984 return copy (real_source, start, len, 985 real_dest, 986 insert_at); 987} 988 989/** 990 * Replaces a segment of dest string with a segment of source string. 991 * 992 * @todo optimize the case where the two lengths are the same, and 993 * avoid memmoving the data in the trailing part of the string twice. 994 * 995 * @param source the source string 996 * @param start where to start copying the source string 997 * @param len length of segment to copy 998 * @param dest the destination string 999 * @param replace_at start of segment of dest string to replace 1000 * @param replace_len length of segment of dest string to replace 1001 * @returns #FALSE if not enough memory 1002 * 1003 */ 1004dbus_bool_t 1005_dbus_string_replace_len (const DBusString *source, 1006 int start, 1007 int len, 1008 DBusString *dest, 1009 int replace_at, 1010 int replace_len) 1011{ 1012 DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at); 1013 _dbus_assert (len >= 0); 1014 _dbus_assert ((start + len) <= real_source->len); 1015 _dbus_assert (replace_at >= 0); 1016 _dbus_assert ((replace_at + replace_len) <= real_dest->len); 1017 1018 if (!copy (real_source, start, len, 1019 real_dest, replace_at)) 1020 return FALSE; 1021 1022 delete (real_dest, replace_at + len, replace_len); 1023 1024 return TRUE; 1025} 1026 1027/* Unicode macros from GLib */ 1028 1029/** computes length and mask of a unicode character 1030 * @param Char the char 1031 * @param Mask the mask variable to assign to 1032 * @param Len the length variable to assign to 1033 */ 1034#define UTF8_COMPUTE(Char, Mask, Len) \ 1035 if (Char < 128) \ 1036 { \ 1037 Len = 1; \ 1038 Mask = 0x7f; \ 1039 } \ 1040 else if ((Char & 0xe0) == 0xc0) \ 1041 { \ 1042 Len = 2; \ 1043 Mask = 0x1f; \ 1044 } \ 1045 else if ((Char & 0xf0) == 0xe0) \ 1046 { \ 1047 Len = 3; \ 1048 Mask = 0x0f; \ 1049 } \ 1050 else if ((Char & 0xf8) == 0xf0) \ 1051 { \ 1052 Len = 4; \ 1053 Mask = 0x07; \ 1054 } \ 1055 else if ((Char & 0xfc) == 0xf8) \ 1056 { \ 1057 Len = 5; \ 1058 Mask = 0x03; \ 1059 } \ 1060 else if ((Char & 0xfe) == 0xfc) \ 1061 { \ 1062 Len = 6; \ 1063 Mask = 0x01; \ 1064 } \ 1065 else \ 1066 Len = -1; 1067 1068/** 1069 * computes length of a unicode character in UTF-8 1070 * @param Char the char 1071 */ 1072#define UTF8_LENGTH(Char) \ 1073 ((Char) < 0x80 ? 1 : \ 1074 ((Char) < 0x800 ? 2 : \ 1075 ((Char) < 0x10000 ? 3 : \ 1076 ((Char) < 0x200000 ? 4 : \ 1077 ((Char) < 0x4000000 ? 5 : 6))))) 1078 1079/** 1080 * Gets a UTF-8 value. 1081 * 1082 * @param Result variable for extracted unicode char. 1083 * @param Chars the bytes to decode 1084 * @param Count counter variable 1085 * @param Mask mask for this char 1086 * @param Len length for this char in bytes 1087 */ 1088#define UTF8_GET(Result, Chars, Count, Mask, Len) \ 1089 (Result) = (Chars)[0] & (Mask); \ 1090 for ((Count) = 1; (Count) < (Len); ++(Count)) \ 1091 { \ 1092 if (((Chars)[(Count)] & 0xc0) != 0x80) \ 1093 { \ 1094 (Result) = -1; \ 1095 break; \ 1096 } \ 1097 (Result) <<= 6; \ 1098 (Result) |= ((Chars)[(Count)] & 0x3f); \ 1099 } 1100 1101/** 1102 * Check whether a unicode char is in a valid range. 1103 * 1104 * @param Char the character 1105 */ 1106#define UNICODE_VALID(Char) \ 1107 ((Char) < 0x110000 && \ 1108 ((Char) < 0xD800 || (Char) >= 0xE000) && \ 1109 (Char) != 0xFFFE && (Char) != 0xFFFF) 1110 1111/** 1112 * Gets a unicode character from a UTF-8 string. Does no validation; 1113 * you must verify that the string is valid UTF-8 in advance and must 1114 * pass in the start of a character. 1115 * 1116 * @param str the string 1117 * @param start the start of the UTF-8 character. 1118 * @param ch_return location to return the character 1119 * @param end_return location to return the byte index of next character 1120 * @returns #TRUE on success, #FALSE otherwise. 1121 */ 1122void 1123_dbus_string_get_unichar (const DBusString *str, 1124 int start, 1125 dbus_unichar_t *ch_return, 1126 int *end_return) 1127{ 1128 int i, mask, len; 1129 dbus_unichar_t result; 1130 unsigned char c; 1131 unsigned char *p; 1132 DBUS_CONST_STRING_PREAMBLE (str); 1133 1134 if (ch_return) 1135 *ch_return = 0; 1136 if (end_return) 1137 *end_return = real->len; 1138 1139 mask = 0; 1140 p = real->str + start; 1141 c = *p; 1142 1143 UTF8_COMPUTE (c, mask, len); 1144 if (len == -1) 1145 return; 1146 UTF8_GET (result, p, i, mask, len); 1147 1148 if (result == (dbus_unichar_t)-1) 1149 return; 1150 1151 if (ch_return) 1152 *ch_return = result; 1153 if (end_return) 1154 *end_return = start + len; 1155} 1156 1157/** 1158 * Finds the given substring in the string, 1159 * returning #TRUE and filling in the byte index 1160 * where the substring was found, if it was found. 1161 * Returns #FALSE if the substring wasn't found. 1162 * Sets *start to the length of the string if the substring 1163 * is not found. 1164 * 1165 * @param str the string 1166 * @param start where to start looking 1167 * @param substr the substring 1168 * @param found return location for where it was found, or #NULL 1169 * @returns #TRUE if found 1170 */ 1171dbus_bool_t 1172_dbus_string_find (const DBusString *str, 1173 int start, 1174 const char *substr, 1175 int *found) 1176{ 1177 int i; 1178 DBUS_CONST_STRING_PREAMBLE (str); 1179 _dbus_assert (substr != NULL); 1180 _dbus_assert (start <= real->len); 1181 1182 /* we always "find" an empty string */ 1183 if (*substr == '\0') 1184 { 1185 if (found) 1186 *found = 0; 1187 return TRUE; 1188 } 1189 1190 i = start; 1191 while (i < real->len) 1192 { 1193 if (real->str[i] == substr[0]) 1194 { 1195 int j = i + 1; 1196 1197 while (j < real->len) 1198 { 1199 if (substr[j - i] == '\0') 1200 break; 1201 else if (real->str[j] != substr[j - i]) 1202 break; 1203 1204 ++j; 1205 } 1206 1207 if (substr[j - i] == '\0') 1208 { 1209 if (found) 1210 *found = i; 1211 return TRUE; 1212 } 1213 } 1214 1215 ++i; 1216 } 1217 1218 if (found) 1219 *found = real->len; 1220 1221 return FALSE; 1222} 1223 1224/** 1225 * Finds a blank (space or tab) in the string. Returns #TRUE 1226 * if found, #FALSE otherwise. If a blank is not found sets 1227 * *found to the length of the string. 1228 * 1229 * @param str the string 1230 * @param start byte index to start looking 1231 * @param found place to store the location of the first blank 1232 * @returns #TRUE if a blank was found 1233 */ 1234dbus_bool_t 1235_dbus_string_find_blank (const DBusString *str, 1236 int start, 1237 int *found) 1238{ 1239 int i; 1240 DBUS_CONST_STRING_PREAMBLE (str); 1241 _dbus_assert (start <= real->len); 1242 1243 i = start; 1244 while (i < real->len) 1245 { 1246 if (real->str[i] == ' ' || 1247 real->str[i] == '\t') 1248 { 1249 if (found) 1250 *found = i; 1251 return TRUE; 1252 } 1253 1254 ++i; 1255 } 1256 1257 if (found) 1258 *found = real->len; 1259 1260 return FALSE; 1261} 1262 1263/** 1264 * Skips blanks from start, storing the first non-blank in *end 1265 * 1266 * @param str the string 1267 * @param start where to start 1268 * @param end where to store the first non-blank byte index 1269 */ 1270void 1271_dbus_string_skip_blank (const DBusString *str, 1272 int start, 1273 int *end) 1274{ 1275 int i; 1276 DBUS_CONST_STRING_PREAMBLE (str); 1277 _dbus_assert (start <= real->len); 1278 1279 i = start; 1280 while (i < real->len) 1281 { 1282 if (!(real->str[i] == ' ' || 1283 real->str[i] == '\t')) 1284 break; 1285 1286 ++i; 1287 } 1288 1289 _dbus_assert (i == real->len || !(real->str[i] == ' ' || 1290 real->str[i] == '\t')); 1291 1292 if (end) 1293 *end = i; 1294} 1295 1296/** 1297 * Tests two DBusString for equality. 1298 * 1299 * @param a first string 1300 * @param b second string 1301 * @returns #TRUE if equal 1302 */ 1303dbus_bool_t 1304_dbus_string_equal (const DBusString *a, 1305 const DBusString *b) 1306{ 1307 const unsigned char *ap; 1308 const unsigned char *bp; 1309 const unsigned char *a_end; 1310 const DBusRealString *real_a = (const DBusRealString*) a; 1311 const DBusRealString *real_b = (const DBusRealString*) b; 1312 DBUS_GENERIC_STRING_PREAMBLE (real_a); 1313 DBUS_GENERIC_STRING_PREAMBLE (real_b); 1314 1315 if (real_a->len != real_b->len) 1316 return FALSE; 1317 1318 ap = real_a->str; 1319 bp = real_b->str; 1320 a_end = real_a->str + real_a->len; 1321 while (ap != a_end) 1322 { 1323 if (*ap != *bp) 1324 return FALSE; 1325 1326 ++ap; 1327 ++bp; 1328 } 1329 1330 return TRUE; 1331} 1332 1333/** 1334 * Checks whether a string is equal to a C string. 1335 * 1336 * @param a the string 1337 * @param c_str the C string 1338 * @returns #TRUE if equal 1339 */ 1340dbus_bool_t 1341_dbus_string_equal_c_str (const DBusString *a, 1342 const char *c_str) 1343{ 1344 const unsigned char *ap; 1345 const unsigned char *bp; 1346 const unsigned char *a_end; 1347 const DBusRealString *real_a = (const DBusRealString*) a; 1348 DBUS_GENERIC_STRING_PREAMBLE (real_a); 1349 1350 ap = real_a->str; 1351 bp = (const unsigned char*) c_str; 1352 a_end = real_a->str + real_a->len; 1353 while (ap != a_end && *bp) 1354 { 1355 if (*ap != *bp) 1356 return FALSE; 1357 1358 ++ap; 1359 ++bp; 1360 } 1361 1362 if (*ap && *bp == '\0') 1363 return FALSE; 1364 else if (ap == a_end && *bp) 1365 return FALSE; 1366 1367 return TRUE; 1368} 1369 1370/** 1371 * Checks whether a string starts with the given C string. 1372 * 1373 * @param a the string 1374 * @param c_str the C string 1375 * @returns #TRUE if string starts with it 1376 */ 1377dbus_bool_t 1378_dbus_string_starts_with_c_str (const DBusString *a, 1379 const char *c_str) 1380{ 1381 const unsigned char *ap; 1382 const unsigned char *bp; 1383 const unsigned char *a_end; 1384 const DBusRealString *real_a = (const DBusRealString*) a; 1385 DBUS_GENERIC_STRING_PREAMBLE (real_a); 1386 1387 ap = real_a->str; 1388 bp = (const unsigned char*) c_str; 1389 a_end = real_a->str + real_a->len; 1390 while (ap != a_end && *bp) 1391 { 1392 if (*ap != *bp) 1393 return FALSE; 1394 1395 ++ap; 1396 ++bp; 1397 } 1398 1399 if (*bp == '\0') 1400 return TRUE; 1401 else 1402 return FALSE; 1403} 1404 1405/** 1406 * Returns whether a string ends with the given suffix 1407 * 1408 * @param a the string 1409 * @param c_str the C-style string 1410 * @returns #TRUE if the string ends with the suffix 1411 */ 1412dbus_bool_t 1413_dbus_string_ends_with_c_str (const DBusString *a, 1414 const char *c_str) 1415{ 1416 const unsigned char *ap; 1417 const unsigned char *bp; 1418 const unsigned char *a_end; 1419 int c_str_len; 1420 const DBusRealString *real_a = (const DBusRealString*) a; 1421 DBUS_GENERIC_STRING_PREAMBLE (real_a); 1422 1423 c_str_len = strlen (c_str); 1424 if (real_a->len < c_str_len) 1425 return FALSE; 1426 1427 ap = real_a->str + (real_a->len - c_str_len); 1428 bp = (const unsigned char*) c_str; 1429 a_end = real_a->str + real_a->len; 1430 while (ap != a_end) 1431 { 1432 if (*ap != *bp) 1433 return FALSE; 1434 1435 ++ap; 1436 ++bp; 1437 } 1438 1439 _dbus_assert (*ap == '\0'); 1440 _dbus_assert (*bp == '\0'); 1441 1442 return TRUE; 1443} 1444 1445static const signed char base64_table[] = { 1446 /* 0 */ 'A', 1447 /* 1 */ 'B', 1448 /* 2 */ 'C', 1449 /* 3 */ 'D', 1450 /* 4 */ 'E', 1451 /* 5 */ 'F', 1452 /* 6 */ 'G', 1453 /* 7 */ 'H', 1454 /* 8 */ 'I', 1455 /* 9 */ 'J', 1456 /* 10 */ 'K', 1457 /* 11 */ 'L', 1458 /* 12 */ 'M', 1459 /* 13 */ 'N', 1460 /* 14 */ 'O', 1461 /* 15 */ 'P', 1462 /* 16 */ 'Q', 1463 /* 17 */ 'R', 1464 /* 18 */ 'S', 1465 /* 19 */ 'T', 1466 /* 20 */ 'U', 1467 /* 21 */ 'V', 1468 /* 22 */ 'W', 1469 /* 23 */ 'X', 1470 /* 24 */ 'Y', 1471 /* 25 */ 'Z', 1472 /* 26 */ 'a', 1473 /* 27 */ 'b', 1474 /* 28 */ 'c', 1475 /* 29 */ 'd', 1476 /* 30 */ 'e', 1477 /* 31 */ 'f', 1478 /* 32 */ 'g', 1479 /* 33 */ 'h', 1480 /* 34 */ 'i', 1481 /* 35 */ 'j', 1482 /* 36 */ 'k', 1483 /* 37 */ 'l', 1484 /* 38 */ 'm', 1485 /* 39 */ 'n', 1486 /* 40 */ 'o', 1487 /* 41 */ 'p', 1488 /* 42 */ 'q', 1489 /* 43 */ 'r', 1490 /* 44 */ 's', 1491 /* 45 */ 't', 1492 /* 46 */ 'u', 1493 /* 47 */ 'v', 1494 /* 48 */ 'w', 1495 /* 49 */ 'x', 1496 /* 50 */ 'y', 1497 /* 51 */ 'z', 1498 /* 52 */ '0', 1499 /* 53 */ '1', 1500 /* 54 */ '2', 1501 /* 55 */ '3', 1502 /* 56 */ '4', 1503 /* 57 */ '5', 1504 /* 58 */ '6', 1505 /* 59 */ '7', 1506 /* 60 */ '8', 1507 /* 61 */ '9', 1508 /* 62 */ '+', 1509 /* 63 */ '/' 1510}; 1511 1512/** The minimum char that's a valid char in Base64-encoded text */ 1513#define UNBASE64_MIN_CHAR (43) 1514/** The maximum char that's a valid char in Base64-encoded text */ 1515#define UNBASE64_MAX_CHAR (122) 1516/** Must subtract this from a char's integer value before offsetting 1517 * into unbase64_table 1518 */ 1519#define UNBASE64_TABLE_OFFSET UNBASE64_MIN_CHAR 1520static const signed char unbase64_table[] = { 1521 /* 43 + */ 62, 1522 /* 44 , */ -1, 1523 /* 45 - */ -1, 1524 /* 46 . */ -1, 1525 /* 47 / */ 63, 1526 /* 48 0 */ 52, 1527 /* 49 1 */ 53, 1528 /* 50 2 */ 54, 1529 /* 51 3 */ 55, 1530 /* 52 4 */ 56, 1531 /* 53 5 */ 57, 1532 /* 54 6 */ 58, 1533 /* 55 7 */ 59, 1534 /* 56 8 */ 60, 1535 /* 57 9 */ 61, 1536 /* 58 : */ -1, 1537 /* 59 ; */ -1, 1538 /* 60 < */ -1, 1539 /* 61 = */ -1, 1540 /* 62 > */ -1, 1541 /* 63 ? */ -1, 1542 /* 64 @ */ -1, 1543 /* 65 A */ 0, 1544 /* 66 B */ 1, 1545 /* 67 C */ 2, 1546 /* 68 D */ 3, 1547 /* 69 E */ 4, 1548 /* 70 F */ 5, 1549 /* 71 G */ 6, 1550 /* 72 H */ 7, 1551 /* 73 I */ 8, 1552 /* 74 J */ 9, 1553 /* 75 K */ 10, 1554 /* 76 L */ 11, 1555 /* 77 M */ 12, 1556 /* 78 N */ 13, 1557 /* 79 O */ 14, 1558 /* 80 P */ 15, 1559 /* 81 Q */ 16, 1560 /* 82 R */ 17, 1561 /* 83 S */ 18, 1562 /* 84 T */ 19, 1563 /* 85 U */ 20, 1564 /* 86 V */ 21, 1565 /* 87 W */ 22, 1566 /* 88 X */ 23, 1567 /* 89 Y */ 24, 1568 /* 90 Z */ 25, 1569 /* 91 [ */ -1, 1570 /* 92 \ */ -1, 1571 /* 93 ] */ -1, 1572 /* 94 ^ */ -1, 1573 /* 95 _ */ -1, 1574 /* 96 ` */ -1, 1575 /* 97 a */ 26, 1576 /* 98 b */ 27, 1577 /* 99 c */ 28, 1578 /* 100 d */ 29, 1579 /* 101 e */ 30, 1580 /* 102 f */ 31, 1581 /* 103 g */ 32, 1582 /* 104 h */ 33, 1583 /* 105 i */ 34, 1584 /* 106 j */ 35, 1585 /* 107 k */ 36, 1586 /* 108 l */ 37, 1587 /* 109 m */ 38, 1588 /* 110 n */ 39, 1589 /* 111 o */ 40, 1590 /* 112 p */ 41, 1591 /* 113 q */ 42, 1592 /* 114 r */ 43, 1593 /* 115 s */ 44, 1594 /* 116 t */ 45, 1595 /* 117 u */ 46, 1596 /* 118 v */ 47, 1597 /* 119 w */ 48, 1598 /* 120 x */ 49, 1599 /* 121 y */ 50, 1600 /* 122 z */ 51 1601}; 1602 1603/** 1604 * Encodes a string using Base64, as documented in RFC 2045. 1605 * 1606 * @param source the string to encode 1607 * @param start byte index to start encoding 1608 * @param dest string where encoded data should be placed 1609 * @param insert_at where to place encoded data 1610 * @returns #TRUE if encoding was successful, #FALSE if no memory etc. 1611 */ 1612dbus_bool_t 1613_dbus_string_base64_encode (const DBusString *source, 1614 int start, 1615 DBusString *dest, 1616 int insert_at) 1617{ 1618 int source_len; 1619 int dest_len; 1620 const unsigned char *s; 1621 unsigned char *d; 1622 const unsigned char *triplet_end; 1623 const unsigned char *final_end; 1624 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 1625 _dbus_assert (source != dest); 1626 1627 /* For each 24 bits (3 bytes) of input, we have 4 chars of 1628 * output. 1629 */ 1630 source_len = real_source->len - start; 1631 dest_len = (source_len / 3) * 4; 1632 if (source_len % 3 != 0) 1633 dest_len += 4; 1634 1635 if (source_len == 0) 1636 return TRUE; 1637 1638 if (!open_gap (dest_len, real_dest, insert_at)) 1639 return FALSE; 1640 1641 d = real_dest->str + insert_at; 1642 s = real_source->str + start; 1643 final_end = real_source->str + (start + source_len); 1644 triplet_end = final_end - (source_len % 3); 1645 _dbus_assert (triplet_end <= final_end); 1646 _dbus_assert ((final_end - triplet_end) < 3); 1647 1648#define ENCODE_64(v) (base64_table[ (unsigned char) (v) ]) 1649#define SIX_BITS_MASK (0x3f) 1650 _dbus_assert (SIX_BITS_MASK < _DBUS_N_ELEMENTS (base64_table)); 1651 1652 while (s != triplet_end) 1653 { 1654 unsigned int triplet; 1655 1656 triplet = s[0] | (s[1] << 8) | (s[2] << 16); 1657 1658 /* Encode each 6 bits */ 1659 1660 *d++ = ENCODE_64 (triplet >> 18); 1661 *d++ = ENCODE_64 ((triplet >> 12) & SIX_BITS_MASK); 1662 *d++ = ENCODE_64 ((triplet >> 6) & SIX_BITS_MASK); 1663 *d++ = ENCODE_64 (triplet & SIX_BITS_MASK); 1664 1665 s += 3; 1666 } 1667 1668 switch (final_end - triplet_end) 1669 { 1670 case 2: 1671 { 1672 unsigned int doublet; 1673 1674 doublet = s[0] | (s[1] << 8); 1675 1676 *d++ = ENCODE_64 (doublet >> 12); 1677 *d++ = ENCODE_64 ((doublet >> 6) & SIX_BITS_MASK); 1678 *d++ = ENCODE_64 (doublet & SIX_BITS_MASK); 1679 *d++ = '='; 1680 } 1681 break; 1682 case 1: 1683 { 1684 unsigned int singlet; 1685 1686 singlet = s[0]; 1687 1688 *d++ = ENCODE_64 ((singlet >> 6) & SIX_BITS_MASK); 1689 *d++ = ENCODE_64 (singlet & SIX_BITS_MASK); 1690 *d++ = '='; 1691 *d++ = '='; 1692 } 1693 break; 1694 case 0: 1695 break; 1696 } 1697 1698 _dbus_assert (d == (real_dest->str + (insert_at + dest_len))); 1699 1700 return TRUE; 1701} 1702 1703 1704/** 1705 * Decodes a string from Base64, as documented in RFC 2045. 1706 * 1707 * @param source the string to decode 1708 * @param start byte index to start decode 1709 * @param dest string where decoded data should be placed 1710 * @param insert_at where to place decoded data 1711 * @returns #TRUE if decoding was successful, #FALSE if no memory etc. 1712 */ 1713dbus_bool_t 1714_dbus_string_base64_decode (const DBusString *source, 1715 int start, 1716 DBusString *dest, 1717 int insert_at) 1718{ 1719 int source_len; 1720 const char *s; 1721 const char *end; 1722 DBusString result; 1723 unsigned int triplet = 0; 1724 int sextet_count; 1725 int pad_count; 1726 DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at); 1727 _dbus_assert (source != dest); 1728 1729 source_len = real_source->len - start; 1730 s = real_source->str + start; 1731 end = real_source->str + source_len; 1732 1733 if (source_len == 0) 1734 return TRUE; 1735 1736 if (!_dbus_string_init (&result, _DBUS_INT_MAX)) 1737 return FALSE; 1738 1739 pad_count = 0; 1740 sextet_count = 0; 1741 while (s != end) 1742 { 1743 /* The idea is to just skip anything that isn't 1744 * a base64 char - it's allowed to have whitespace, 1745 * newlines, etc. in here. We also ignore trailing 1746 * base64 chars, though that's suspicious. 1747 */ 1748 1749 if (*s >= UNBASE64_MIN_CHAR && 1750 *s <= UNBASE64_MAX_CHAR) 1751 { 1752 if (*s == '=') 1753 { 1754 /* '=' is padding, doesn't represent additional data 1755 * but does increment our count. 1756 */ 1757 pad_count += 1; 1758 sextet_count += 1; 1759 } 1760 else 1761 { 1762 int val; 1763 1764 val = unbase64_table[(*s) - UNBASE64_TABLE_OFFSET]; 1765 1766 if (val >= 0) 1767 { 1768 triplet <<= 6; 1769 triplet |= (unsigned int) val; 1770 sextet_count += 1; 1771 } 1772 } 1773 1774 if (sextet_count == 4) 1775 { 1776 /* no pad = 3 bytes, 1 pad = 2 bytes, 2 pad = 1 byte */ 1777 1778 _dbus_string_append_byte (&result, 1779 triplet & 0xff); 1780 1781 if (pad_count < 2) 1782 _dbus_string_append_byte (&result, 1783 (triplet >> 8) & 0xff); 1784 1785 if (pad_count < 1) 1786 _dbus_string_append_byte (&result, 1787 triplet >> 16); 1788 1789 sextet_count = 0; 1790 pad_count = 0; 1791 triplet = 0; 1792 } 1793 } 1794 1795 ++s; 1796 } 1797 1798 if (!_dbus_string_move (&result, 0, dest, insert_at)) 1799 { 1800 _dbus_string_free (&result); 1801 return FALSE; 1802 } 1803 1804 _dbus_string_free (&result); 1805 1806 return TRUE; 1807} 1808 1809/** 1810 * Checks that the given range of the string 1811 * is valid ASCII. If the given range is not contained 1812 * in the string, returns #FALSE. 1813 * 1814 * @param str the string 1815 * @param start first byte index to check 1816 * @param len number of bytes to check 1817 * @returns #TRUE if the byte range exists and is all valid ASCII 1818 */ 1819dbus_bool_t 1820_dbus_string_validate_ascii (const DBusString *str, 1821 int start, 1822 int len) 1823{ 1824 const unsigned char *s; 1825 const unsigned char *end; 1826 DBUS_CONST_STRING_PREAMBLE (str); 1827 _dbus_assert (start >= 0); 1828 _dbus_assert (len >= 0); 1829 1830 if ((start + len) > real->len) 1831 return FALSE; 1832 1833 s = real->str + start; 1834 end = s + len; 1835 while (s != end) 1836 { 1837 if (*s == '\0' || 1838 ((*s & ~0x7f) != 0)) 1839 return FALSE; 1840 1841 ++s; 1842 } 1843 1844 return TRUE; 1845} 1846 1847/** @} */ 1848 1849#ifdef DBUS_BUILD_TESTS 1850#include "dbus-test.h" 1851#include <stdio.h> 1852 1853static void 1854test_max_len (DBusString *str, 1855 int max_len) 1856{ 1857 if (max_len > 0) 1858 { 1859 if (!_dbus_string_set_length (str, max_len - 1)) 1860 _dbus_assert_not_reached ("setting len to one less than max should have worked"); 1861 } 1862 1863 if (!_dbus_string_set_length (str, max_len)) 1864 _dbus_assert_not_reached ("setting len to max len should have worked"); 1865 1866 if (_dbus_string_set_length (str, max_len + 1)) 1867 _dbus_assert_not_reached ("setting len to one more than max len should not have worked"); 1868 1869 if (!_dbus_string_set_length (str, 0)) 1870 _dbus_assert_not_reached ("setting len to zero should have worked"); 1871} 1872 1873static void 1874test_base64_roundtrip (const unsigned char *data, 1875 int len) 1876{ 1877 DBusString orig; 1878 DBusString encoded; 1879 DBusString decoded; 1880 1881 if (len < 0) 1882 len = strlen (data); 1883 1884 if (!_dbus_string_init (&orig, _DBUS_INT_MAX)) 1885 _dbus_assert_not_reached ("could not init string"); 1886 1887 if (!_dbus_string_init (&encoded, _DBUS_INT_MAX)) 1888 _dbus_assert_not_reached ("could not init string"); 1889 1890 if (!_dbus_string_init (&decoded, _DBUS_INT_MAX)) 1891 _dbus_assert_not_reached ("could not init string"); 1892 1893 if (!_dbus_string_append_len (&orig, data, len)) 1894 _dbus_assert_not_reached ("couldn't append orig data"); 1895 1896 if (!_dbus_string_base64_encode (&orig, 0, &encoded, 0)) 1897 _dbus_assert_not_reached ("could not encode"); 1898 1899 if (!_dbus_string_base64_decode (&encoded, 0, &decoded, 0)) 1900 _dbus_assert_not_reached ("could not decode"); 1901 1902 if (!_dbus_string_equal (&orig, &decoded)) 1903 { 1904 const char *s; 1905 1906 printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n", 1907 _dbus_string_get_length (&orig), 1908 _dbus_string_get_length (&encoded), 1909 _dbus_string_get_length (&decoded)); 1910 printf ("Original: %s\n", data); 1911 _dbus_string_get_const_data (&decoded, &s); 1912 printf ("Decoded: %s\n", s); 1913 _dbus_assert_not_reached ("original string not the same as string decoded from base64"); 1914 } 1915 1916 _dbus_string_free (&orig); 1917 _dbus_string_free (&encoded); 1918 _dbus_string_free (&decoded); 1919} 1920 1921/** 1922 * @ingroup DBusStringInternals 1923 * Unit test for DBusString. 1924 * 1925 * @todo Need to write tests for _dbus_string_copy() and 1926 * _dbus_string_move() moving to/from each of start/middle/end of a 1927 * string. Also need tests for _dbus_string_move_len () 1928 * 1929 * @returns #TRUE on success. 1930 */ 1931dbus_bool_t 1932_dbus_string_test (void) 1933{ 1934 DBusString str; 1935 DBusString other; 1936 int i, end; 1937 long v; 1938 double d; 1939 int lens[] = { 0, 1, 2, 3, 4, 5, 10, 16, 17, 18, 25, 31, 32, 33, 34, 35, 63, 64, 65, 66, 67, 68, 69, 70, 71, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136 }; 1940 char *s; 1941 dbus_unichar_t ch; 1942 1943 i = 0; 1944 while (i < _DBUS_N_ELEMENTS (lens)) 1945 { 1946 if (!_dbus_string_init (&str, lens[i])) 1947 _dbus_assert_not_reached ("failed to init string"); 1948 1949 test_max_len (&str, lens[i]); 1950 _dbus_string_free (&str); 1951 1952 ++i; 1953 } 1954 1955 /* Test shortening and setting length */ 1956 i = 0; 1957 while (i < _DBUS_N_ELEMENTS (lens)) 1958 { 1959 int j; 1960 1961 if (!_dbus_string_init (&str, lens[i])) 1962 _dbus_assert_not_reached ("failed to init string"); 1963 1964 if (!_dbus_string_set_length (&str, lens[i])) 1965 _dbus_assert_not_reached ("failed to set string length"); 1966 1967 j = lens[i]; 1968 while (j > 0) 1969 { 1970 _dbus_assert (_dbus_string_get_length (&str) == j); 1971 if (j > 0) 1972 { 1973 _dbus_string_shorten (&str, 1); 1974 _dbus_assert (_dbus_string_get_length (&str) == (j - 1)); 1975 } 1976 --j; 1977 } 1978 1979 _dbus_string_free (&str); 1980 1981 ++i; 1982 } 1983 1984 /* Test appending data */ 1985 if (!_dbus_string_init (&str, _DBUS_INT_MAX)) 1986 _dbus_assert_not_reached ("failed to init string"); 1987 1988 i = 0; 1989 while (i < 10) 1990 { 1991 if (!_dbus_string_append (&str, "a")) 1992 _dbus_assert_not_reached ("failed to append string to string\n"); 1993 1994 _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1); 1995 1996 if (!_dbus_string_append_byte (&str, 'b')) 1997 _dbus_assert_not_reached ("failed to append byte to string\n"); 1998 1999 _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2); 2000 2001 ++i; 2002 } 2003 2004 _dbus_string_free (&str); 2005 2006 /* Check steal_data */ 2007 2008 if (!_dbus_string_init (&str, _DBUS_INT_MAX)) 2009 _dbus_assert_not_reached ("failed to init string"); 2010 2011 if (!_dbus_string_append (&str, "Hello World")) 2012 _dbus_assert_not_reached ("could not append to string"); 2013 2014 i = _dbus_string_get_length (&str); 2015 2016 if (!_dbus_string_steal_data (&str, &s)) 2017 _dbus_assert_not_reached ("failed to steal data"); 2018 2019 _dbus_assert (_dbus_string_get_length (&str) == 0); 2020 _dbus_assert (((int)strlen (s)) == i); 2021 2022 dbus_free (s); 2023 2024 /* Check move */ 2025 2026 if (!_dbus_string_append (&str, "Hello World")) 2027 _dbus_assert_not_reached ("could not append to string"); 2028 2029 i = _dbus_string_get_length (&str); 2030 2031 if (!_dbus_string_init (&other, _DBUS_INT_MAX)) 2032 _dbus_assert_not_reached ("could not init string"); 2033 2034 if (!_dbus_string_move (&str, 0, &other, 0)) 2035 _dbus_assert_not_reached ("could not move"); 2036 2037 _dbus_assert (_dbus_string_get_length (&str) == 0); 2038 _dbus_assert (_dbus_string_get_length (&other) == i); 2039 2040 if (!_dbus_string_append (&str, "Hello World")) 2041 _dbus_assert_not_reached ("could not append to string"); 2042 2043 if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other))) 2044 _dbus_assert_not_reached ("could not move"); 2045 2046 _dbus_assert (_dbus_string_get_length (&str) == 0); 2047 _dbus_assert (_dbus_string_get_length (&other) == i * 2); 2048 2049 if (!_dbus_string_append (&str, "Hello World")) 2050 _dbus_assert_not_reached ("could not append to string"); 2051 2052 if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2)) 2053 _dbus_assert_not_reached ("could not move"); 2054 2055 _dbus_assert (_dbus_string_get_length (&str) == 0); 2056 _dbus_assert (_dbus_string_get_length (&other) == i * 3); 2057 2058 _dbus_string_free (&other); 2059 2060 /* Check copy */ 2061 2062 if (!_dbus_string_append (&str, "Hello World")) 2063 _dbus_assert_not_reached ("could not append to string"); 2064 2065 i = _dbus_string_get_length (&str); 2066 2067 if (!_dbus_string_init (&other, _DBUS_INT_MAX)) 2068 _dbus_assert_not_reached ("could not init string"); 2069 2070 if (!_dbus_string_copy (&str, 0, &other, 0)) 2071 _dbus_assert_not_reached ("could not copy"); 2072 2073 _dbus_assert (_dbus_string_get_length (&str) == i); 2074 _dbus_assert (_dbus_string_get_length (&other) == i); 2075 2076 if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other))) 2077 _dbus_assert_not_reached ("could not copy"); 2078 2079 _dbus_assert (_dbus_string_get_length (&str) == i); 2080 _dbus_assert (_dbus_string_get_length (&other) == i * 2); 2081 _dbus_assert (_dbus_string_equal_c_str (&other, 2082 "Hello WorldHello World")); 2083 2084 if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2)) 2085 _dbus_assert_not_reached ("could not copy"); 2086 2087 _dbus_assert (_dbus_string_get_length (&str) == i); 2088 _dbus_assert (_dbus_string_get_length (&other) == i * 3); 2089 _dbus_assert (_dbus_string_equal_c_str (&other, 2090 "Hello WorldHello WorldHello World")); 2091 2092 _dbus_string_free (&str); 2093 _dbus_string_free (&other); 2094 2095 /* Check replace */ 2096 2097 if (!_dbus_string_init (&str, _DBUS_INT_MAX)) 2098 _dbus_assert_not_reached ("failed to init string"); 2099 2100 if (!_dbus_string_append (&str, "Hello World")) 2101 _dbus_assert_not_reached ("could not append to string"); 2102 2103 i = _dbus_string_get_length (&str); 2104 2105 if (!_dbus_string_init (&other, _DBUS_INT_MAX)) 2106 _dbus_assert_not_reached ("could not init string"); 2107 2108 if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str), 2109 &other, 0, _dbus_string_get_length (&other))) 2110 _dbus_assert_not_reached ("could not replace"); 2111 2112 _dbus_assert (_dbus_string_get_length (&str) == i); 2113 _dbus_assert (_dbus_string_get_length (&other) == i); 2114 _dbus_assert (_dbus_string_equal_c_str (&other, "Hello World")); 2115 2116 if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str), 2117 &other, 5, 1)) 2118 _dbus_assert_not_reached ("could not replace center space"); 2119 2120 _dbus_assert (_dbus_string_get_length (&str) == i); 2121 _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1); 2122 _dbus_assert (_dbus_string_equal_c_str (&other, 2123 "HelloHello WorldWorld")); 2124 2125 2126 if (!_dbus_string_replace_len (&str, 1, 1, 2127 &other, 2128 _dbus_string_get_length (&other) - 1, 2129 1)) 2130 _dbus_assert_not_reached ("could not replace end character"); 2131 2132 _dbus_assert (_dbus_string_get_length (&str) == i); 2133 _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1); 2134 _dbus_assert (_dbus_string_equal_c_str (&other, 2135 "HelloHello WorldWorle")); 2136 2137 _dbus_string_free (&str); 2138 _dbus_string_free (&other); 2139 2140 /* Check append/get unichar */ 2141 2142 if (!_dbus_string_init (&str, _DBUS_INT_MAX)) 2143 _dbus_assert_not_reached ("failed to init string"); 2144 2145 ch = 0; 2146 if (!_dbus_string_append_unichar (&str, 0xfffc)) 2147 _dbus_assert_not_reached ("failed to append unichar"); 2148 2149 _dbus_string_get_unichar (&str, 0, &ch, &i); 2150 2151 _dbus_assert (ch == 0xfffc); 2152 _dbus_assert (i == _dbus_string_get_length (&str)); 2153 2154 _dbus_string_free (&str); 2155 2156 /* Check append/parse int/double */ 2157 2158 if (!_dbus_string_init (&str, _DBUS_INT_MAX)) 2159 _dbus_assert_not_reached ("failed to init string"); 2160 2161 if (!_dbus_string_append_int (&str, 27)) 2162 _dbus_assert_not_reached ("failed to append int"); 2163 2164 i = _dbus_string_get_length (&str); 2165 2166 if (!_dbus_string_parse_int (&str, 0, &v, &end)) 2167 _dbus_assert_not_reached ("failed to parse int"); 2168 2169 _dbus_assert (v == 27); 2170 _dbus_assert (end == i); 2171 2172 _dbus_string_free (&str); 2173 2174 if (!_dbus_string_init (&str, _DBUS_INT_MAX)) 2175 _dbus_assert_not_reached ("failed to init string"); 2176 2177 if (!_dbus_string_append_double (&str, 50.3)) 2178 _dbus_assert_not_reached ("failed to append float"); 2179 2180 i = _dbus_string_get_length (&str); 2181 2182 if (!_dbus_string_parse_double (&str, 0, &d, &end)) 2183 _dbus_assert_not_reached ("failed to parse float"); 2184 2185 _dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6)); 2186 _dbus_assert (end == i); 2187 2188 _dbus_string_free (&str); 2189 2190 /* Test find */ 2191 if (!_dbus_string_init (&str, _DBUS_INT_MAX)) 2192 _dbus_assert_not_reached ("failed to init string"); 2193 2194 if (!_dbus_string_append (&str, "Hello")) 2195 _dbus_assert_not_reached ("couldn't append to string"); 2196 2197 if (!_dbus_string_find (&str, 0, "He", &i)) 2198 _dbus_assert_not_reached ("didn't find 'He'"); 2199 _dbus_assert (i == 0); 2200 2201 if (!_dbus_string_find (&str, 0, "ello", &i)) 2202 _dbus_assert_not_reached ("didn't find 'ello'"); 2203 _dbus_assert (i == 1); 2204 2205 if (!_dbus_string_find (&str, 0, "lo", &i)) 2206 _dbus_assert_not_reached ("didn't find 'lo'"); 2207 _dbus_assert (i == 3); 2208 2209 if (!_dbus_string_find (&str, 2, "lo", &i)) 2210 _dbus_assert_not_reached ("didn't find 'lo'"); 2211 _dbus_assert (i == 3); 2212 2213 if (_dbus_string_find (&str, 4, "lo", &i)) 2214 _dbus_assert_not_reached ("did find 'lo'"); 2215 2216 if (!_dbus_string_find (&str, 0, "l", &i)) 2217 _dbus_assert_not_reached ("didn't find 'l'"); 2218 _dbus_assert (i == 2); 2219 2220 if (!_dbus_string_find (&str, 0, "H", &i)) 2221 _dbus_assert_not_reached ("didn't find 'H'"); 2222 _dbus_assert (i == 0); 2223 2224 if (!_dbus_string_find (&str, 0, "", &i)) 2225 _dbus_assert_not_reached ("didn't find ''"); 2226 _dbus_assert (i == 0); 2227 2228 if (_dbus_string_find (&str, 0, "Hello!", NULL)) 2229 _dbus_assert_not_reached ("Did find 'Hello!'"); 2230 2231 if (_dbus_string_find (&str, 0, "Oh, Hello", NULL)) 2232 _dbus_assert_not_reached ("Did find 'Oh, Hello'"); 2233 2234 if (_dbus_string_find (&str, 0, "ill", NULL)) 2235 _dbus_assert_not_reached ("Did find 'ill'"); 2236 2237 if (_dbus_string_find (&str, 0, "q", NULL)) 2238 _dbus_assert_not_reached ("Did find 'q'"); 2239 2240 _dbus_string_free (&str); 2241 2242 /* Base 64 */ 2243 test_base64_roundtrip ("Hello this is a string\n", -1); 2244 test_base64_roundtrip ("Hello this is a string\n1", -1); 2245 test_base64_roundtrip ("Hello this is a string\n12", -1); 2246 test_base64_roundtrip ("Hello this is a string\n123", -1); 2247 test_base64_roundtrip ("Hello this is a string\n1234", -1); 2248 test_base64_roundtrip ("Hello this is a string\n12345", -1); 2249 test_base64_roundtrip ("", 0); 2250 test_base64_roundtrip ("1", 1); 2251 test_base64_roundtrip ("12", 2); 2252 test_base64_roundtrip ("123", 3); 2253 test_base64_roundtrip ("1234", 4); 2254 test_base64_roundtrip ("12345", 5); 2255 test_base64_roundtrip ("", 1); 2256 test_base64_roundtrip ("1", 2); 2257 test_base64_roundtrip ("12", 3); 2258 test_base64_roundtrip ("123", 4); 2259 test_base64_roundtrip ("1234", 5); 2260 test_base64_roundtrip ("12345", 6); 2261 { 2262 unsigned char buf[512]; 2263 i = 0; 2264 while (i < _DBUS_N_ELEMENTS (buf)) 2265 { 2266 buf[i] = i; 2267 ++i; 2268 } 2269 i = 0; 2270 while (i < _DBUS_N_ELEMENTS (buf)) 2271 { 2272 test_base64_roundtrip (buf, i); 2273 ++i; 2274 } 2275 } 2276 2277 return TRUE; 2278} 2279 2280#endif /* DBUS_BUILD_TESTS */ 2281