2004-03-01 David Zeuthen <david@fubar.dk>
[platform/upstream/dbus.git] / dbus / dbus-string.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-string.c String utility class (internal to D-BUS implementation)
3  * 
4  * Copyright (C) 2002, 2003 Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 2.0
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 /* for vsnprintf */
29 #include <stdio.h>
30 #include "dbus-marshal.h"
31 #define DBUS_CAN_USE_DBUS_STRING_PRIVATE 1
32 #include "dbus-string-private.h"
33 #include "dbus-protocol.h"
34 /* for DBUS_VA_COPY */
35 #include "dbus-sysdeps.h"
36
37 /**
38  * @defgroup DBusString string class
39  * @ingroup  DBusInternals
40  * @brief DBusString data structure
41  *
42  * Types and functions related to DBusString. DBusString is intended
43  * to be a string class that makes it hard to mess up security issues
44  * (and just in general harder to write buggy code).  It should be
45  * used (or extended and then used) rather than the libc stuff in
46  * string.h.  The string class is a bit inconvenient at spots because
47  * it handles out-of-memory failures and tries to be extra-robust.
48  * 
49  * A DBusString has a maximum length set at initialization time; this
50  * can be used to ensure that a buffer doesn't get too big.  The
51  * _dbus_string_lengthen() method checks for overflow, and for max
52  * length being exceeded.
53  * 
54  * Try to avoid conversion to a plain C string, i.e. add methods on
55  * the string object instead, only convert to C string when passing
56  * things out to the public API. In particular, no sprintf, strcpy,
57  * strcat, any of that should be used. The GString feature of
58  * accepting negative numbers for "length of string" is also absent,
59  * because it could keep us from detecting bogus huge lengths. i.e. if
60  * we passed in some bogus huge length it would be taken to mean
61  * "current length of string" instead of "broken crack"
62  */
63
64 /**
65  * @defgroup DBusStringInternals DBusString implementation details
66  * @ingroup  DBusInternals
67  * @brief DBusString implementation details
68  *
69  * The guts of DBusString.
70  *
71  * @{
72  */
73
74 /**
75  * We allocate 1 byte for nul termination, plus 7 bytes for possible
76  * align_offset, so we always need 8 bytes on top of the string's
77  * length to be in the allocated block.
78  */
79 #define ALLOCATION_PADDING 8
80
81 /**
82  * This is the maximum max length (and thus also the maximum length)
83  * of a DBusString
84  */
85 #define MAX_MAX_LENGTH (_DBUS_INT_MAX - ALLOCATION_PADDING)
86
87 /**
88  * Checks a bunch of assertions about a string object
89  *
90  * @param real the DBusRealString
91  */
92 #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 - ALLOCATION_PADDING)); _dbus_assert ((real)->len <= (real)->max_length)
93
94 /**
95  * Checks assertions about a string object that needs to be
96  * modifiable - may not be locked or const. Also declares
97  * the "real" variable pointing to DBusRealString. 
98  * @param str the string
99  */
100 #define DBUS_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
101   DBUS_GENERIC_STRING_PREAMBLE (real);                                          \
102   _dbus_assert (!(real)->constant);                                             \
103   _dbus_assert (!(real)->locked)
104
105 /**
106  * Checks assertions about a string object that may be locked but
107  * can't be const. i.e. a string object that we can free.  Also
108  * declares the "real" variable pointing to DBusRealString.
109  *
110  * @param str the string
111  */
112 #define DBUS_LOCKED_STRING_PREAMBLE(str) DBusRealString *real = (DBusRealString*) str; \
113   DBUS_GENERIC_STRING_PREAMBLE (real);                                                 \
114   _dbus_assert (!(real)->constant)
115
116 /**
117  * Checks assertions about a string that may be const or locked.  Also
118  * declares the "real" variable pointing to DBusRealString.
119  * @param str the string.
120  */
121 #define DBUS_CONST_STRING_PREAMBLE(str) const DBusRealString *real = (DBusRealString*) str; \
122   DBUS_GENERIC_STRING_PREAMBLE (real)
123
124 /** @} */
125
126 /**
127  * @addtogroup DBusString
128  * @{
129  */
130
131 static void
132 fixup_alignment (DBusRealString *real)
133 {
134   char *aligned;
135   char *real_block;
136   unsigned int old_align_offset;
137
138   /* we have to have extra space in real->allocated for the align offset and nul byte */
139   _dbus_assert (real->len <= real->allocated - ALLOCATION_PADDING);
140   
141   old_align_offset = real->align_offset;
142   real_block = real->str - old_align_offset;
143   
144   aligned = _DBUS_ALIGN_ADDRESS (real_block, 8);
145
146   real->align_offset = aligned - real_block;
147   real->str = aligned;
148   
149   if (old_align_offset != real->align_offset)
150     {
151       /* Here comes the suck */
152       memmove (real_block + real->align_offset,
153                real_block + old_align_offset,
154                real->len + 1);
155     }
156
157   _dbus_assert (real->align_offset < 8);
158   _dbus_assert (_DBUS_ALIGN_ADDRESS (real->str, 8) == real->str);
159 }
160
161 static void
162 undo_alignment (DBusRealString *real)
163 {
164   if (real->align_offset != 0)
165     {
166       memmove (real->str - real->align_offset,
167                real->str,
168                real->len + 1);
169
170       real->str = real->str - real->align_offset;
171       real->align_offset = 0;
172     }
173 }
174
175 /**
176  * Initializes a string that can be up to the given allocation size
177  * before it has to realloc. The string starts life with zero length.
178  * The string must eventually be freed with _dbus_string_free().
179  * 
180  * @param str memory to hold the string
181  * @param allocate_size amount to preallocate
182  * @returns #TRUE on success, #FALSE if no memory
183  */
184 dbus_bool_t
185 _dbus_string_init_preallocated (DBusString *str,
186                                 int         allocate_size)
187 {
188   DBusRealString *real;
189   
190   _dbus_assert (str != NULL);
191
192   _dbus_assert (sizeof (DBusString) == sizeof (DBusRealString));
193   
194   real = (DBusRealString*) str;
195
196   /* It's very important not to touch anything
197    * other than real->str if we're going to fail,
198    * since we also use this function to reset
199    * an existing string, e.g. in _dbus_string_steal_data()
200    */
201   
202   real->str = dbus_malloc (ALLOCATION_PADDING + allocate_size);
203   if (real->str == NULL)
204     return FALSE;  
205   
206   real->allocated = ALLOCATION_PADDING + allocate_size;
207   real->len = 0;
208   real->str[real->len] = '\0';
209   
210   real->max_length = MAX_MAX_LENGTH;
211   real->constant = FALSE;
212   real->locked = FALSE;
213   real->invalid = FALSE;
214   real->align_offset = 0;
215   
216   fixup_alignment (real);
217   
218   return TRUE;
219 }
220
221 /**
222  * Initializes a string. The string starts life with zero length.  The
223  * string must eventually be freed with _dbus_string_free().
224  * 
225  * @param str memory to hold the string
226  * @returns #TRUE on success, #FALSE if no memory
227  */
228 dbus_bool_t
229 _dbus_string_init (DBusString *str)
230 {
231   return _dbus_string_init_preallocated (str, 0);
232 }
233
234 /* The max length thing is sort of a historical artifact
235  * from a feature that turned out to be dumb; perhaps
236  * we should purge it entirely. The problem with
237  * the feature is that it looks like memory allocation
238  * failure, but is not a transient or resolvable failure.
239  */
240 static void
241 set_max_length (DBusString *str,
242                 int         max_length)
243 {
244   DBusRealString *real;
245   
246   real = (DBusRealString*) str;
247
248   real->max_length = max_length;
249 }
250
251 /**
252  * Initializes a constant string. The value parameter is not copied
253  * (should be static), and the string may never be modified.
254  * It is safe but not necessary to call _dbus_string_free()
255  * on a const string. The string has a length limit of MAXINT - 8.
256  * 
257  * @param str memory to use for the string
258  * @param value a string to be stored in str (not copied!!!)
259  */
260 void
261 _dbus_string_init_const (DBusString *str,
262                          const char *value)
263 {
264   _dbus_assert (value != NULL);
265   
266   _dbus_string_init_const_len (str, value,
267                                strlen (value));
268 }
269
270 /**
271  * Initializes a constant string with a length. The value parameter is
272  * not copied (should be static), and the string may never be
273  * modified.  It is safe but not necessary to call _dbus_string_free()
274  * on a const string.
275  * 
276  * @param str memory to use for the string
277  * @param value a string to be stored in str (not copied!!!)
278  * @param len the length to use
279  */
280 void
281 _dbus_string_init_const_len (DBusString *str,
282                              const char *value,
283                              int         len)
284 {
285   DBusRealString *real;
286   
287   _dbus_assert (str != NULL);
288   _dbus_assert (value != NULL);
289   _dbus_assert (len <= MAX_MAX_LENGTH);
290   _dbus_assert (len >= 0);
291   
292   real = (DBusRealString*) str;
293   
294   real->str = (char*) value;
295   real->len = len;
296   real->allocated = real->len + ALLOCATION_PADDING; /* a lie, just to avoid special-case assertions... */
297   real->max_length = real->len + 1;
298   real->constant = TRUE;
299   real->invalid = FALSE;
300
301   /* We don't require const strings to be 8-byte aligned as the
302    * memory is coming from elsewhere.
303    */
304 }
305
306 /**
307  * Frees a string created by _dbus_string_init().
308  *
309  * @param str memory where the string is stored.
310  */
311 void
312 _dbus_string_free (DBusString *str)
313 {
314   DBusRealString *real = (DBusRealString*) str;
315   DBUS_GENERIC_STRING_PREAMBLE (real);
316   
317   if (real->constant)
318     return;
319   dbus_free (real->str - real->align_offset);
320
321   real->invalid = TRUE;
322 }
323
324 #ifdef DBUS_BUILD_TESTS
325 /* Not using this feature at the moment,
326  * so marked DBUS_BUILD_TESTS-only
327  */
328 /**
329  * Locks a string such that any attempts to change the string will
330  * result in aborting the program. Also, if the string is wasting a
331  * lot of memory (allocation is sufficiently larger than what the
332  * string is really using), _dbus_string_lock() will realloc the
333  * string's data to "compact" it.
334  *
335  * @param str the string to lock.
336  */
337 void
338 _dbus_string_lock (DBusString *str)
339 {  
340   DBUS_LOCKED_STRING_PREAMBLE (str); /* can lock multiple times */
341
342   real->locked = TRUE;
343
344   /* Try to realloc to avoid excess memory usage, since
345    * we know we won't change the string further
346    */
347 #define MAX_WASTE 48
348   if (real->allocated - MAX_WASTE > real->len)
349     {
350       char *new_str;
351       int new_allocated;
352
353       new_allocated = real->len + ALLOCATION_PADDING;
354
355       new_str = dbus_realloc (real->str - real->align_offset,
356                               new_allocated);
357       if (new_str != NULL)
358         {
359           real->str = new_str + real->align_offset;
360           real->allocated = new_allocated;
361           fixup_alignment (real);
362         }
363     }
364 }
365 #endif /* DBUS_BUILD_TESTS */
366
367 static dbus_bool_t
368 reallocate_for_length (DBusRealString *real,
369                        int             new_length)
370 {
371   int new_allocated;
372   char *new_str;
373
374   /* at least double our old allocation to avoid O(n), avoiding
375    * overflow
376    */
377   if (real->allocated > (MAX_MAX_LENGTH + ALLOCATION_PADDING) / 2)
378     new_allocated = MAX_MAX_LENGTH + ALLOCATION_PADDING;
379   else
380     new_allocated = real->allocated * 2;
381
382   /* if you change the code just above here, run the tests without
383    * the following before you commit
384    */
385 #ifdef DBUS_BUILD_TESTS
386   new_allocated = 0; /* ensure a realloc every time so that we go
387                       * through all malloc failure codepaths
388                       */
389 #endif
390       
391   /* But be sure we always alloc at least space for the new length */
392   new_allocated = MAX (new_allocated, new_length + ALLOCATION_PADDING);
393
394   _dbus_assert (new_allocated >= real->allocated); /* code relies on this */
395   new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
396   if (new_str == NULL)
397     return FALSE;
398
399   real->str = new_str + real->align_offset;
400   real->allocated = new_allocated;
401   fixup_alignment (real);
402
403   return TRUE;
404 }
405
406 static dbus_bool_t
407 set_length (DBusRealString *real,
408             int             new_length)
409 {
410   /* Note, we are setting the length not including nul termination */
411
412   /* exceeding max length is the same as failure to allocate memory */
413   if (new_length > real->max_length)
414     return FALSE;
415   else if (new_length > (real->allocated - ALLOCATION_PADDING) &&
416            !reallocate_for_length (real, new_length))
417     return FALSE;
418   else
419     {
420       real->len = new_length;
421       real->str[real->len] = '\0';
422       return TRUE;
423     }
424 }
425
426 static dbus_bool_t
427 open_gap (int             len,
428           DBusRealString *dest,
429           int             insert_at)
430 {
431   if (len == 0)
432     return TRUE;
433
434   if (len > dest->max_length - dest->len)
435     return FALSE; /* detected overflow of dest->len + len below */
436   
437   if (!set_length (dest, dest->len + len))
438     return FALSE;
439
440   memmove (dest->str + insert_at + len, 
441            dest->str + insert_at,
442            dest->len - len - insert_at);
443
444   return TRUE;
445 }
446
447 /**
448  * Gets the raw character buffer from the string.  The returned buffer
449  * will be nul-terminated, but note that strings may contain binary
450  * data so there may be extra nul characters prior to the termination.
451  * This function should be little-used, extend DBusString or add
452  * stuff to dbus-sysdeps.c instead. It's an error to use this
453  * function on a const string.
454  *
455  * @param str the string
456  * @returns the data
457  */
458 char*
459 _dbus_string_get_data (DBusString *str)
460 {
461   DBUS_STRING_PREAMBLE (str);
462   
463   return real->str;
464 }
465
466 /**
467  * Gets the raw character buffer from a const string.
468  *
469  * @param str the string
470  * @returns the string data
471  */
472 const char*
473 _dbus_string_get_const_data (const DBusString  *str)
474 {
475   DBUS_CONST_STRING_PREAMBLE (str);
476   
477   return real->str;
478 }
479
480 /**
481  * Gets a sub-portion of the raw character buffer from the
482  * string. The "len" field is required simply for error
483  * checking, to be sure you don't try to use more
484  * string than exists. The nul termination of the
485  * returned buffer remains at the end of the entire
486  * string, not at start + len.
487  *
488  * @param str the string
489  * @param start byte offset to return
490  * @param len length of segment to return
491  * @returns the string data
492  */
493 char*
494 _dbus_string_get_data_len (DBusString *str,
495                            int         start,
496                            int         len)
497 {
498   DBUS_STRING_PREAMBLE (str);
499   _dbus_assert (start >= 0);
500   _dbus_assert (len >= 0);
501   _dbus_assert (start <= real->len);
502   _dbus_assert (len <= real->len - start);
503   
504   return real->str + start;
505 }
506
507 /**
508  * const version of _dbus_string_get_data_len().
509  *
510  * @param str the string
511  * @param start byte offset to return
512  * @param len length of segment to return
513  * @returns the string data
514  */
515 const char*
516 _dbus_string_get_const_data_len (const DBusString  *str,
517                                  int                start,
518                                  int                len)
519 {
520   DBUS_CONST_STRING_PREAMBLE (str);
521   _dbus_assert (start >= 0);
522   _dbus_assert (len >= 0);
523   _dbus_assert (start <= real->len);
524   _dbus_assert (len <= real->len - start);
525   
526   return real->str + start;
527 }
528
529 /**
530  * Sets the value of the byte at the given position.
531  *
532  * @param str the string
533  * @param i the position
534  * @param byte the new value
535  */
536 void
537 _dbus_string_set_byte (DBusString    *str,
538                        int            i,
539                        unsigned char  byte)
540 {
541   DBUS_STRING_PREAMBLE (str);
542   _dbus_assert (i < real->len);
543   _dbus_assert (i >= 0);
544   
545   real->str[i] = byte;
546 }
547
548 /**
549  * Gets the byte at the given position. It is
550  * allowed to ask for the nul byte at the end of
551  * the string.
552  *
553  * @param str the string
554  * @param start the position
555  * @returns the byte at that position
556  */
557 unsigned char
558 _dbus_string_get_byte (const DBusString  *str,
559                        int                start)
560 {
561   DBUS_CONST_STRING_PREAMBLE (str);
562   _dbus_assert (start <= real->len);
563   _dbus_assert (start >= 0);
564   
565   return real->str[start];
566 }
567
568 /**
569  * Inserts a number of bytes of a given value at the
570  * given position.
571  *
572  * @param str the string
573  * @param i the position
574  * @param n_bytes number of bytes
575  * @param byte the value to insert
576  * @returns #TRUE on success
577  */
578 dbus_bool_t
579 _dbus_string_insert_bytes (DBusString   *str,
580                            int           i,
581                            int           n_bytes,
582                            unsigned char byte)
583 {
584   DBUS_STRING_PREAMBLE (str);
585   _dbus_assert (i <= real->len);
586   _dbus_assert (i >= 0);
587   _dbus_assert (n_bytes >= 0);
588
589   if (n_bytes == 0)
590     return TRUE;
591   
592   if (!open_gap (n_bytes, real, i))
593     return FALSE;
594   
595   memset (real->str + i, byte, n_bytes);
596
597   return TRUE;
598 }
599
600 /**
601  * Like _dbus_string_get_data(), but removes the
602  * gotten data from the original string. The caller
603  * must free the data returned. This function may
604  * fail due to lack of memory, and return #FALSE.
605  *
606  * @param str the string
607  * @param data_return location to return the buffer
608  * @returns #TRUE on success
609  */
610 dbus_bool_t
611 _dbus_string_steal_data (DBusString        *str,
612                          char             **data_return)
613 {
614   int old_max_length;
615   DBUS_STRING_PREAMBLE (str);
616   _dbus_assert (data_return != NULL);
617
618   undo_alignment (real);
619   
620   *data_return = real->str;
621
622   old_max_length = real->max_length;
623   
624   /* reset the string */
625   if (!_dbus_string_init (str))
626     {
627       /* hrm, put it back then */
628       real->str = *data_return;
629       *data_return = NULL;
630       fixup_alignment (real);
631       return FALSE;
632     }
633
634   real->max_length = old_max_length;
635
636   return TRUE;
637 }
638
639 /**
640  * Like _dbus_string_get_data_len(), but removes the gotten data from
641  * the original string. The caller must free the data returned. This
642  * function may fail due to lack of memory, and return #FALSE.
643  * The returned string is nul-terminated and has length len.
644  *
645  * @todo this function is broken because on failure it
646  * may corrupt the source string.
647  * 
648  * @param str the string
649  * @param data_return location to return the buffer
650  * @param start the start of segment to steal
651  * @param len the length of segment to steal
652  * @returns #TRUE on success
653  */
654 dbus_bool_t
655 _dbus_string_steal_data_len (DBusString        *str,
656                              char             **data_return,
657                              int                start,
658                              int                len)
659 {
660   DBusString dest;
661   DBUS_STRING_PREAMBLE (str);
662   _dbus_assert (data_return != NULL);
663   _dbus_assert (start >= 0);
664   _dbus_assert (len >= 0);
665   _dbus_assert (start <= real->len);
666   _dbus_assert (len <= real->len - start);
667
668   if (!_dbus_string_init (&dest))
669     return FALSE;
670
671   set_max_length (&dest, real->max_length);
672   
673   if (!_dbus_string_move_len (str, start, len, &dest, 0))
674     {
675       _dbus_string_free (&dest);
676       return FALSE;
677     }
678
679   _dbus_warn ("Broken code in _dbus_string_steal_data_len(), see @todo, FIXME\n");
680   if (!_dbus_string_steal_data (&dest, data_return))
681     {
682       _dbus_string_free (&dest);
683       return FALSE;
684     }
685
686   _dbus_string_free (&dest);
687   return TRUE;
688 }
689
690
691 /**
692  * Copies the data from the string into a char*
693  *
694  * @param str the string
695  * @param data_return place to return the data
696  * @returns #TRUE on success, #FALSE on no memory
697  */
698 dbus_bool_t
699 _dbus_string_copy_data (const DBusString  *str,
700                         char             **data_return)
701 {
702   DBUS_CONST_STRING_PREAMBLE (str);
703   _dbus_assert (data_return != NULL);
704   
705   *data_return = dbus_malloc (real->len + 1);
706   if (*data_return == NULL)
707     return FALSE;
708
709   memcpy (*data_return, real->str, real->len + 1);
710
711   return TRUE;
712 }
713
714 /**
715  * Copies a segment of the string into a char*
716  *
717  * @param str the string
718  * @param data_return place to return the data
719  * @param start start index
720  * @param len length to copy
721  * @returns #FALSE if no memory
722  */
723 dbus_bool_t
724 _dbus_string_copy_data_len (const DBusString  *str,
725                             char             **data_return,
726                             int                start,
727                             int                len)
728 {
729   DBusString dest;
730
731   DBUS_CONST_STRING_PREAMBLE (str);
732   _dbus_assert (data_return != NULL);
733   _dbus_assert (start >= 0);
734   _dbus_assert (len >= 0);
735   _dbus_assert (start <= real->len);
736   _dbus_assert (len <= real->len - start);
737
738   if (!_dbus_string_init (&dest))
739     return FALSE;
740
741   set_max_length (&dest, real->max_length);
742
743   if (!_dbus_string_copy_len (str, start, len, &dest, 0))
744     {
745       _dbus_string_free (&dest);
746       return FALSE;
747     }
748
749   if (!_dbus_string_steal_data (&dest, data_return))
750     {
751       _dbus_string_free (&dest);
752       return FALSE;
753     }
754
755   _dbus_string_free (&dest);
756   return TRUE;
757 }
758
759 /**
760  * Gets the length of a string (not including nul termination).
761  *
762  * @returns the length.
763  */
764 int
765 _dbus_string_get_length (const DBusString  *str)
766 {
767   DBUS_CONST_STRING_PREAMBLE (str);
768   
769   return real->len;
770 }
771
772 /**
773  * Makes a string longer by the given number of bytes.  Checks whether
774  * adding additional_length to the current length would overflow an
775  * integer, and checks for exceeding a string's max length.
776  * The new bytes are not initialized, other than nul-terminating
777  * the end of the string. The uninitialized bytes may contain
778  * nul bytes or other junk.
779  *
780  * @param str a string
781  * @param additional_length length to add to the string.
782  * @returns #TRUE on success.
783  */
784 dbus_bool_t
785 _dbus_string_lengthen (DBusString *str,
786                        int         additional_length)
787 {
788   DBUS_STRING_PREAMBLE (str);  
789   _dbus_assert (additional_length >= 0);
790
791   if (additional_length > real->max_length - real->len)
792     return FALSE; /* would overflow */
793   
794   return set_length (real,
795                      real->len + additional_length);
796 }
797
798 /**
799  * Makes a string shorter by the given number of bytes.
800  *
801  * @param str a string
802  * @param length_to_remove length to remove from the string.
803  */
804 void
805 _dbus_string_shorten (DBusString *str,
806                       int         length_to_remove)
807 {
808   DBUS_STRING_PREAMBLE (str);
809   _dbus_assert (length_to_remove >= 0);
810   _dbus_assert (length_to_remove <= real->len);
811
812   set_length (real,
813               real->len - length_to_remove);
814 }
815
816 /**
817  * Sets the length of a string. Can be used to truncate or lengthen
818  * the string. If the string is lengthened, the function may fail and
819  * return #FALSE. Newly-added bytes are not initialized, as with
820  * _dbus_string_lengthen().
821  *
822  * @param str a string
823  * @param length new length of the string.
824  * @returns #FALSE on failure.
825  */
826 dbus_bool_t
827 _dbus_string_set_length (DBusString *str,
828                          int         length)
829 {
830   DBUS_STRING_PREAMBLE (str);
831   _dbus_assert (length >= 0);
832
833   return set_length (real, length);
834 }
835
836 static dbus_bool_t
837 align_length_then_lengthen (DBusString *str,
838                             int         alignment,
839                             int         then_lengthen_by)
840 {
841   unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */
842   int delta;
843   DBUS_STRING_PREAMBLE (str);
844   _dbus_assert (alignment >= 1);
845   _dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */
846
847   new_len = _DBUS_ALIGN_VALUE (real->len, alignment);
848   if (new_len > (unsigned long) real->max_length - then_lengthen_by)
849     return FALSE;
850   new_len += then_lengthen_by;
851   
852   delta = new_len - real->len;
853   _dbus_assert (delta >= 0);
854
855   if (delta == 0)
856     return TRUE;
857
858   if (!set_length (real, new_len))
859     return FALSE;
860
861   /* delta == padding + then_lengthen_by
862    * new_len == old_len + padding + then_lengthen_by
863    */
864   if (then_lengthen_by < delta)
865     {
866       unsigned int i;
867       i = new_len - delta;
868       while (i < (new_len - then_lengthen_by))
869         {
870           real->str[i] = '\0';
871           ++i;
872         }
873     }
874       
875   return TRUE;
876 }
877
878 /**
879  * Align the length of a string to a specific alignment (typically 4 or 8)
880  * by appending nul bytes to the string.
881  *
882  * @param str a string
883  * @param alignment the alignment
884  * @returns #FALSE if no memory
885  */
886 dbus_bool_t
887 _dbus_string_align_length (DBusString *str,
888                            int         alignment)
889 {
890   return align_length_then_lengthen (str, alignment, 0);
891 }
892
893 static dbus_bool_t
894 append (DBusRealString *real,
895         const char     *buffer,
896         int             buffer_len)
897 {
898   if (buffer_len == 0)
899     return TRUE;
900
901   if (!_dbus_string_lengthen ((DBusString*)real, buffer_len))
902     return FALSE;
903
904   memcpy (real->str + (real->len - buffer_len),
905           buffer,
906           buffer_len);
907
908   return TRUE;
909 }
910
911 /**
912  * Appends a nul-terminated C-style string to a DBusString.
913  *
914  * @param str the DBusString
915  * @param buffer the nul-terminated characters to append
916  * @returns #FALSE if not enough memory.
917  */
918 dbus_bool_t
919 _dbus_string_append (DBusString *str,
920                      const char *buffer)
921 {
922   unsigned long buffer_len;
923   
924   DBUS_STRING_PREAMBLE (str);
925   _dbus_assert (buffer != NULL);
926   
927   buffer_len = strlen (buffer);
928   if (buffer_len > (unsigned long) real->max_length)
929     return FALSE;
930   
931   return append (real, buffer, buffer_len);
932 }
933
934 /**
935  * Appends 4 bytes aligned on a 4 byte boundary
936  * with any alignment padding initialized to 0.
937  *
938  * @param str the DBusString
939  * @param octets 4 bytes to append
940  * @returns #FALSE if not enough memory.
941  */
942 dbus_bool_t
943 _dbus_string_append_4_aligned (DBusString         *str,
944                                const unsigned char octets[4])
945 {
946   dbus_uint32_t *p;
947   DBUS_STRING_PREAMBLE (str);
948   
949   if (!align_length_then_lengthen (str, 4, 4))
950     return FALSE;
951
952   p = (dbus_uint32_t*) (real->str + (real->len - 4));
953   *p = *((dbus_uint32_t*)octets);
954
955   return TRUE;
956 }
957
958 /**
959  * Appends 8 bytes aligned on an 8 byte boundary
960  * with any alignment padding initialized to 0.
961  *
962  * @param str the DBusString
963  * @param octets 4 bytes to append
964  * @returns #FALSE if not enough memory.
965  */
966 dbus_bool_t
967 _dbus_string_append_8_aligned (DBusString         *str,
968                                const unsigned char octets[8])
969 {
970 #ifdef DBUS_HAVE_INT64
971   dbus_uint64_t *p;
972   DBUS_STRING_PREAMBLE (str);
973   
974   if (!align_length_then_lengthen (str, 8, 8))
975     return FALSE;
976
977   p = (dbus_uint64_t*) (real->str + (real->len - 8));
978   *p = *((dbus_uint64_t*)octets);
979 #else
980   unsigned char *p;
981   DBUS_STRING_PREAMBLE (str);
982   
983   if (!align_length_then_lengthen (str, 8, 8))
984     return FALSE;
985
986   p = real->str + (real->len - 8);
987   
988   *p++ = octets[0];
989   *p++ = octets[1];
990   *p++ = octets[2];
991   *p++ = octets[3];
992   *p++ = octets[4];
993   *p++ = octets[5];
994   *p++ = octets[6];
995   *p++ = octets[7];
996   _dbus_assert (p == (real->str + real->len));
997 #endif
998
999   return TRUE;
1000 }
1001
1002 /**
1003  * Appends a printf-style formatted string
1004  * to the #DBusString.
1005  *
1006  * @param str the string
1007  * @param format printf format
1008  * @param args variable argument list
1009  * @returns #FALSE if no memory
1010  */
1011 dbus_bool_t
1012 _dbus_string_append_printf_valist  (DBusString        *str,
1013                                     const char        *format,
1014                                     va_list            args)
1015 {
1016   int len;
1017   char c;
1018   va_list args_copy;
1019
1020   DBUS_STRING_PREAMBLE (str);
1021
1022   DBUS_VA_COPY (args_copy, args);
1023
1024   /* Measure the message length without terminating nul */
1025   len = vsnprintf (&c, 1, format, args);
1026
1027   if (!_dbus_string_lengthen (str, len))
1028     {
1029       /* don't leak the copy */
1030       va_end (args_copy);
1031       return FALSE;
1032     }
1033   
1034   vsprintf (real->str + (real->len - len),
1035             format, args_copy);
1036
1037   va_end (args_copy);
1038
1039   return TRUE;
1040 }
1041
1042 /**
1043  * Appends a printf-style formatted string
1044  * to the #DBusString.
1045  *
1046  * @param str the string
1047  * @param format printf format
1048  * @returns #FALSE if no memory
1049  */
1050 dbus_bool_t
1051 _dbus_string_append_printf (DBusString        *str,
1052                             const char        *format,
1053                             ...)
1054 {
1055   va_list args;
1056   dbus_bool_t retval;
1057   
1058   va_start (args, format);
1059   retval = _dbus_string_append_printf_valist (str, format, args);
1060   va_end (args);
1061
1062   return retval;
1063 }
1064
1065 /**
1066  * Appends block of bytes with the given length to a DBusString.
1067  *
1068  * @param str the DBusString
1069  * @param buffer the bytes to append
1070  * @param len the number of bytes to append
1071  * @returns #FALSE if not enough memory.
1072  */
1073 dbus_bool_t
1074 _dbus_string_append_len (DBusString *str,
1075                          const char *buffer,
1076                          int         len)
1077 {
1078   DBUS_STRING_PREAMBLE (str);
1079   _dbus_assert (buffer != NULL);
1080   _dbus_assert (len >= 0);
1081
1082   return append (real, buffer, len);
1083 }
1084
1085 /**
1086  * Appends a single byte to the string, returning #FALSE
1087  * if not enough memory.
1088  *
1089  * @param str the string
1090  * @param byte the byte to append
1091  * @returns #TRUE on success
1092  */
1093 dbus_bool_t
1094 _dbus_string_append_byte (DBusString    *str,
1095                           unsigned char  byte)
1096 {
1097   DBUS_STRING_PREAMBLE (str);
1098
1099   if (!set_length (real, real->len + 1))
1100     return FALSE;
1101
1102   real->str[real->len-1] = byte;
1103
1104   return TRUE;
1105 }
1106
1107 /**
1108  * Appends a single Unicode character, encoding the character
1109  * in UTF-8 format.
1110  *
1111  * @param str the string
1112  * @param ch the Unicode character
1113  */
1114 dbus_bool_t
1115 _dbus_string_append_unichar (DBusString    *str,
1116                              dbus_unichar_t ch)
1117 {
1118   int len;
1119   int first;
1120   int i;
1121   char *out;
1122   
1123   DBUS_STRING_PREAMBLE (str);
1124
1125   /* this code is from GLib but is pretty standard I think */
1126   
1127   len = 0;
1128   
1129   if (ch < 0x80)
1130     {
1131       first = 0;
1132       len = 1;
1133     }
1134   else if (ch < 0x800)
1135     {
1136       first = 0xc0;
1137       len = 2;
1138     }
1139   else if (ch < 0x10000)
1140     {
1141       first = 0xe0;
1142       len = 3;
1143     }
1144    else if (ch < 0x200000)
1145     {
1146       first = 0xf0;
1147       len = 4;
1148     }
1149   else if (ch < 0x4000000)
1150     {
1151       first = 0xf8;
1152       len = 5;
1153     }
1154   else
1155     {
1156       first = 0xfc;
1157       len = 6;
1158     }
1159
1160   if (len > (real->max_length - real->len))
1161     return FALSE; /* real->len + len would overflow */
1162   
1163   if (!set_length (real, real->len + len))
1164     return FALSE;
1165
1166   out = real->str + (real->len - len);
1167   
1168   for (i = len - 1; i > 0; --i)
1169     {
1170       out[i] = (ch & 0x3f) | 0x80;
1171       ch >>= 6;
1172     }
1173   out[0] = ch | first;
1174
1175   return TRUE;
1176 }
1177
1178 static void
1179 delete (DBusRealString *real,
1180         int             start,
1181         int             len)
1182 {
1183   if (len == 0)
1184     return;
1185   
1186   memmove (real->str + start, real->str + start + len, real->len - (start + len));
1187   real->len -= len;
1188   real->str[real->len] = '\0';
1189 }
1190
1191 /**
1192  * Deletes a segment of a DBusString with length len starting at
1193  * start. (Hint: to clear an entire string, setting length to 0
1194  * with _dbus_string_set_length() is easier.)
1195  *
1196  * @param str the DBusString
1197  * @param start where to start deleting
1198  * @param len the number of bytes to delete
1199  */
1200 void
1201 _dbus_string_delete (DBusString       *str,
1202                      int               start,
1203                      int               len)
1204 {
1205   DBUS_STRING_PREAMBLE (str);
1206   _dbus_assert (start >= 0);
1207   _dbus_assert (len >= 0);
1208   _dbus_assert (start <= real->len);
1209   _dbus_assert (len <= real->len - start);
1210   
1211   delete (real, start, len);
1212 }
1213
1214 static dbus_bool_t
1215 copy (DBusRealString *source,
1216       int             start,
1217       int             len,
1218       DBusRealString *dest,
1219       int             insert_at)
1220 {
1221   if (len == 0)
1222     return TRUE;
1223
1224   if (!open_gap (len, dest, insert_at))
1225     return FALSE;
1226   
1227   memcpy (dest->str + insert_at,
1228           source->str + start,
1229           len);
1230
1231   return TRUE;
1232 }
1233
1234 /**
1235  * Checks assertions for two strings we're copying a segment between,
1236  * and declares real_source/real_dest variables.
1237  *
1238  * @param source the source string
1239  * @param start the starting offset
1240  * @param dest the dest string
1241  * @param insert_at where the copied segment is inserted
1242  */
1243 #define DBUS_STRING_COPY_PREAMBLE(source, start, dest, insert_at)       \
1244   DBusRealString *real_source = (DBusRealString*) source;               \
1245   DBusRealString *real_dest = (DBusRealString*) dest;                   \
1246   _dbus_assert ((source) != (dest));                                    \
1247   DBUS_GENERIC_STRING_PREAMBLE (real_source);                           \
1248   DBUS_GENERIC_STRING_PREAMBLE (real_dest);                             \
1249   _dbus_assert (!real_dest->constant);                                  \
1250   _dbus_assert (!real_dest->locked);                                    \
1251   _dbus_assert ((start) >= 0);                                          \
1252   _dbus_assert ((start) <= real_source->len);                           \
1253   _dbus_assert ((insert_at) >= 0);                                      \
1254   _dbus_assert ((insert_at) <= real_dest->len)
1255
1256 /**
1257  * Moves the end of one string into another string. Both strings
1258  * must be initialized, valid strings.
1259  *
1260  * @param source the source string
1261  * @param start where to chop off the source string
1262  * @param dest the destination string
1263  * @param insert_at where to move the chopped-off part of source string
1264  * @returns #FALSE if not enough memory
1265  */
1266 dbus_bool_t
1267 _dbus_string_move (DBusString       *source,
1268                    int               start,
1269                    DBusString       *dest,
1270                    int               insert_at)
1271 {
1272   DBusRealString *real_source = (DBusRealString*) source;
1273   _dbus_assert (start <= real_source->len);
1274   
1275   return _dbus_string_move_len (source, start,
1276                                 real_source->len - start,
1277                                 dest, insert_at);
1278 }
1279
1280 /**
1281  * Like _dbus_string_move(), but does not delete the section
1282  * of the source string that's copied to the dest string.
1283  *
1284  * @param source the source string
1285  * @param start where to start copying the source string
1286  * @param dest the destination string
1287  * @param insert_at where to place the copied part of source string
1288  * @returns #FALSE if not enough memory
1289  */
1290 dbus_bool_t
1291 _dbus_string_copy (const DBusString *source,
1292                    int               start,
1293                    DBusString       *dest,
1294                    int               insert_at)
1295 {
1296   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1297
1298   return copy (real_source, start,
1299                real_source->len - start,
1300                real_dest,
1301                insert_at);
1302 }
1303
1304 /**
1305  * Like _dbus_string_move(), but can move a segment from
1306  * the middle of the source string.
1307  *
1308  * @todo this doesn't do anything with max_length field.
1309  * we should probably just kill the max_length field though.
1310  * 
1311  * @param source the source string
1312  * @param start first byte of source string to move
1313  * @param len length of segment to move
1314  * @param dest the destination string
1315  * @param insert_at where to move the bytes from the source string
1316  * @returns #FALSE if not enough memory
1317  */
1318 dbus_bool_t
1319 _dbus_string_move_len (DBusString       *source,
1320                        int               start,
1321                        int               len,
1322                        DBusString       *dest,
1323                        int               insert_at)
1324
1325 {
1326   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1327   _dbus_assert (len >= 0);
1328   _dbus_assert ((start + len) <= real_source->len);
1329
1330
1331   if (len == 0)
1332     {
1333       return TRUE;
1334     }
1335   else if (start == 0 &&
1336            len == real_source->len &&
1337            real_dest->len == 0)
1338     {
1339       /* Short-circuit moving an entire existing string to an empty string
1340        * by just swapping the buffers.
1341        */
1342       /* we assume ->constant doesn't matter as you can't have
1343        * a constant string involved in a move.
1344        */
1345 #define ASSIGN_DATA(a, b) do {                  \
1346         (a)->str = (b)->str;                    \
1347         (a)->len = (b)->len;                    \
1348         (a)->allocated = (b)->allocated;        \
1349         (a)->align_offset = (b)->align_offset;  \
1350       } while (0)
1351       
1352       DBusRealString tmp;
1353
1354       ASSIGN_DATA (&tmp, real_source);
1355       ASSIGN_DATA (real_source, real_dest);
1356       ASSIGN_DATA (real_dest, &tmp);
1357
1358       return TRUE;
1359     }
1360   else
1361     {
1362       if (!copy (real_source, start, len,
1363                  real_dest,
1364                  insert_at))
1365         return FALSE;
1366       
1367       delete (real_source, start,
1368               len);
1369       
1370       return TRUE;
1371     }
1372 }
1373
1374 /**
1375  * Like _dbus_string_copy(), but can copy a segment from the middle of
1376  * the source string.
1377  *
1378  * @param source the source string
1379  * @param start where to start copying the source string
1380  * @param len length of segment to copy
1381  * @param dest the destination string
1382  * @param insert_at where to place the copied segment of source string
1383  * @returns #FALSE if not enough memory
1384  */
1385 dbus_bool_t
1386 _dbus_string_copy_len (const DBusString *source,
1387                        int               start,
1388                        int               len,
1389                        DBusString       *dest,
1390                        int               insert_at)
1391 {
1392   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
1393   _dbus_assert (len >= 0);
1394   _dbus_assert (start <= real_source->len);
1395   _dbus_assert (len <= real_source->len - start);
1396   
1397   return copy (real_source, start, len,
1398                real_dest,
1399                insert_at);
1400 }
1401
1402 /**
1403  * Replaces a segment of dest string with a segment of source string.
1404  *
1405  * @todo optimize the case where the two lengths are the same, and
1406  * avoid memmoving the data in the trailing part of the string twice.
1407  *
1408  * @todo avoid inserting the source into dest, then deleting
1409  * the replaced chunk of dest (which creates a potentially large
1410  * intermediate string). Instead, extend the replaced chunk
1411  * of dest with padding to the same size as the source chunk,
1412  * then copy in the source bytes.
1413  * 
1414  * @param source the source string
1415  * @param start where to start copying the source string
1416  * @param len length of segment to copy
1417  * @param dest the destination string
1418  * @param replace_at start of segment of dest string to replace
1419  * @param replace_len length of segment of dest string to replace
1420  * @returns #FALSE if not enough memory
1421  *
1422  */
1423 dbus_bool_t
1424 _dbus_string_replace_len (const DBusString *source,
1425                           int               start,
1426                           int               len,
1427                           DBusString       *dest,
1428                           int               replace_at,
1429                           int               replace_len)
1430 {
1431   DBUS_STRING_COPY_PREAMBLE (source, start, dest, replace_at);
1432   _dbus_assert (len >= 0);
1433   _dbus_assert (start <= real_source->len);
1434   _dbus_assert (len <= real_source->len - start);
1435   _dbus_assert (replace_at >= 0);
1436   _dbus_assert (replace_at <= real_dest->len);
1437   _dbus_assert (replace_len <= real_dest->len - replace_at);
1438
1439   if (!copy (real_source, start, len,
1440              real_dest, replace_at))
1441     return FALSE;
1442
1443   delete (real_dest, replace_at + len, replace_len);
1444
1445   return TRUE;
1446 }
1447
1448 /* Unicode macros and utf8_validate() from GLib Owen Taylor, Havoc
1449  * Pennington, and Tom Tromey are the authors and authorized relicense.
1450  */
1451
1452 /** computes length and mask of a unicode character
1453  * @param Char the char
1454  * @param Mask the mask variable to assign to
1455  * @param Len the length variable to assign to
1456  */
1457 #define UTF8_COMPUTE(Char, Mask, Len)                                         \
1458   if (Char < 128)                                                             \
1459     {                                                                         \
1460       Len = 1;                                                                \
1461       Mask = 0x7f;                                                            \
1462     }                                                                         \
1463   else if ((Char & 0xe0) == 0xc0)                                             \
1464     {                                                                         \
1465       Len = 2;                                                                \
1466       Mask = 0x1f;                                                            \
1467     }                                                                         \
1468   else if ((Char & 0xf0) == 0xe0)                                             \
1469     {                                                                         \
1470       Len = 3;                                                                \
1471       Mask = 0x0f;                                                            \
1472     }                                                                         \
1473   else if ((Char & 0xf8) == 0xf0)                                             \
1474     {                                                                         \
1475       Len = 4;                                                                \
1476       Mask = 0x07;                                                            \
1477     }                                                                         \
1478   else if ((Char & 0xfc) == 0xf8)                                             \
1479     {                                                                         \
1480       Len = 5;                                                                \
1481       Mask = 0x03;                                                            \
1482     }                                                                         \
1483   else if ((Char & 0xfe) == 0xfc)                                             \
1484     {                                                                         \
1485       Len = 6;                                                                \
1486       Mask = 0x01;                                                            \
1487     }                                                                         \
1488   else                                                                        \
1489     Len = -1;
1490
1491 /**
1492  * computes length of a unicode character in UTF-8
1493  * @param Char the char
1494  */
1495 #define UTF8_LENGTH(Char)              \
1496   ((Char) < 0x80 ? 1 :                 \
1497    ((Char) < 0x800 ? 2 :               \
1498     ((Char) < 0x10000 ? 3 :            \
1499      ((Char) < 0x200000 ? 4 :          \
1500       ((Char) < 0x4000000 ? 5 : 6)))))
1501    
1502 /**
1503  * Gets a UTF-8 value.
1504  *
1505  * @param Result variable for extracted unicode char.
1506  * @param Chars the bytes to decode
1507  * @param Count counter variable
1508  * @param Mask mask for this char
1509  * @param Len length for this char in bytes
1510  */
1511 #define UTF8_GET(Result, Chars, Count, Mask, Len)                             \
1512   (Result) = (Chars)[0] & (Mask);                                             \
1513   for ((Count) = 1; (Count) < (Len); ++(Count))                               \
1514     {                                                                         \
1515       if (((Chars)[(Count)] & 0xc0) != 0x80)                                  \
1516         {                                                                     \
1517           (Result) = -1;                                                      \
1518           break;                                                              \
1519         }                                                                     \
1520       (Result) <<= 6;                                                         \
1521       (Result) |= ((Chars)[(Count)] & 0x3f);                                  \
1522     }
1523
1524 /**
1525  * Check whether a unicode char is in a valid range.
1526  *
1527  * @param Char the character
1528  */
1529 #define UNICODE_VALID(Char)                   \
1530     ((Char) < 0x110000 &&                     \
1531      (((Char) & 0xFFFFF800) != 0xD800) &&     \
1532      ((Char) < 0xFDD0 || (Char) > 0xFDEF) &&  \
1533      ((Char) & 0xFFFF) != 0xFFFF)
1534
1535 /**
1536  * Gets a unicode character from a UTF-8 string. Does no validation;
1537  * you must verify that the string is valid UTF-8 in advance and must
1538  * pass in the start of a character.
1539  *
1540  * @param str the string
1541  * @param start the start of the UTF-8 character.
1542  * @param ch_return location to return the character
1543  * @param end_return location to return the byte index of next character
1544  */
1545 void
1546 _dbus_string_get_unichar (const DBusString *str,
1547                           int               start,
1548                           dbus_unichar_t   *ch_return,
1549                           int              *end_return)
1550 {
1551   int i, mask, len;
1552   dbus_unichar_t result;
1553   unsigned char c;
1554   unsigned char *p;
1555   DBUS_CONST_STRING_PREAMBLE (str);
1556   _dbus_assert (start >= 0);
1557   _dbus_assert (start <= real->len);
1558   
1559   if (ch_return)
1560     *ch_return = 0;
1561   if (end_return)
1562     *end_return = real->len;
1563   
1564   mask = 0;
1565   p = real->str + start;
1566   c = *p;
1567   
1568   UTF8_COMPUTE (c, mask, len);
1569   if (len == -1)
1570     return;
1571   UTF8_GET (result, p, i, mask, len);
1572
1573   if (result == (dbus_unichar_t)-1)
1574     return;
1575
1576   if (ch_return)
1577     *ch_return = result;
1578   if (end_return)
1579     *end_return = start + len;
1580 }
1581
1582 /**
1583  * Finds the given substring in the string,
1584  * returning #TRUE and filling in the byte index
1585  * where the substring was found, if it was found.
1586  * Returns #FALSE if the substring wasn't found.
1587  * Sets *start to the length of the string if the substring
1588  * is not found.
1589  *
1590  * @param str the string
1591  * @param start where to start looking
1592  * @param substr the substring
1593  * @param found return location for where it was found, or #NULL
1594  * @returns #TRUE if found
1595  */
1596 dbus_bool_t
1597 _dbus_string_find (const DBusString *str,
1598                    int               start,
1599                    const char       *substr,
1600                    int              *found)
1601 {
1602   return _dbus_string_find_to (str, start,
1603                                ((const DBusRealString*)str)->len,
1604                                substr, found);
1605 }
1606
1607 /**
1608  * Finds the given substring in the string,
1609  * up to a certain position,
1610  * returning #TRUE and filling in the byte index
1611  * where the substring was found, if it was found.
1612  * Returns #FALSE if the substring wasn't found.
1613  * Sets *start to the length of the string if the substring
1614  * is not found.
1615  *
1616  * @param str the string
1617  * @param start where to start looking
1618  * @param end where to stop looking
1619  * @param substr the substring
1620  * @param found return location for where it was found, or #NULL
1621  * @returns #TRUE if found
1622  */
1623 dbus_bool_t
1624 _dbus_string_find_to (const DBusString *str,
1625                       int               start,
1626                       int               end,
1627                       const char       *substr,
1628                       int              *found)
1629 {
1630   int i;
1631   DBUS_CONST_STRING_PREAMBLE (str);
1632   _dbus_assert (substr != NULL);
1633   _dbus_assert (start <= real->len);
1634   _dbus_assert (start >= 0);
1635   _dbus_assert (substr != NULL);
1636   _dbus_assert (end <= real->len);
1637   _dbus_assert (start <= end);
1638
1639   /* we always "find" an empty string */
1640   if (*substr == '\0')
1641     {
1642       if (found)
1643         *found = start;
1644       return TRUE;
1645     }
1646
1647   i = start;
1648   while (i < end)
1649     {
1650       if (real->str[i] == substr[0])
1651         {
1652           int j = i + 1;
1653           
1654           while (j < end)
1655             {
1656               if (substr[j - i] == '\0')
1657                 break;
1658               else if (real->str[j] != substr[j - i])
1659                 break;
1660               
1661               ++j;
1662             }
1663
1664           if (substr[j - i] == '\0')
1665             {
1666               if (found)
1667                 *found = i;
1668               return TRUE;
1669             }
1670         }
1671       
1672       ++i;
1673     }
1674
1675   if (found)
1676     *found = end;
1677   
1678   return FALSE;  
1679 }
1680
1681 /**
1682  * Find the given byte scanning backward from the given start.
1683  * Sets *found to -1 if the byte is not found.
1684  *
1685  * @param str the string
1686  * @param start the place to start scanning (will not find the byte at this point)
1687  * @param byte the byte to find
1688  * @param found return location for where it was found
1689  * @returns #TRUE if found
1690  */
1691 dbus_bool_t
1692 _dbus_string_find_byte_backward (const DBusString  *str,
1693                                  int                start,
1694                                  unsigned char      byte,
1695                                  int               *found)
1696 {
1697   int i;
1698   DBUS_CONST_STRING_PREAMBLE (str);
1699   _dbus_assert (start <= real->len);
1700   _dbus_assert (start >= 0);
1701   _dbus_assert (found != NULL);
1702
1703   i = start - 1;
1704   while (i >= 0)
1705     {
1706       if (real->str[i] == byte)
1707         break;
1708       
1709       --i;
1710     }
1711
1712   if (found)
1713     *found = i;
1714
1715   return i >= 0;
1716 }
1717
1718 /**
1719  * Finds a blank (space or tab) in the string. Returns #TRUE
1720  * if found, #FALSE otherwise. If a blank is not found sets
1721  * *found to the length of the string.
1722  *
1723  * @param str the string
1724  * @param start byte index to start looking
1725  * @param found place to store the location of the first blank
1726  * @returns #TRUE if a blank was found
1727  */
1728 dbus_bool_t
1729 _dbus_string_find_blank (const DBusString *str,
1730                          int               start,
1731                          int              *found)
1732 {
1733   int i;
1734   DBUS_CONST_STRING_PREAMBLE (str);
1735   _dbus_assert (start <= real->len);
1736   _dbus_assert (start >= 0);
1737   
1738   i = start;
1739   while (i < real->len)
1740     {
1741       if (real->str[i] == ' ' ||
1742           real->str[i] == '\t')
1743         {
1744           if (found)
1745             *found = i;
1746           return TRUE;
1747         }
1748       
1749       ++i;
1750     }
1751
1752   if (found)
1753     *found = real->len;
1754   
1755   return FALSE;
1756 }
1757
1758 /**
1759  * Skips blanks from start, storing the first non-blank in *end
1760  * (blank is space or tab).
1761  *
1762  * @param str the string
1763  * @param start where to start
1764  * @param end where to store the first non-blank byte index
1765  */
1766 void
1767 _dbus_string_skip_blank (const DBusString *str,
1768                          int               start,
1769                          int              *end)
1770 {
1771   int i;
1772   DBUS_CONST_STRING_PREAMBLE (str);
1773   _dbus_assert (start <= real->len);
1774   _dbus_assert (start >= 0);
1775   
1776   i = start;
1777   while (i < real->len)
1778     {
1779       if (!(real->str[i] == ' ' ||
1780             real->str[i] == '\t'))
1781         break;
1782       
1783       ++i;
1784     }
1785
1786   _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
1787                                     real->str[i] == '\t'));
1788   
1789   if (end)
1790     *end = i;
1791 }
1792
1793 /**
1794  * Skips whitespace from start, storing the first non-whitespace in *end.
1795  * (whitespace is space, tab, newline, CR).
1796  *
1797  * @param str the string
1798  * @param start where to start
1799  * @param end where to store the first non-whitespace byte index
1800  */
1801 void
1802 _dbus_string_skip_white (const DBusString *str,
1803                          int               start,
1804                          int              *end)
1805 {
1806   int i;
1807   DBUS_CONST_STRING_PREAMBLE (str);
1808   _dbus_assert (start <= real->len);
1809   _dbus_assert (start >= 0);
1810   
1811   i = start;
1812   while (i < real->len)
1813     {
1814       if (!(real->str[i] == ' ' ||
1815             real->str[i] == '\n' ||
1816             real->str[i] == '\r' ||
1817             real->str[i] == '\t'))
1818         break;
1819       
1820       ++i;
1821     }
1822
1823   _dbus_assert (i == real->len || !(real->str[i] == ' ' ||
1824                                     real->str[i] == '\t'));
1825   
1826   if (end)
1827     *end = i;
1828 }
1829
1830 /**
1831  * Assigns a newline-terminated or \\r\\n-terminated line from the front
1832  * of the string to the given dest string. The dest string's previous
1833  * contents are deleted. If the source string contains no newline,
1834  * moves the entire source string to the dest string.
1835  *
1836  * @todo owen correctly notes that this is a stupid function (it was
1837  * written purely for test code,
1838  * e.g. dbus-message-builder.c). Probably should be enforced as test
1839  * code only with #ifdef DBUS_BUILD_TESTS
1840  * 
1841  * @param source the source string
1842  * @param dest the destination string (contents are replaced)
1843  * @returns #FALSE if no memory, or source has length 0
1844  */
1845 dbus_bool_t
1846 _dbus_string_pop_line (DBusString *source,
1847                        DBusString *dest)
1848 {
1849   int eol;
1850   dbus_bool_t have_newline;
1851   
1852   _dbus_string_set_length (dest, 0);
1853   
1854   eol = 0;
1855   if (_dbus_string_find (source, 0, "\n", &eol))
1856     {
1857       have_newline = TRUE;
1858       eol += 1; /* include newline */
1859     }
1860   else
1861     {
1862       eol = _dbus_string_get_length (source);
1863       have_newline = FALSE;
1864     }
1865
1866   if (eol == 0)
1867     return FALSE; /* eof */
1868   
1869   if (!_dbus_string_move_len (source, 0, eol,
1870                               dest, 0))
1871     {
1872       return FALSE;
1873     }
1874
1875   /* dump the newline and the \r if we have one */
1876   if (have_newline)
1877     {
1878       dbus_bool_t have_cr;
1879       
1880       _dbus_assert (_dbus_string_get_length (dest) > 0);
1881
1882       if (_dbus_string_get_length (dest) > 1 &&
1883           _dbus_string_get_byte (dest,
1884                                  _dbus_string_get_length (dest) - 2) == '\r')
1885         have_cr = TRUE;
1886       else
1887         have_cr = FALSE;
1888         
1889       _dbus_string_set_length (dest,
1890                                _dbus_string_get_length (dest) -
1891                                (have_cr ? 2 : 1));
1892     }
1893   
1894   return TRUE;
1895 }
1896
1897 /**
1898  * Deletes up to and including the first blank space
1899  * in the string.
1900  *
1901  * @param str the string
1902  */
1903 void
1904 _dbus_string_delete_first_word (DBusString *str)
1905 {
1906   int i;
1907   
1908   if (_dbus_string_find_blank (str, 0, &i))
1909     _dbus_string_skip_blank (str, i, &i);
1910
1911   _dbus_string_delete (str, 0, i);
1912 }
1913
1914 /**
1915  * Deletes any leading blanks in the string
1916  *
1917  * @param str the string
1918  */
1919 void
1920 _dbus_string_delete_leading_blanks (DBusString *str)
1921 {
1922   int i;
1923   
1924   _dbus_string_skip_blank (str, 0, &i);
1925
1926   if (i > 0)
1927     _dbus_string_delete (str, 0, i);
1928 }
1929
1930 /**
1931  * Tests two DBusString for equality.
1932  *
1933  * @todo memcmp is probably faster
1934  *
1935  * @param a first string
1936  * @param b second string
1937  * @returns #TRUE if equal
1938  */
1939 dbus_bool_t
1940 _dbus_string_equal (const DBusString *a,
1941                     const DBusString *b)
1942 {
1943   const unsigned char *ap;
1944   const unsigned char *bp;
1945   const unsigned char *a_end;
1946   const DBusRealString *real_a = (const DBusRealString*) a;
1947   const DBusRealString *real_b = (const DBusRealString*) b;
1948   DBUS_GENERIC_STRING_PREAMBLE (real_a);
1949   DBUS_GENERIC_STRING_PREAMBLE (real_b);
1950
1951   if (real_a->len != real_b->len)
1952     return FALSE;
1953
1954   ap = real_a->str;
1955   bp = real_b->str;
1956   a_end = real_a->str + real_a->len;
1957   while (ap != a_end)
1958     {
1959       if (*ap != *bp)
1960         return FALSE;
1961       
1962       ++ap;
1963       ++bp;
1964     }
1965
1966   return TRUE;
1967 }
1968
1969 /**
1970  * Tests two DBusString for equality up to the given length.
1971  *
1972  * @todo write a unit test
1973  *
1974  * @todo memcmp is probably faster
1975  *
1976  * @param a first string
1977  * @param b second string
1978  * @param len the lengh
1979  * @returns #TRUE if equal for the given number of bytes
1980  */
1981 dbus_bool_t
1982 _dbus_string_equal_len (const DBusString *a,
1983                         const DBusString *b,
1984                         int               len)
1985 {
1986   const unsigned char *ap;
1987   const unsigned char *bp;
1988   const unsigned char *a_end;
1989   const DBusRealString *real_a = (const DBusRealString*) a;
1990   const DBusRealString *real_b = (const DBusRealString*) b;
1991   DBUS_GENERIC_STRING_PREAMBLE (real_a);
1992   DBUS_GENERIC_STRING_PREAMBLE (real_b);
1993
1994   if (real_a->len != real_b->len &&
1995       (real_a->len < len || real_b->len < len))
1996     return FALSE;
1997
1998   ap = real_a->str;
1999   bp = real_b->str;
2000   a_end = real_a->str + MIN (real_a->len, len);
2001   while (ap != a_end)
2002     {
2003       if (*ap != *bp)
2004         return FALSE;
2005       
2006       ++ap;
2007       ++bp;
2008     }
2009
2010   return TRUE;
2011 }
2012
2013 /**
2014  * Checks whether a string is equal to a C string.
2015  *
2016  * @param a the string
2017  * @param c_str the C string
2018  * @returns #TRUE if equal
2019  */
2020 dbus_bool_t
2021 _dbus_string_equal_c_str (const DBusString *a,
2022                           const char       *c_str)
2023 {
2024   const unsigned char *ap;
2025   const unsigned char *bp;
2026   const unsigned char *a_end;
2027   const DBusRealString *real_a = (const DBusRealString*) a;
2028   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2029   _dbus_assert (c_str != NULL);
2030   
2031   ap = real_a->str;
2032   bp = (const unsigned char*) c_str;
2033   a_end = real_a->str + real_a->len;
2034   while (ap != a_end && *bp)
2035     {
2036       if (*ap != *bp)
2037         return FALSE;
2038       
2039       ++ap;
2040       ++bp;
2041     }
2042
2043   if (ap != a_end || *bp)
2044     return FALSE;
2045   
2046   return TRUE;
2047 }
2048
2049 /**
2050  * Checks whether a string starts with the given C string.
2051  *
2052  * @param a the string
2053  * @param c_str the C string
2054  * @returns #TRUE if string starts with it
2055  */
2056 dbus_bool_t
2057 _dbus_string_starts_with_c_str (const DBusString *a,
2058                                 const char       *c_str)
2059 {
2060   const unsigned char *ap;
2061   const unsigned char *bp;
2062   const unsigned char *a_end;
2063   const DBusRealString *real_a = (const DBusRealString*) a;
2064   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2065   _dbus_assert (c_str != NULL);
2066   
2067   ap = real_a->str;
2068   bp = (const unsigned char*) c_str;
2069   a_end = real_a->str + real_a->len;
2070   while (ap != a_end && *bp)
2071     {
2072       if (*ap != *bp)
2073         return FALSE;
2074       
2075       ++ap;
2076       ++bp;
2077     }
2078
2079   if (*bp == '\0')
2080     return TRUE;
2081   else
2082     return FALSE;
2083 }
2084
2085 /**
2086  * Returns whether a string ends with the given suffix
2087  *
2088  * @todo memcmp might make this faster.
2089  * 
2090  * @param a the string
2091  * @param c_str the C-style string
2092  * @returns #TRUE if the string ends with the suffix
2093  */
2094 dbus_bool_t
2095 _dbus_string_ends_with_c_str (const DBusString *a,
2096                               const char       *c_str)
2097 {
2098   const unsigned char *ap;
2099   const unsigned char *bp;
2100   const unsigned char *a_end;
2101   unsigned long c_str_len;
2102   const DBusRealString *real_a = (const DBusRealString*) a;
2103   DBUS_GENERIC_STRING_PREAMBLE (real_a);
2104   _dbus_assert (c_str != NULL);
2105   
2106   c_str_len = strlen (c_str);
2107   if (((unsigned long)real_a->len) < c_str_len)
2108     return FALSE;
2109   
2110   ap = real_a->str + (real_a->len - c_str_len);
2111   bp = (const unsigned char*) c_str;
2112   a_end = real_a->str + real_a->len;
2113   while (ap != a_end)
2114     {
2115       if (*ap != *bp)
2116         return FALSE;
2117       
2118       ++ap;
2119       ++bp;
2120     }
2121
2122   _dbus_assert (*ap == '\0');
2123   _dbus_assert (*bp == '\0');
2124   
2125   return TRUE;
2126 }
2127
2128 static const signed char base64_table[] = {
2129   /* 0 */ 'A',
2130   /* 1 */ 'B',
2131   /* 2 */ 'C',
2132   /* 3 */ 'D',
2133   /* 4 */ 'E',
2134   /* 5 */ 'F',
2135   /* 6 */ 'G',
2136   /* 7 */ 'H',
2137   /* 8 */ 'I',
2138   /* 9 */ 'J',
2139   /* 10 */ 'K',
2140   /* 11 */ 'L',
2141   /* 12 */ 'M',
2142   /* 13 */ 'N',
2143   /* 14 */ 'O',
2144   /* 15 */ 'P',
2145   /* 16 */ 'Q',
2146   /* 17 */ 'R',
2147   /* 18 */ 'S',
2148   /* 19 */ 'T',
2149   /* 20 */ 'U',
2150   /* 21 */ 'V',
2151   /* 22 */ 'W',
2152   /* 23 */ 'X',
2153   /* 24 */ 'Y',
2154   /* 25 */ 'Z',
2155   /* 26 */ 'a',
2156   /* 27 */ 'b',
2157   /* 28 */ 'c',
2158   /* 29 */ 'd',
2159   /* 30 */ 'e',
2160   /* 31 */ 'f',
2161   /* 32 */ 'g',
2162   /* 33 */ 'h',
2163   /* 34 */ 'i',
2164   /* 35 */ 'j',
2165   /* 36 */ 'k',
2166   /* 37 */ 'l',
2167   /* 38 */ 'm',
2168   /* 39 */ 'n',
2169   /* 40 */ 'o',
2170   /* 41 */ 'p',
2171   /* 42 */ 'q',
2172   /* 43 */ 'r',
2173   /* 44 */ 's',
2174   /* 45 */ 't',
2175   /* 46 */ 'u',
2176   /* 47 */ 'v',
2177   /* 48 */ 'w',
2178   /* 49 */ 'x',
2179   /* 50 */ 'y',
2180   /* 51 */ 'z',
2181   /* 52 */ '0',
2182   /* 53 */ '1',
2183   /* 54 */ '2',
2184   /* 55 */ '3',
2185   /* 56 */ '4',
2186   /* 57 */ '5',
2187   /* 58 */ '6',
2188   /* 59 */ '7',
2189   /* 60 */ '8',
2190   /* 61 */ '9',
2191   /* 62 */ '+',
2192   /* 63 */ '/'
2193 };
2194
2195 /** The minimum char that's a valid char in Base64-encoded text */
2196 #define UNBASE64_MIN_CHAR (43)
2197 /** The maximum char that's a valid char in Base64-encoded text */
2198 #define UNBASE64_MAX_CHAR (122)
2199 /** Must subtract this from a char's integer value before offsetting
2200  * into unbase64_table
2201  */
2202 #define UNBASE64_TABLE_OFFSET UNBASE64_MIN_CHAR
2203 static const signed char unbase64_table[] = {
2204   /* 43 + */ 62,
2205   /* 44 , */ -1,
2206   /* 45 - */ -1,
2207   /* 46 . */ -1,
2208   /* 47 / */ 63,
2209   /* 48 0 */ 52,
2210   /* 49 1 */ 53,
2211   /* 50 2 */ 54,
2212   /* 51 3 */ 55,
2213   /* 52 4 */ 56,
2214   /* 53 5 */ 57,
2215   /* 54 6 */ 58,
2216   /* 55 7 */ 59,
2217   /* 56 8 */ 60,
2218   /* 57 9 */ 61,
2219   /* 58 : */ -1,
2220   /* 59 ; */ -1,
2221   /* 60 < */ -1,
2222   /* 61 = */ -1,
2223   /* 62 > */ -1,
2224   /* 63 ? */ -1,
2225   /* 64 @ */ -1,
2226   /* 65 A */ 0,
2227   /* 66 B */ 1,
2228   /* 67 C */ 2,
2229   /* 68 D */ 3,
2230   /* 69 E */ 4,
2231   /* 70 F */ 5,
2232   /* 71 G */ 6,
2233   /* 72 H */ 7,
2234   /* 73 I */ 8,
2235   /* 74 J */ 9,
2236   /* 75 K */ 10,
2237   /* 76 L */ 11,
2238   /* 77 M */ 12,
2239   /* 78 N */ 13,
2240   /* 79 O */ 14,
2241   /* 80 P */ 15,
2242   /* 81 Q */ 16,
2243   /* 82 R */ 17,
2244   /* 83 S */ 18,
2245   /* 84 T */ 19,
2246   /* 85 U */ 20,
2247   /* 86 V */ 21,
2248   /* 87 W */ 22,
2249   /* 88 X */ 23,
2250   /* 89 Y */ 24,
2251   /* 90 Z */ 25,
2252   /* 91 [ */ -1,
2253   /* 92 \ */ -1,
2254   /* 93 ] */ -1,
2255   /* 94 ^ */ -1,
2256   /* 95 _ */ -1,
2257   /* 96 ` */ -1,
2258   /* 97 a */ 26,
2259   /* 98 b */ 27,
2260   /* 99 c */ 28,
2261   /* 100 d */ 29,
2262   /* 101 e */ 30,
2263   /* 102 f */ 31,
2264   /* 103 g */ 32,
2265   /* 104 h */ 33,
2266   /* 105 i */ 34,
2267   /* 106 j */ 35,
2268   /* 107 k */ 36,
2269   /* 108 l */ 37,
2270   /* 109 m */ 38,
2271   /* 110 n */ 39,
2272   /* 111 o */ 40,
2273   /* 112 p */ 41,
2274   /* 113 q */ 42,
2275   /* 114 r */ 43,
2276   /* 115 s */ 44,
2277   /* 116 t */ 45,
2278   /* 117 u */ 46,
2279   /* 118 v */ 47,
2280   /* 119 w */ 48,
2281   /* 120 x */ 49,
2282   /* 121 y */ 50,
2283   /* 122 z */ 51
2284 };
2285
2286 /**
2287  * Encodes a string using Base64, as documented in RFC 2045.
2288  *
2289  * @param source the string to encode
2290  * @param start byte index to start encoding
2291  * @param dest string where encoded data should be placed
2292  * @param insert_at where to place encoded data
2293  * @returns #TRUE if encoding was successful, #FALSE if no memory etc.
2294  */
2295 dbus_bool_t
2296 _dbus_string_base64_encode (const DBusString *source,
2297                             int               start,
2298                             DBusString       *dest,
2299                             int               insert_at)
2300 {
2301   int source_len;
2302   unsigned int dest_len; /* unsigned for overflow checks below */
2303   const unsigned char *s;
2304   unsigned char *d;
2305   const unsigned char *triplet_end;
2306   const unsigned char *final_end;
2307   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);  
2308   _dbus_assert (source != dest);
2309   
2310   /* For each 24 bits (3 bytes) of input, we have 4 bytes of
2311    * output.
2312    */
2313   source_len = real_source->len - start;
2314   dest_len = (source_len / 3) * 4;
2315   if (source_len % 3 != 0)
2316     dest_len += 4;
2317
2318   if (dest_len > (unsigned int) real_dest->max_length)
2319     return FALSE;
2320   
2321   if (source_len == 0)
2322     return TRUE;
2323   
2324   if (!open_gap (dest_len, real_dest, insert_at))
2325     return FALSE;
2326
2327   d = real_dest->str + insert_at;
2328   s = real_source->str + start;
2329   final_end = real_source->str + (start + source_len);
2330   triplet_end = final_end - (source_len % 3);
2331   _dbus_assert (triplet_end <= final_end);
2332   _dbus_assert ((final_end - triplet_end) < 3);
2333
2334 #define ENCODE_64(v) (base64_table[ (unsigned char) (v) ])
2335 #define SIX_BITS_MASK (0x3f)
2336   _dbus_assert (SIX_BITS_MASK < _DBUS_N_ELEMENTS (base64_table));
2337   
2338   while (s != triplet_end)
2339     {
2340       unsigned int triplet;
2341
2342       triplet = s[2] | (s[1] << 8) | (s[0] << 16);
2343
2344       /* Encode each 6 bits. */
2345
2346       *d++ = ENCODE_64 (triplet >> 18);
2347       *d++ = ENCODE_64 ((triplet >> 12) & SIX_BITS_MASK);
2348       *d++ = ENCODE_64 ((triplet >> 6) & SIX_BITS_MASK);
2349       *d++ = ENCODE_64 (triplet & SIX_BITS_MASK);
2350       
2351       s += 3;
2352     }
2353
2354   switch (final_end - triplet_end)
2355     {
2356     case 2:
2357       {
2358         unsigned int doublet;
2359         
2360         doublet = s[1] | (s[0] << 8);        
2361
2362         *d++ = ENCODE_64 (doublet >> 12);
2363         *d++ = ENCODE_64 ((doublet >> 6) & SIX_BITS_MASK);
2364         *d++ = ENCODE_64 (doublet & SIX_BITS_MASK);
2365         *d++ = '=';
2366       }
2367       break;
2368     case 1:
2369       {
2370         unsigned int singlet;
2371         
2372         singlet = s[0];
2373
2374         *d++ = ENCODE_64 ((singlet >> 6) & SIX_BITS_MASK);
2375         *d++ = ENCODE_64 (singlet & SIX_BITS_MASK);
2376         *d++ = '=';
2377         *d++ = '=';
2378       }
2379       break;
2380     case 0:
2381       break;
2382     }
2383
2384   _dbus_assert (d == (real_dest->str + (insert_at + dest_len)));
2385
2386   return TRUE;
2387 }
2388
2389 /**
2390  * Decodes a string from Base64, as documented in RFC 2045.
2391  *
2392  * @todo sort out the AUDIT comment in here. The case it mentions
2393  * ("====" or "x===") is not allowed in correct base64, so need to
2394  * decide what to do with that kind of input. Probably ignore it
2395  * since we ignore any other junk seen.
2396  *
2397  * @param source the string to decode
2398  * @param start byte index to start decode
2399  * @param dest string where decoded data should be placed
2400  * @param insert_at where to place decoded data
2401  * @returns #TRUE if decoding was successful, #FALSE if no memory etc.
2402  */
2403 dbus_bool_t
2404 _dbus_string_base64_decode (const DBusString *source,
2405                             int               start,
2406                             DBusString       *dest,
2407                             int               insert_at)
2408 {
2409   int source_len;
2410   const char *s;
2411   const char *end;
2412   DBusString result;
2413   unsigned int triplet = 0;
2414   int sextet_count;
2415   int pad_count;
2416   DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
2417   _dbus_assert (source != dest);
2418   
2419   source_len = real_source->len - start;
2420   s = real_source->str + start;
2421   end = real_source->str + source_len;
2422
2423   if (source_len == 0)
2424     return TRUE;
2425
2426   if (!_dbus_string_init (&result))
2427     return FALSE;
2428
2429   pad_count = 0;
2430   sextet_count = 0;
2431   while (s != end)
2432     {
2433       /* The idea is to just skip anything that isn't
2434        * a base64 char - it's allowed to have whitespace,
2435        * newlines, etc. in here. We also ignore trailing
2436        * base64 chars, though that's suspicious.
2437        */
2438       
2439       if (*s >= UNBASE64_MIN_CHAR &&
2440           *s <= UNBASE64_MAX_CHAR)
2441         {
2442           if (*s == '=')
2443             {
2444               /* '=' is padding, doesn't represent additional data
2445                * but does increment our count.
2446                */
2447               pad_count += 1;
2448               sextet_count += 1;
2449             }
2450           else
2451             {
2452               int val;
2453
2454               val = unbase64_table[(*s) - UNBASE64_TABLE_OFFSET];
2455
2456               if (val >= 0)
2457                 {
2458                   triplet <<= 6;
2459                   triplet |= (unsigned int) val;
2460                   sextet_count += 1;
2461                 }
2462             }
2463
2464           if (sextet_count == 4)
2465             {
2466               /* no pad = 3 bytes, 1 pad = 2 bytes, 2 pad = 1 byte */
2467
2468
2469               /* AUDIT: Comment doesn't mention 4 pad => 0,
2470                *         3 pad => 1 byte, though the code should
2471                *        work fine if those are the required outputs.
2472                *
2473                *        I assume that the spec requires dropping
2474                *        the top two bits of, say, ///= which is > 2 
2475                *        bytes worth of bits. (Or otherwise, you couldn't
2476                *        actually represent 2 byte sequences.
2477                */
2478               
2479               if (pad_count < 1)
2480                 {
2481                   if (!_dbus_string_append_byte (&result,
2482                                                  triplet >> 16))
2483                     goto failed;
2484                 }
2485               
2486               if (pad_count < 2)
2487                 {
2488                   if (!_dbus_string_append_byte (&result,
2489                                                  (triplet >> 8) & 0xff))
2490                     goto failed;
2491                 }
2492               
2493               if (!_dbus_string_append_byte (&result,
2494                                              triplet & 0xff))
2495                 goto failed;
2496               
2497               sextet_count = 0;
2498               pad_count = 0;
2499               triplet = 0;
2500             }
2501         }
2502       
2503       ++s;
2504     }
2505
2506   if (!_dbus_string_move (&result, 0, dest, insert_at))
2507     {
2508       _dbus_string_free (&result);
2509       return FALSE;
2510     }
2511
2512   _dbus_string_free (&result);
2513
2514   return TRUE;
2515
2516  failed:
2517   _dbus_string_free (&result);
2518
2519   return FALSE;
2520 }
2521
2522 /**
2523  * Encodes a string in hex, the way MD5 and SHA-1 are usually
2524  * encoded. (Each byte is two hex digits.)
2525  *
2526  * @param source the string to encode
2527  * @param start byte index to start encoding
2528  * @param dest string where encoded data should be placed
2529  * @param insert_at where to place encoded data
2530  * @returns #TRUE if encoding was successful, #FALSE if no memory etc.
2531  */
2532 dbus_bool_t
2533 _dbus_string_hex_encode (const DBusString *source,
2534                          int               start,
2535                          DBusString       *dest,
2536                          int               insert_at)
2537 {
2538   DBusString result;
2539   const char hexdigits[16] = {
2540     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
2541     'a', 'b', 'c', 'd', 'e', 'f'
2542   };
2543   const unsigned char *p;
2544   const unsigned char *end;
2545   dbus_bool_t retval;
2546   
2547   _dbus_assert (start <= _dbus_string_get_length (source));
2548
2549   if (!_dbus_string_init (&result))
2550     return FALSE;
2551
2552   retval = FALSE;
2553   
2554   p = (const unsigned char*) _dbus_string_get_const_data (source);
2555   end = p + _dbus_string_get_length (source);
2556   p += start;
2557   
2558   while (p != end)
2559     {
2560       if (!_dbus_string_append_byte (&result,
2561                                      hexdigits[(*p >> 4)]))
2562         goto out;
2563       
2564       if (!_dbus_string_append_byte (&result,
2565                                      hexdigits[(*p & 0x0f)]))
2566         goto out;
2567
2568       ++p;
2569     }
2570
2571   if (!_dbus_string_move (&result, 0, dest, insert_at))
2572     goto out;
2573
2574   retval = TRUE;
2575
2576  out:
2577   _dbus_string_free (&result);
2578   return retval;
2579 }
2580
2581 /**
2582  * Decodes a string from hex encoding.
2583  *
2584  * @param source the string to decode
2585  * @param start byte index to start decode
2586  * @param dest string where decoded data should be placed
2587  * @param insert_at where to place decoded data
2588  * @returns #TRUE if decoding was successful, #FALSE if no memory etc.
2589  */
2590 dbus_bool_t
2591 _dbus_string_hex_decode (const DBusString *source,
2592                          int               start,
2593                          DBusString       *dest,
2594                          int               insert_at)
2595 {
2596   DBusString result;
2597   const unsigned char *p;
2598   const unsigned char *end;
2599   dbus_bool_t retval;
2600   dbus_bool_t high_bits;
2601   
2602   _dbus_assert (start <= _dbus_string_get_length (source));
2603
2604   if (!_dbus_string_init (&result))
2605     return FALSE;
2606
2607   retval = FALSE;
2608
2609   high_bits = TRUE;
2610   p = (const unsigned char*) _dbus_string_get_const_data (source);
2611   end = p + _dbus_string_get_length (source);
2612   p += start;
2613   
2614   while (p != end)
2615     {
2616       unsigned int val;
2617
2618       switch (*p)
2619         {
2620         case '0':
2621           val = 0;
2622           break;
2623         case '1':
2624           val = 1;
2625           break;
2626         case '2':
2627           val = 2;
2628           break;
2629         case '3':
2630           val = 3;
2631           break;
2632         case '4':
2633           val = 4;
2634           break;
2635         case '5':
2636           val = 5;
2637           break;
2638         case '6':
2639           val = 6;
2640           break;
2641         case '7':
2642           val = 7;
2643           break;
2644         case '8':
2645           val = 8;
2646           break;
2647         case '9':
2648           val = 9;
2649           break;
2650         case 'a':
2651         case 'A':
2652           val = 10;
2653           break;
2654         case 'b':
2655         case 'B':
2656           val = 11;
2657           break;
2658         case 'c':
2659         case 'C':
2660           val = 12;
2661           break;
2662         case 'd':
2663         case 'D':
2664           val = 13;
2665           break;
2666         case 'e':
2667         case 'E':
2668           val = 14;
2669           break;
2670         case 'f':
2671         case 'F':
2672           val = 15;
2673           break;
2674         default:
2675           val = 0;
2676           _dbus_verbose ("invalid character '%c' in hex encoded text\n",
2677                          *p);
2678           goto out;
2679         }
2680
2681       if (high_bits)
2682         {
2683           if (!_dbus_string_append_byte (&result,
2684                                          val << 4))
2685             goto out;
2686         }
2687       else
2688         {
2689           int len;
2690           unsigned char b;
2691
2692           len = _dbus_string_get_length (&result);
2693           
2694           b = _dbus_string_get_byte (&result, len - 1);
2695
2696           b |= val;
2697
2698           _dbus_string_set_byte (&result, len - 1, b);
2699         }
2700
2701       high_bits = !high_bits;
2702
2703       ++p;
2704     }
2705
2706   if (!_dbus_string_move (&result, 0, dest, insert_at))
2707     goto out;
2708
2709   retval = TRUE;
2710   
2711  out:
2712   _dbus_string_free (&result);  
2713   return retval;
2714 }
2715
2716 /**
2717  * Checks that the given range of the string is valid ASCII with no
2718  * nul bytes. If the given range is not entirely contained in the
2719  * string, returns #FALSE.
2720  *
2721  * @todo this is inconsistent with most of DBusString in that
2722  * it allows a start,len range that isn't in the string.
2723  * 
2724  * @param str the string
2725  * @param start first byte index to check
2726  * @param len number of bytes to check
2727  * @returns #TRUE if the byte range exists and is all valid ASCII
2728  */
2729 dbus_bool_t
2730 _dbus_string_validate_ascii (const DBusString *str,
2731                              int               start,
2732                              int               len)
2733 {
2734   const unsigned char *s;
2735   const unsigned char *end;
2736   DBUS_CONST_STRING_PREAMBLE (str);
2737   _dbus_assert (start >= 0);
2738   _dbus_assert (start <= real->len);
2739   _dbus_assert (len >= 0);
2740   
2741   if (len > real->len - start)
2742     return FALSE;
2743   
2744   s = real->str + start;
2745   end = s + len;
2746   while (s != end)
2747     {
2748       if (_DBUS_UNLIKELY (*s == '\0' ||
2749                           ((*s & ~0x7f) != 0)))
2750         return FALSE;
2751         
2752       ++s;
2753     }
2754   
2755   return TRUE;
2756 }
2757
2758 /**
2759  * Checks that the given range of the string is valid UTF-8. If the
2760  * given range is not entirely contained in the string, returns
2761  * #FALSE. If the string contains any nul bytes in the given range,
2762  * returns #FALSE. If the start and start+len are not on character
2763  * boundaries, returns #FALSE.
2764  *
2765  * @todo this is inconsistent with most of DBusString in that
2766  * it allows a start,len range that isn't in the string.
2767  * 
2768  * @param str the string
2769  * @param start first byte index to check
2770  * @param len number of bytes to check
2771  * @returns #TRUE if the byte range exists and is all valid UTF-8
2772  */
2773 dbus_bool_t
2774 _dbus_string_validate_utf8  (const DBusString *str,
2775                              int               start,
2776                              int               len)
2777 {
2778   const unsigned char *p;
2779   const unsigned char *end;
2780   DBUS_CONST_STRING_PREAMBLE (str);
2781   _dbus_assert (start >= 0);
2782   _dbus_assert (start <= real->len);
2783   _dbus_assert (len >= 0);
2784
2785   /* we are doing _DBUS_UNLIKELY() here which might be
2786    * dubious in a generic library like GLib, but in D-BUS
2787    * we know we're validating messages and that it would
2788    * only be evil/broken apps that would have invalid
2789    * UTF-8. Also, this function seems to be a performance
2790    * bottleneck in profiles.
2791    */
2792   
2793   if (_DBUS_UNLIKELY (len > real->len - start))
2794     return FALSE;
2795   
2796   p = real->str + start;
2797   end = p + len;
2798   
2799   while (p < end)
2800     {
2801       int i, mask = 0, char_len;
2802       dbus_unichar_t result;
2803       unsigned char c = (unsigned char) *p;
2804       
2805       UTF8_COMPUTE (c, mask, char_len);
2806
2807       if (_DBUS_UNLIKELY (char_len == -1))
2808         break;
2809
2810       /* check that the expected number of bytes exists in the remaining length */
2811       if (_DBUS_UNLIKELY ((end - p) < char_len))
2812         break;
2813         
2814       UTF8_GET (result, p, i, mask, char_len);
2815
2816       if (_DBUS_UNLIKELY (UTF8_LENGTH (result) != char_len)) /* Check for overlong UTF-8 */
2817         break;
2818
2819       if (_DBUS_UNLIKELY (result == (dbus_unichar_t)-1))
2820         break;
2821
2822       if (_DBUS_UNLIKELY (!UNICODE_VALID (result)))
2823         break;
2824       
2825       p += char_len;
2826     }
2827
2828   /* See that we covered the entire length if a length was
2829    * passed in
2830    */
2831   if (_DBUS_UNLIKELY (p != end))
2832     return FALSE;
2833   else
2834     return TRUE;
2835 }
2836
2837 /**
2838  * Checks that the given range of the string is all nul bytes. If the
2839  * given range is not entirely contained in the string, returns
2840  * #FALSE.
2841  *
2842  * @todo this is inconsistent with most of DBusString in that
2843  * it allows a start,len range that isn't in the string.
2844  * 
2845  * @param str the string
2846  * @param start first byte index to check
2847  * @param len number of bytes to check
2848  * @returns #TRUE if the byte range exists and is all nul bytes
2849  */
2850 dbus_bool_t
2851 _dbus_string_validate_nul (const DBusString *str,
2852                            int               start,
2853                            int               len)
2854 {
2855   const unsigned char *s;
2856   const unsigned char *end;
2857   DBUS_CONST_STRING_PREAMBLE (str);
2858   _dbus_assert (start >= 0);
2859   _dbus_assert (len >= 0);
2860   _dbus_assert (start <= real->len);
2861   
2862   if (len > real->len - start)
2863     return FALSE;
2864   
2865   s = real->str + start;
2866   end = s + len;
2867   while (s != end)
2868     {
2869       if (_DBUS_UNLIKELY (*s != '\0'))
2870         return FALSE;
2871       ++s;
2872     }
2873   
2874   return TRUE;
2875 }
2876
2877 /**
2878  * Checks that the given range of the string is a valid object path
2879  * name in the D-BUS protocol. This includes a length restriction,
2880  * etc., see the specification. It does not validate UTF-8, that has
2881  * to be done separately for now.
2882  *
2883  * @todo this is inconsistent with most of DBusString in that
2884  * it allows a start,len range that isn't in the string.
2885  *
2886  * @todo change spec to disallow more things, such as spaces in the
2887  * path name
2888  * 
2889  * @param str the string
2890  * @param start first byte index to check
2891  * @param len number of bytes to check
2892  * @returns #TRUE if the byte range exists and is a valid name
2893  */
2894 dbus_bool_t
2895 _dbus_string_validate_path (const DBusString  *str,
2896                             int                start,
2897                             int                len)
2898 {
2899   const unsigned char *s;
2900   const unsigned char *end;
2901   const unsigned char *last_slash;
2902   
2903   DBUS_CONST_STRING_PREAMBLE (str);
2904   _dbus_assert (start >= 0);
2905   _dbus_assert (len >= 0);
2906   _dbus_assert (start <= real->len);
2907   
2908   if (len > real->len - start)
2909     return FALSE;
2910
2911   if (len > DBUS_MAXIMUM_NAME_LENGTH)
2912     return FALSE;
2913
2914   if (len == 0)
2915     return FALSE;
2916
2917   s = real->str + start;
2918   end = s + len;
2919
2920   if (*s != '/')
2921     return FALSE;
2922   last_slash = s;
2923   ++s;
2924   
2925   while (s != end)
2926     {
2927       if (*s == '/')
2928         {
2929           if ((s - last_slash) < 2)
2930             return FALSE; /* no empty path components allowed */
2931
2932           last_slash = s;
2933         }
2934       
2935       ++s;
2936     }
2937
2938   if ((end - last_slash) < 2 &&
2939       len > 1)
2940     return FALSE; /* trailing slash not allowed unless the string is "/" */
2941   
2942   return TRUE;
2943 }
2944
2945 #define VALID_INITIAL_NAME_CHARACTER(c)         \
2946   ( ((c) >= 'A' && (c) <= 'Z') ||               \
2947     ((c) >= 'a' && (c) <= 'z') ||               \
2948     ((c) == '_') )
2949
2950 #define VALID_NAME_CHARACTER(c)                 \
2951   ( ((c) >= '0' && (c) <= '9') ||               \
2952     ((c) >= 'A' && (c) <= 'Z') ||               \
2953     ((c) >= 'a' && (c) <= 'z') ||               \
2954     ((c) == '_') )
2955
2956 /**
2957  * Checks that the given range of the string is a valid interface name
2958  * in the D-BUS protocol. This includes a length restriction and an
2959  * ASCII subset, see the specification.
2960  *
2961  * @todo this is inconsistent with most of DBusString in that
2962  * it allows a start,len range that isn't in the string.
2963  * 
2964  * @param str the string
2965  * @param start first byte index to check
2966  * @param len number of bytes to check
2967  * @returns #TRUE if the byte range exists and is a valid name
2968  */
2969 dbus_bool_t
2970 _dbus_string_validate_interface (const DBusString  *str,
2971                                  int                start,
2972                                  int                len)
2973 {  
2974   const unsigned char *s;
2975   const unsigned char *end;
2976   const unsigned char *iface;
2977   const unsigned char *last_dot;
2978   
2979   DBUS_CONST_STRING_PREAMBLE (str);
2980   _dbus_assert (start >= 0);
2981   _dbus_assert (len >= 0);
2982   _dbus_assert (start <= real->len);
2983   
2984   if (len > real->len - start)
2985     return FALSE;
2986
2987   if (len > DBUS_MAXIMUM_NAME_LENGTH)
2988     return FALSE;
2989
2990   if (len == 0)
2991     return FALSE;
2992
2993   last_dot = NULL;
2994   iface = real->str + start;
2995   end = iface + len;
2996   s = iface;
2997
2998   /* check special cases of first char so it doesn't have to be done
2999    * in the loop. Note we know len > 0
3000    */
3001   if (_DBUS_UNLIKELY (*s == '.')) /* disallow starting with a . */
3002     return FALSE;
3003   else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
3004     return FALSE;
3005   else
3006     ++s;
3007   
3008   while (s != end)
3009     {
3010       if (*s == '.')
3011         {
3012           if (_DBUS_UNLIKELY ((s + 1) == end))
3013             return FALSE;
3014           else if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*(s + 1))))
3015             return FALSE;
3016           last_dot = s;
3017           ++s; /* we just validated the next char, so skip two */
3018         }
3019       else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
3020         {
3021           return FALSE;
3022         }
3023       
3024       ++s;
3025     }
3026
3027   if (_DBUS_UNLIKELY (last_dot == NULL))
3028     return FALSE;
3029   
3030   return TRUE;
3031 }
3032
3033 /**
3034  * Checks that the given range of the string is a valid member name
3035  * in the D-BUS protocol. This includes a length restriction, etc.,
3036  * see the specification.
3037  *
3038  * @todo this is inconsistent with most of DBusString in that
3039  * it allows a start,len range that isn't in the string.
3040  * 
3041  * @param str the string
3042  * @param start first byte index to check
3043  * @param len number of bytes to check
3044  * @returns #TRUE if the byte range exists and is a valid name
3045  */
3046 dbus_bool_t
3047 _dbus_string_validate_member (const DBusString  *str,
3048                               int                start,
3049                               int                len)
3050 {
3051   const unsigned char *s;
3052   const unsigned char *end;
3053   const unsigned char *member;
3054   
3055   DBUS_CONST_STRING_PREAMBLE (str);
3056   _dbus_assert (start >= 0);
3057   _dbus_assert (len >= 0);
3058   _dbus_assert (start <= real->len);
3059   
3060   if (len > real->len - start)
3061     return FALSE;
3062
3063   if (len > DBUS_MAXIMUM_NAME_LENGTH)
3064     return FALSE;
3065
3066   if (len == 0)
3067     return FALSE;
3068
3069   member = real->str + start;
3070   end = member + len;
3071   s = member;
3072
3073   /* check special cases of first char so it doesn't have to be done
3074    * in the loop. Note we know len > 0
3075    */
3076
3077   if (_DBUS_UNLIKELY (!VALID_INITIAL_NAME_CHARACTER (*s)))
3078     return FALSE;
3079   else
3080     ++s;
3081   
3082   while (s != end)
3083     {
3084       if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
3085         {
3086           return FALSE;
3087         }
3088       
3089       ++s;
3090     }
3091   
3092   return TRUE;
3093 }
3094
3095 /**
3096  * Checks that the given range of the string is a valid error name
3097  * in the D-BUS protocol. This includes a length restriction, etc.,
3098  * see the specification.
3099  *
3100  * @todo this is inconsistent with most of DBusString in that
3101  * it allows a start,len range that isn't in the string.
3102  * 
3103  * @param str the string
3104  * @param start first byte index to check
3105  * @param len number of bytes to check
3106  * @returns #TRUE if the byte range exists and is a valid name
3107  */
3108 dbus_bool_t
3109 _dbus_string_validate_error_name (const DBusString  *str,
3110                                   int                start,
3111                                   int                len)
3112 {
3113   /* Same restrictions as interface name at the moment */
3114   return _dbus_string_validate_interface (str, start, len);
3115 }
3116
3117 /* This assumes the first char exists and is ':' */
3118 static dbus_bool_t
3119 _dbus_string_validate_base_service (const DBusString  *str,
3120                                     int                start,
3121                                     int                len)
3122 {
3123   const unsigned char *s;
3124   const unsigned char *end;
3125   const unsigned char *service;
3126   
3127   DBUS_CONST_STRING_PREAMBLE (str);
3128   _dbus_assert (start >= 0);
3129   _dbus_assert (len >= 0);
3130   _dbus_assert (start <= real->len);
3131   
3132   if (len > real->len - start)
3133     return FALSE;
3134
3135   if (len > DBUS_MAXIMUM_NAME_LENGTH)
3136     return FALSE;
3137
3138   _dbus_assert (len > 0);
3139
3140   service = real->str + start;
3141   end = service + len;
3142   _dbus_assert (*service == ':');
3143   s = service + 1;
3144   
3145   while (s != end)
3146     {
3147       if (*s == '.')
3148         {
3149           if (_DBUS_UNLIKELY ((s + 1) == end))
3150             return FALSE;
3151           if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*(s + 1))))
3152             return FALSE;
3153           ++s; /* we just validated the next char, so skip two */
3154         }
3155       else if (_DBUS_UNLIKELY (!VALID_NAME_CHARACTER (*s)))
3156         {
3157           return FALSE;
3158         }
3159       
3160       ++s;
3161     }
3162   
3163   return TRUE;
3164 }
3165
3166 /**
3167  * Checks that the given range of the string is a valid service name
3168  * in the D-BUS protocol. This includes a length restriction, etc.,
3169  * see the specification.
3170  *
3171  * @todo this is inconsistent with most of DBusString in that
3172  * it allows a start,len range that isn't in the string.
3173  * 
3174  * @param str the string
3175  * @param start first byte index to check
3176  * @param len number of bytes to check
3177  * @returns #TRUE if the byte range exists and is a valid name
3178  */
3179 dbus_bool_t
3180 _dbus_string_validate_service (const DBusString  *str,
3181                                int                start,
3182                                int                len)
3183 {
3184   if (_DBUS_UNLIKELY (len == 0))
3185     return FALSE;
3186   if (_dbus_string_get_byte (str, start) == ':')
3187     return _dbus_string_validate_base_service (str, start, len);
3188   else
3189     return _dbus_string_validate_interface (str, start, len);
3190 }
3191
3192 /**
3193  * Clears all allocated bytes in the string to zero.
3194  *
3195  * @param str the string
3196  */
3197 void
3198 _dbus_string_zero (DBusString *str)
3199 {
3200   DBUS_STRING_PREAMBLE (str);
3201
3202   memset (real->str - real->align_offset, '\0', real->allocated);
3203 }
3204 /** @} */
3205
3206 #ifdef DBUS_BUILD_TESTS
3207 #include "dbus-test.h"
3208 #include <stdio.h>
3209
3210 static void
3211 test_max_len (DBusString *str,
3212               int         max_len)
3213 {
3214   if (max_len > 0)
3215     {
3216       if (!_dbus_string_set_length (str, max_len - 1))
3217         _dbus_assert_not_reached ("setting len to one less than max should have worked");
3218     }
3219
3220   if (!_dbus_string_set_length (str, max_len))
3221     _dbus_assert_not_reached ("setting len to max len should have worked");
3222
3223   if (_dbus_string_set_length (str, max_len + 1))
3224     _dbus_assert_not_reached ("setting len to one more than max len should not have worked");
3225
3226   if (!_dbus_string_set_length (str, 0))
3227     _dbus_assert_not_reached ("setting len to zero should have worked");
3228 }
3229
3230 static void
3231 test_base64_roundtrip (const unsigned char *data,
3232                        int                  len)
3233 {
3234   DBusString orig;
3235   DBusString encoded;
3236   DBusString decoded;
3237
3238   if (len < 0)
3239     len = strlen (data);
3240   
3241   if (!_dbus_string_init (&orig))
3242     _dbus_assert_not_reached ("could not init string");
3243
3244   if (!_dbus_string_init (&encoded))
3245     _dbus_assert_not_reached ("could not init string");
3246   
3247   if (!_dbus_string_init (&decoded))
3248     _dbus_assert_not_reached ("could not init string");
3249
3250   if (!_dbus_string_append_len (&orig, data, len))
3251     _dbus_assert_not_reached ("couldn't append orig data");
3252
3253   if (!_dbus_string_base64_encode (&orig, 0, &encoded, 0))
3254     _dbus_assert_not_reached ("could not encode");
3255
3256   if (!_dbus_string_base64_decode (&encoded, 0, &decoded, 0))
3257     _dbus_assert_not_reached ("could not decode");
3258
3259   if (!_dbus_string_equal (&orig, &decoded))
3260     {
3261       const char *s;
3262       
3263       printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n",
3264               _dbus_string_get_length (&orig),
3265               _dbus_string_get_length (&encoded),
3266               _dbus_string_get_length (&decoded));
3267       printf ("Original: %s\n", data);
3268       s = _dbus_string_get_const_data (&decoded);
3269       printf ("Decoded: %s\n", s);
3270       _dbus_assert_not_reached ("original string not the same as string decoded from base64");
3271     }
3272   
3273   _dbus_string_free (&orig);
3274   _dbus_string_free (&encoded);
3275   _dbus_string_free (&decoded);  
3276 }
3277
3278 static void
3279 test_hex_roundtrip (const unsigned char *data,
3280                     int                  len)
3281 {
3282   DBusString orig;
3283   DBusString encoded;
3284   DBusString decoded;
3285
3286   if (len < 0)
3287     len = strlen (data);
3288   
3289   if (!_dbus_string_init (&orig))
3290     _dbus_assert_not_reached ("could not init string");
3291
3292   if (!_dbus_string_init (&encoded))
3293     _dbus_assert_not_reached ("could not init string");
3294   
3295   if (!_dbus_string_init (&decoded))
3296     _dbus_assert_not_reached ("could not init string");
3297
3298   if (!_dbus_string_append_len (&orig, data, len))
3299     _dbus_assert_not_reached ("couldn't append orig data");
3300
3301   if (!_dbus_string_hex_encode (&orig, 0, &encoded, 0))
3302     _dbus_assert_not_reached ("could not encode");
3303
3304   if (!_dbus_string_hex_decode (&encoded, 0, &decoded, 0))
3305     _dbus_assert_not_reached ("could not decode");
3306     
3307   if (!_dbus_string_equal (&orig, &decoded))
3308     {
3309       const char *s;
3310       
3311       printf ("Original string %d bytes encoded %d bytes decoded %d bytes\n",
3312               _dbus_string_get_length (&orig),
3313               _dbus_string_get_length (&encoded),
3314               _dbus_string_get_length (&decoded));
3315       printf ("Original: %s\n", data);
3316       s = _dbus_string_get_const_data (&decoded);
3317       printf ("Decoded: %s\n", s);
3318       _dbus_assert_not_reached ("original string not the same as string decoded from base64");
3319     }
3320   
3321   _dbus_string_free (&orig);
3322   _dbus_string_free (&encoded);
3323   _dbus_string_free (&decoded);  
3324 }
3325
3326 typedef void (* TestRoundtripFunc) (const unsigned char *data,
3327                                     int                  len);
3328 static void
3329 test_roundtrips (TestRoundtripFunc func)
3330 {
3331   (* func) ("Hello this is a string\n", -1);
3332   (* func) ("Hello this is a string\n1", -1);
3333   (* func) ("Hello this is a string\n12", -1);
3334   (* func) ("Hello this is a string\n123", -1);
3335   (* func) ("Hello this is a string\n1234", -1);
3336   (* func) ("Hello this is a string\n12345", -1);
3337   (* func) ("", 0);
3338   (* func) ("1", 1);
3339   (* func) ("12", 2);
3340   (* func) ("123", 3);
3341   (* func) ("1234", 4);
3342   (* func) ("12345", 5);
3343   (* func) ("", 1);
3344   (* func) ("1", 2);
3345   (* func) ("12", 3);
3346   (* func) ("123", 4);
3347   (* func) ("1234", 5);
3348   (* func) ("12345", 6);
3349   {
3350     unsigned char buf[512];
3351     int i;
3352     
3353     i = 0;
3354     while (i < _DBUS_N_ELEMENTS (buf))
3355       {
3356         buf[i] = i;
3357         ++i;
3358       }
3359     i = 0;
3360     while (i < _DBUS_N_ELEMENTS (buf))
3361       {
3362         (* func) (buf, i);
3363         ++i;
3364       }
3365   }
3366 }
3367
3368
3369 /**
3370  * @ingroup DBusStringInternals
3371  * Unit test for DBusString.
3372  *
3373  * @todo Need to write tests for _dbus_string_copy() and
3374  * _dbus_string_move() moving to/from each of start/middle/end of a
3375  * string. Also need tests for _dbus_string_move_len ()
3376  * 
3377  * @returns #TRUE on success.
3378  */
3379 dbus_bool_t
3380 _dbus_string_test (void)
3381 {
3382   DBusString str;
3383   DBusString other;
3384   int i, end;
3385   long v;
3386   double d;
3387   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 };
3388   char *s;
3389   dbus_unichar_t ch;
3390   const char *valid_paths[] = {
3391     "/",
3392     "/foo/bar",
3393     "/foo",
3394     "/foo/bar/baz"
3395   };
3396   const char *invalid_paths[] = {
3397     "bar",
3398     "bar/baz",
3399     "/foo/bar/",
3400     "/foo/"
3401     "foo/",
3402     "boo//blah",
3403     "//",
3404     "///",
3405     "foo///blah/",
3406     "Hello World",
3407     "",
3408     "   ",
3409     "foo bar"
3410   };
3411
3412   const char *valid_interfaces[] = {
3413     "org.freedesktop.Foo",
3414     "Bar.Baz",
3415     "Blah.Blah.Blah.Blah.Blah",
3416     "a.b",
3417     "a.b.c.d.e.f.g",
3418     "a0.b1.c2.d3.e4.f5.g6",
3419     "abc123.foo27"
3420   };
3421   const char *invalid_interfaces[] = {
3422     ".",
3423     "",
3424     "..",
3425     ".Foo.Bar",
3426     "..Foo.Bar",
3427     "Foo.Bar.",
3428     "Foo.Bar..",
3429     "Foo",
3430     "9foo.bar.baz",
3431     "foo.bar..baz",
3432     "foo.bar...baz",
3433     "foo.bar.b..blah",
3434     ":",
3435     ":0-1",
3436     "10",
3437     ":11.34324",
3438     "0.0.0",
3439     "0..0",
3440     "foo.Bar.%",
3441     "foo.Bar!!",
3442     "!Foo.bar.bz",
3443     "foo.$.blah",
3444     "",
3445     "   ",
3446     "foo bar"
3447   };
3448
3449   const char *valid_base_services[] = {
3450     ":0",
3451     ":a",
3452     ":",
3453     ":.a",
3454     ":.1",
3455     ":0.1",
3456     ":000.2222",
3457     ":.blah",
3458     ":abce.freedesktop.blah"
3459   };
3460   const char *invalid_base_services[] = {
3461     ":-",
3462     ":!",
3463     ":0-10",
3464     ":blah.",
3465     ":blah.",
3466     ":blah..org",
3467     ":blah.org..",
3468     ":..blah.org",
3469     "",
3470     "   ",
3471     "foo bar"
3472   };
3473
3474   const char *valid_members[] = {
3475     "Hello",
3476     "Bar",
3477     "foobar",
3478     "_foobar",
3479     "foo89"
3480   };
3481
3482   const char *invalid_members[] = {
3483     "9Hello",
3484     "10",
3485     "1",
3486     "foo-bar",
3487     "blah.org",
3488     ".blah",
3489     "blah.",
3490     "Hello.",
3491     "!foo",
3492     "",
3493     "   ",
3494     "foo bar"
3495   };
3496   
3497   i = 0;
3498   while (i < _DBUS_N_ELEMENTS (lens))
3499     {
3500       if (!_dbus_string_init (&str))
3501         _dbus_assert_not_reached ("failed to init string");
3502
3503       set_max_length (&str, lens[i]);
3504       
3505       test_max_len (&str, lens[i]);
3506       _dbus_string_free (&str);
3507
3508       ++i;
3509     }
3510
3511   /* Test shortening and setting length */
3512   i = 0;
3513   while (i < _DBUS_N_ELEMENTS (lens))
3514     {
3515       int j;
3516       
3517       if (!_dbus_string_init (&str))
3518         _dbus_assert_not_reached ("failed to init string");
3519
3520       set_max_length (&str, lens[i]);
3521       
3522       if (!_dbus_string_set_length (&str, lens[i]))
3523         _dbus_assert_not_reached ("failed to set string length");
3524
3525       j = lens[i];
3526       while (j > 0)
3527         {
3528           _dbus_assert (_dbus_string_get_length (&str) == j);
3529           if (j > 0)
3530             {
3531               _dbus_string_shorten (&str, 1);
3532               _dbus_assert (_dbus_string_get_length (&str) == (j - 1));
3533             }
3534           --j;
3535         }
3536       
3537       _dbus_string_free (&str);
3538
3539       ++i;
3540     }
3541
3542   /* Test appending data */
3543   if (!_dbus_string_init (&str))
3544     _dbus_assert_not_reached ("failed to init string");
3545
3546   i = 0;
3547   while (i < 10)
3548     {
3549       if (!_dbus_string_append (&str, "a"))
3550         _dbus_assert_not_reached ("failed to append string to string\n");
3551
3552       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 1);
3553
3554       if (!_dbus_string_append_byte (&str, 'b'))
3555         _dbus_assert_not_reached ("failed to append byte to string\n");
3556
3557       _dbus_assert (_dbus_string_get_length (&str) == i * 2 + 2);
3558                     
3559       ++i;
3560     }
3561
3562   _dbus_string_free (&str);
3563
3564   /* Check steal_data */
3565   
3566   if (!_dbus_string_init (&str))
3567     _dbus_assert_not_reached ("failed to init string");
3568
3569   if (!_dbus_string_append (&str, "Hello World"))
3570     _dbus_assert_not_reached ("could not append to string");
3571
3572   i = _dbus_string_get_length (&str);
3573   
3574   if (!_dbus_string_steal_data (&str, &s))
3575     _dbus_assert_not_reached ("failed to steal data");
3576
3577   _dbus_assert (_dbus_string_get_length (&str) == 0);
3578   _dbus_assert (((int)strlen (s)) == i);
3579
3580   dbus_free (s);
3581
3582   /* Check move */
3583   
3584   if (!_dbus_string_append (&str, "Hello World"))
3585     _dbus_assert_not_reached ("could not append to string");
3586
3587   i = _dbus_string_get_length (&str);
3588
3589   if (!_dbus_string_init (&other))
3590     _dbus_assert_not_reached ("could not init string");
3591   
3592   if (!_dbus_string_move (&str, 0, &other, 0))
3593     _dbus_assert_not_reached ("could not move");
3594
3595   _dbus_assert (_dbus_string_get_length (&str) == 0);
3596   _dbus_assert (_dbus_string_get_length (&other) == i);
3597
3598   if (!_dbus_string_append (&str, "Hello World"))
3599     _dbus_assert_not_reached ("could not append to string");
3600   
3601   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other)))
3602     _dbus_assert_not_reached ("could not move");
3603
3604   _dbus_assert (_dbus_string_get_length (&str) == 0);
3605   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
3606
3607     if (!_dbus_string_append (&str, "Hello World"))
3608     _dbus_assert_not_reached ("could not append to string");
3609   
3610   if (!_dbus_string_move (&str, 0, &other, _dbus_string_get_length (&other) / 2))
3611     _dbus_assert_not_reached ("could not move");
3612
3613   _dbus_assert (_dbus_string_get_length (&str) == 0);
3614   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
3615   
3616   _dbus_string_free (&other);
3617
3618   /* Check copy */
3619   
3620   if (!_dbus_string_append (&str, "Hello World"))
3621     _dbus_assert_not_reached ("could not append to string");
3622
3623   i = _dbus_string_get_length (&str);
3624   
3625   if (!_dbus_string_init (&other))
3626     _dbus_assert_not_reached ("could not init string");
3627   
3628   if (!_dbus_string_copy (&str, 0, &other, 0))
3629     _dbus_assert_not_reached ("could not copy");
3630
3631   _dbus_assert (_dbus_string_get_length (&str) == i);
3632   _dbus_assert (_dbus_string_get_length (&other) == i);
3633
3634   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other)))
3635     _dbus_assert_not_reached ("could not copy");
3636
3637   _dbus_assert (_dbus_string_get_length (&str) == i);
3638   _dbus_assert (_dbus_string_get_length (&other) == i * 2);
3639   _dbus_assert (_dbus_string_equal_c_str (&other,
3640                                           "Hello WorldHello World"));
3641
3642   if (!_dbus_string_copy (&str, 0, &other, _dbus_string_get_length (&other) / 2))
3643     _dbus_assert_not_reached ("could not copy");
3644
3645   _dbus_assert (_dbus_string_get_length (&str) == i);
3646   _dbus_assert (_dbus_string_get_length (&other) == i * 3);
3647   _dbus_assert (_dbus_string_equal_c_str (&other,
3648                                           "Hello WorldHello WorldHello World"));
3649   
3650   _dbus_string_free (&str);
3651   _dbus_string_free (&other);
3652
3653   /* Check replace */
3654
3655   if (!_dbus_string_init (&str))
3656     _dbus_assert_not_reached ("failed to init string");
3657   
3658   if (!_dbus_string_append (&str, "Hello World"))
3659     _dbus_assert_not_reached ("could not append to string");
3660
3661   i = _dbus_string_get_length (&str);
3662   
3663   if (!_dbus_string_init (&other))
3664     _dbus_assert_not_reached ("could not init string");
3665   
3666   if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
3667                                  &other, 0, _dbus_string_get_length (&other)))
3668     _dbus_assert_not_reached ("could not replace");
3669
3670   _dbus_assert (_dbus_string_get_length (&str) == i);
3671   _dbus_assert (_dbus_string_get_length (&other) == i);
3672   _dbus_assert (_dbus_string_equal_c_str (&other, "Hello World"));
3673   
3674   if (!_dbus_string_replace_len (&str, 0, _dbus_string_get_length (&str),
3675                                  &other, 5, 1))
3676     _dbus_assert_not_reached ("could not replace center space");
3677
3678   _dbus_assert (_dbus_string_get_length (&str) == i);
3679   _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
3680   _dbus_assert (_dbus_string_equal_c_str (&other,
3681                                           "HelloHello WorldWorld"));
3682
3683   
3684   if (!_dbus_string_replace_len (&str, 1, 1,
3685                                  &other,
3686                                  _dbus_string_get_length (&other) - 1,
3687                                  1))
3688     _dbus_assert_not_reached ("could not replace end character");
3689   
3690   _dbus_assert (_dbus_string_get_length (&str) == i);
3691   _dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
3692   _dbus_assert (_dbus_string_equal_c_str (&other,
3693                                           "HelloHello WorldWorle"));
3694   
3695   _dbus_string_free (&str);
3696   _dbus_string_free (&other);
3697   
3698   /* Check append/get unichar */
3699   
3700   if (!_dbus_string_init (&str))
3701     _dbus_assert_not_reached ("failed to init string");
3702
3703   ch = 0;
3704   if (!_dbus_string_append_unichar (&str, 0xfffc))
3705     _dbus_assert_not_reached ("failed to append unichar");
3706
3707   _dbus_string_get_unichar (&str, 0, &ch, &i);
3708
3709   _dbus_assert (ch == 0xfffc);
3710   _dbus_assert (i == _dbus_string_get_length (&str));
3711
3712   _dbus_string_free (&str);
3713
3714   /* Check insert/set/get byte */
3715   
3716   if (!_dbus_string_init (&str))
3717     _dbus_assert_not_reached ("failed to init string");
3718
3719   if (!_dbus_string_append (&str, "Hello"))
3720     _dbus_assert_not_reached ("failed to append Hello");
3721
3722   _dbus_assert (_dbus_string_get_byte (&str, 0) == 'H');
3723   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'e');
3724   _dbus_assert (_dbus_string_get_byte (&str, 2) == 'l');
3725   _dbus_assert (_dbus_string_get_byte (&str, 3) == 'l');
3726   _dbus_assert (_dbus_string_get_byte (&str, 4) == 'o');
3727
3728   _dbus_string_set_byte (&str, 1, 'q');
3729   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'q');
3730
3731   if (!_dbus_string_insert_bytes (&str, 0, 1, 255))
3732     _dbus_assert_not_reached ("can't insert byte");
3733
3734   if (!_dbus_string_insert_bytes (&str, 2, 4, 'Z'))
3735     _dbus_assert_not_reached ("can't insert byte");
3736
3737   if (!_dbus_string_insert_bytes (&str, _dbus_string_get_length (&str), 1, 'W'))
3738     _dbus_assert_not_reached ("can't insert byte");
3739   
3740   _dbus_assert (_dbus_string_get_byte (&str, 0) == 255);
3741   _dbus_assert (_dbus_string_get_byte (&str, 1) == 'H');
3742   _dbus_assert (_dbus_string_get_byte (&str, 2) == 'Z');
3743   _dbus_assert (_dbus_string_get_byte (&str, 3) == 'Z');
3744   _dbus_assert (_dbus_string_get_byte (&str, 4) == 'Z');
3745   _dbus_assert (_dbus_string_get_byte (&str, 5) == 'Z');
3746   _dbus_assert (_dbus_string_get_byte (&str, 6) == 'q');
3747   _dbus_assert (_dbus_string_get_byte (&str, 7) == 'l');
3748   _dbus_assert (_dbus_string_get_byte (&str, 8) == 'l');
3749   _dbus_assert (_dbus_string_get_byte (&str, 9) == 'o');
3750   _dbus_assert (_dbus_string_get_byte (&str, 10) == 'W');
3751
3752   _dbus_string_free (&str);
3753   
3754   /* Check append/parse int/double */
3755   
3756   if (!_dbus_string_init (&str))
3757     _dbus_assert_not_reached ("failed to init string");
3758
3759   if (!_dbus_string_append_int (&str, 27))
3760     _dbus_assert_not_reached ("failed to append int");
3761
3762   i = _dbus_string_get_length (&str);
3763
3764   if (!_dbus_string_parse_int (&str, 0, &v, &end))
3765     _dbus_assert_not_reached ("failed to parse int");
3766
3767   _dbus_assert (v == 27);
3768   _dbus_assert (end == i);
3769
3770   _dbus_string_free (&str);
3771   
3772   if (!_dbus_string_init (&str))
3773     _dbus_assert_not_reached ("failed to init string");
3774   
3775   if (!_dbus_string_append_double (&str, 50.3))
3776     _dbus_assert_not_reached ("failed to append float");
3777
3778   i = _dbus_string_get_length (&str);
3779
3780   if (!_dbus_string_parse_double (&str, 0, &d, &end))
3781     _dbus_assert_not_reached ("failed to parse float");
3782
3783   _dbus_assert (d > (50.3 - 1e-6) && d < (50.3 + 1e-6));
3784   _dbus_assert (end == i);
3785
3786   _dbus_string_free (&str);
3787
3788   /* Test find */
3789   if (!_dbus_string_init (&str))
3790     _dbus_assert_not_reached ("failed to init string");
3791
3792   if (!_dbus_string_append (&str, "Hello"))
3793     _dbus_assert_not_reached ("couldn't append to string");
3794   
3795   if (!_dbus_string_find (&str, 0, "He", &i))
3796     _dbus_assert_not_reached ("didn't find 'He'");
3797   _dbus_assert (i == 0);
3798
3799   if (!_dbus_string_find (&str, 0, "Hello", &i))
3800     _dbus_assert_not_reached ("didn't find 'Hello'");
3801   _dbus_assert (i == 0);
3802   
3803   if (!_dbus_string_find (&str, 0, "ello", &i))
3804     _dbus_assert_not_reached ("didn't find 'ello'");
3805   _dbus_assert (i == 1);
3806
3807   if (!_dbus_string_find (&str, 0, "lo", &i))
3808     _dbus_assert_not_reached ("didn't find 'lo'");
3809   _dbus_assert (i == 3);
3810
3811   if (!_dbus_string_find (&str, 2, "lo", &i))
3812     _dbus_assert_not_reached ("didn't find 'lo'");
3813   _dbus_assert (i == 3);
3814
3815   if (_dbus_string_find (&str, 4, "lo", &i))
3816     _dbus_assert_not_reached ("did find 'lo'");
3817   
3818   if (!_dbus_string_find (&str, 0, "l", &i))
3819     _dbus_assert_not_reached ("didn't find 'l'");
3820   _dbus_assert (i == 2);
3821
3822   if (!_dbus_string_find (&str, 0, "H", &i))
3823     _dbus_assert_not_reached ("didn't find 'H'");
3824   _dbus_assert (i == 0);
3825
3826   if (!_dbus_string_find (&str, 0, "", &i))
3827     _dbus_assert_not_reached ("didn't find ''");
3828   _dbus_assert (i == 0);
3829   
3830   if (_dbus_string_find (&str, 0, "Hello!", NULL))
3831     _dbus_assert_not_reached ("Did find 'Hello!'");
3832
3833   if (_dbus_string_find (&str, 0, "Oh, Hello", NULL))
3834     _dbus_assert_not_reached ("Did find 'Oh, Hello'");
3835   
3836   if (_dbus_string_find (&str, 0, "ill", NULL))
3837     _dbus_assert_not_reached ("Did find 'ill'");
3838
3839   if (_dbus_string_find (&str, 0, "q", NULL))
3840     _dbus_assert_not_reached ("Did find 'q'");
3841
3842   if (!_dbus_string_find_to (&str, 0, 2, "He", NULL))
3843     _dbus_assert_not_reached ("Didn't find 'He'");
3844
3845   if (_dbus_string_find_to (&str, 0, 2, "Hello", NULL))
3846     _dbus_assert_not_reached ("Did find 'Hello'");
3847
3848   if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'H', &i))
3849     _dbus_assert_not_reached ("Did not find 'H'");
3850   _dbus_assert (i == 0);
3851
3852   if (!_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str), 'o', &i))
3853     _dbus_assert_not_reached ("Did not find 'o'");
3854   _dbus_assert (i == _dbus_string_get_length (&str) - 1);
3855
3856   if (_dbus_string_find_byte_backward (&str, _dbus_string_get_length (&str) - 1, 'o', &i))
3857     _dbus_assert_not_reached ("Did find 'o'");
3858   _dbus_assert (i == -1);
3859
3860   if (_dbus_string_find_byte_backward (&str, 1, 'e', &i))
3861     _dbus_assert_not_reached ("Did find 'e'");
3862   _dbus_assert (i == -1);
3863
3864   if (!_dbus_string_find_byte_backward (&str, 2, 'e', &i))
3865     _dbus_assert_not_reached ("Didn't find 'e'");
3866   _dbus_assert (i == 1);
3867   
3868   _dbus_string_free (&str);
3869
3870   /* Base 64 and Hex encoding */
3871   test_roundtrips (test_base64_roundtrip);
3872   test_roundtrips (test_hex_roundtrip);
3873
3874   /* Path validation */
3875   i = 0;
3876   while (i < (int) _DBUS_N_ELEMENTS (valid_paths))
3877     {
3878       _dbus_string_init_const (&str, valid_paths[i]);
3879
3880       if (!_dbus_string_validate_path (&str, 0,
3881                                        _dbus_string_get_length (&str)))
3882         {
3883           _dbus_warn ("Path \"%s\" should have been valid\n", valid_paths[i]);
3884           _dbus_assert_not_reached ("invalid path");
3885         }
3886       
3887       ++i;
3888     }
3889
3890   i = 0;
3891   while (i < (int) _DBUS_N_ELEMENTS (invalid_paths))
3892     {
3893       _dbus_string_init_const (&str, invalid_paths[i]);
3894       
3895       if (_dbus_string_validate_path (&str, 0,
3896                                       _dbus_string_get_length (&str)))
3897         {
3898           _dbus_warn ("Path \"%s\" should have been invalid\n", invalid_paths[i]);
3899           _dbus_assert_not_reached ("valid path");
3900         }
3901       
3902       ++i;
3903     }
3904
3905   /* Interface validation */
3906   i = 0;
3907   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
3908     {
3909       _dbus_string_init_const (&str, valid_interfaces[i]);
3910
3911       if (!_dbus_string_validate_interface (&str, 0,
3912                                             _dbus_string_get_length (&str)))
3913         {
3914           _dbus_warn ("Interface \"%s\" should have been valid\n", valid_interfaces[i]);
3915           _dbus_assert_not_reached ("invalid interface");
3916         }
3917       
3918       ++i;
3919     }
3920
3921   i = 0;
3922   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
3923     {
3924       _dbus_string_init_const (&str, invalid_interfaces[i]);
3925       
3926       if (_dbus_string_validate_interface (&str, 0,
3927                                            _dbus_string_get_length (&str)))
3928         {
3929           _dbus_warn ("Interface \"%s\" should have been invalid\n", invalid_interfaces[i]);
3930           _dbus_assert_not_reached ("valid interface");
3931         }
3932       
3933       ++i;
3934     }
3935
3936   /* Service validation (check that valid interfaces are valid services,
3937    * and invalid interfaces are invalid services except if they start with ':')
3938    */
3939   i = 0;
3940   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
3941     {
3942       _dbus_string_init_const (&str, valid_interfaces[i]);
3943
3944       if (!_dbus_string_validate_service (&str, 0,
3945                                           _dbus_string_get_length (&str)))
3946         {
3947           _dbus_warn ("Service \"%s\" should have been valid\n", valid_interfaces[i]);
3948           _dbus_assert_not_reached ("invalid service");
3949         }
3950       
3951       ++i;
3952     }
3953
3954   i = 0;
3955   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
3956     {
3957       if (invalid_interfaces[i][0] != ':')
3958         {
3959           _dbus_string_init_const (&str, invalid_interfaces[i]);
3960           
3961           if (_dbus_string_validate_service (&str, 0,
3962                                              _dbus_string_get_length (&str)))
3963             {
3964               _dbus_warn ("Service \"%s\" should have been invalid\n", invalid_interfaces[i]);
3965               _dbus_assert_not_reached ("valid service");
3966             }
3967         }
3968       
3969       ++i;
3970     }
3971
3972   /* Base service validation */
3973   i = 0;
3974   while (i < (int) _DBUS_N_ELEMENTS (valid_base_services))
3975     {
3976       _dbus_string_init_const (&str, valid_base_services[i]);
3977
3978       if (!_dbus_string_validate_service (&str, 0,
3979                                           _dbus_string_get_length (&str)))
3980         {
3981           _dbus_warn ("Service \"%s\" should have been valid\n", valid_base_services[i]);
3982           _dbus_assert_not_reached ("invalid base service");
3983         }
3984       
3985       ++i;
3986     }
3987
3988   i = 0;
3989   while (i < (int) _DBUS_N_ELEMENTS (invalid_base_services))
3990     {
3991       _dbus_string_init_const (&str, invalid_base_services[i]);
3992       
3993       if (_dbus_string_validate_service (&str, 0,
3994                                          _dbus_string_get_length (&str)))
3995         {
3996           _dbus_warn ("Service \"%s\" should have been invalid\n", invalid_base_services[i]);
3997           _dbus_assert_not_reached ("valid base service");
3998         }
3999       
4000       ++i;
4001     }
4002
4003
4004   /* Error name validation (currently identical to interfaces)
4005    */
4006   i = 0;
4007   while (i < (int) _DBUS_N_ELEMENTS (valid_interfaces))
4008     {
4009       _dbus_string_init_const (&str, valid_interfaces[i]);
4010
4011       if (!_dbus_string_validate_error_name (&str, 0,
4012                                              _dbus_string_get_length (&str)))
4013         {
4014           _dbus_warn ("Error name \"%s\" should have been valid\n", valid_interfaces[i]);
4015           _dbus_assert_not_reached ("invalid error name");
4016         }
4017       
4018       ++i;
4019     }
4020
4021   i = 0;
4022   while (i < (int) _DBUS_N_ELEMENTS (invalid_interfaces))
4023     {
4024       if (invalid_interfaces[i][0] != ':')
4025         {
4026           _dbus_string_init_const (&str, invalid_interfaces[i]);
4027           
4028           if (_dbus_string_validate_error_name (&str, 0,
4029                                                 _dbus_string_get_length (&str)))
4030             {
4031               _dbus_warn ("Error name \"%s\" should have been invalid\n", invalid_interfaces[i]);
4032               _dbus_assert_not_reached ("valid error name");
4033             }
4034         }
4035       
4036       ++i;
4037     }
4038   
4039   /* Member validation */
4040   i = 0;
4041   while (i < (int) _DBUS_N_ELEMENTS (valid_members))
4042     {
4043       _dbus_string_init_const (&str, valid_members[i]);
4044
4045       if (!_dbus_string_validate_member (&str, 0,
4046                                          _dbus_string_get_length (&str)))
4047         {
4048           _dbus_warn ("Member \"%s\" should have been valid\n", valid_members[i]);
4049           _dbus_assert_not_reached ("invalid member");
4050         }
4051       
4052       ++i;
4053     }
4054
4055   i = 0;
4056   while (i < (int) _DBUS_N_ELEMENTS (invalid_members))
4057     {
4058       _dbus_string_init_const (&str, invalid_members[i]);
4059       
4060       if (_dbus_string_validate_member (&str, 0,
4061                                         _dbus_string_get_length (&str)))
4062         {
4063           _dbus_warn ("Member \"%s\" should have been invalid\n", invalid_members[i]);
4064           _dbus_assert_not_reached ("valid member");
4065         }
4066       
4067       ++i;
4068     }
4069
4070   /* Validate claimed length longer than real length */
4071   _dbus_string_init_const (&str, "abc.efg");
4072   if (_dbus_string_validate_service (&str, 0, 8))
4073     _dbus_assert_not_reached ("validated too-long string");
4074   if (_dbus_string_validate_interface (&str, 0, 8))
4075     _dbus_assert_not_reached ("validated too-long string");
4076   if (_dbus_string_validate_error_name (&str, 0, 8))
4077     _dbus_assert_not_reached ("validated too-long string");
4078
4079   _dbus_string_init_const (&str, "abc");
4080   if (_dbus_string_validate_member (&str, 0, 4))
4081     _dbus_assert_not_reached ("validated too-long string");
4082
4083   /* Validate string exceeding max name length */
4084   if (!_dbus_string_init (&str))
4085     _dbus_assert_not_reached ("no memory");
4086
4087   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
4088     if (!_dbus_string_append (&str, "abc.def"))
4089       _dbus_assert_not_reached ("no memory");
4090
4091   if (_dbus_string_validate_service (&str, 0, _dbus_string_get_length (&str)))
4092     _dbus_assert_not_reached ("validated overmax string");
4093   if (_dbus_string_validate_interface (&str, 0, _dbus_string_get_length (&str)))
4094     _dbus_assert_not_reached ("validated overmax string");
4095   if (_dbus_string_validate_error_name (&str, 0, _dbus_string_get_length (&str)))
4096     _dbus_assert_not_reached ("validated overmax string");
4097
4098   /* overlong member */
4099   _dbus_string_set_length (&str, 0);
4100   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
4101     if (!_dbus_string_append (&str, "abc"))
4102       _dbus_assert_not_reached ("no memory");  
4103
4104   if (_dbus_string_validate_member (&str, 0, _dbus_string_get_length (&str)))
4105     _dbus_assert_not_reached ("validated overmax string");
4106
4107   /* overlong base service */
4108   _dbus_string_set_length (&str, 0);
4109   _dbus_string_append (&str, ":");
4110   while (_dbus_string_get_length (&str) <= DBUS_MAXIMUM_NAME_LENGTH)
4111     if (!_dbus_string_append (&str, "abc"))
4112       _dbus_assert_not_reached ("no memory");  
4113
4114   if (_dbus_string_validate_service (&str, 0, _dbus_string_get_length (&str)))
4115     _dbus_assert_not_reached ("validated overmax string");
4116   
4117   _dbus_string_free (&str);
4118   
4119   return TRUE;
4120 }
4121
4122 #endif /* DBUS_BUILD_TESTS */