2 Unix SMB/CIFS implementation.
3 Samba utility functions
5 Copyright (C) Andrew Tridgell 1992-2001
6 Copyright (C) Simo Sorce 2001-2002
7 Copyright (C) Martin Pool 2003
8 Copyright (C) James Peach 2005
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "libcli/raw/smb.h"
28 #include "system/locale.h"
32 * @brief String utilities.
37 Trim the specified elements off the front and back of a string.
39 _PUBLIC_ BOOL
trim_string(char *s
,const char *front
,const char *back
)
46 /* Ignore null or empty strings. */
47 if (!s
|| (s
[0] == '\0'))
50 front_len
= front
? strlen(front
) : 0;
51 back_len
= back
? strlen(back
) : 0;
56 while (len
&& strncmp(s
, front
, front_len
)==0) {
57 /* Must use memmove here as src & dest can
58 * easily overlap. Found by valgrind. JRA. */
59 memmove(s
, s
+front_len
, (len
-front_len
)+1);
66 while ((len
>= back_len
) && strncmp(s
+len
-back_len
,back
,back_len
)==0) {
76 Find the number of 'c' chars in a string
78 _PUBLIC_
size_t count_chars(const char *s
, char c
)
93 Safe string copy into a known length string. maxlength does not
94 include the terminating zero.
96 _PUBLIC_
char *safe_strcpy(char *dest
,const char *src
, size_t maxlength
)
101 DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
106 /* We intentionally write out at the extremity of the destination
107 * string. If the destination is too short (e.g. pstrcpy into mallocd
108 * or fstring) then this should cause an error under a memory
110 dest
[maxlength
] = '\0';
111 if (PTR_DIFF(&len
, dest
) > 0) { /* check if destination is on the stack, ok if so */
112 log_suspicious_usage("safe_strcpy", src
);
123 if (len
> maxlength
) {
124 DEBUG(0,("ERROR: string overflow by %u (%u - %u) in safe_strcpy [%.50s]\n",
125 (uint_t
)(len
-maxlength
), (unsigned)len
, (unsigned)maxlength
, src
));
129 memmove(dest
, src
, len
);
135 Safe string cat into a string. maxlength does not
136 include the terminating zero.
138 _PUBLIC_
char *safe_strcat(char *dest
, const char *src
, size_t maxlength
)
140 size_t src_len
, dest_len
;
143 DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
151 if (PTR_DIFF(&src_len
, dest
) > 0) { /* check if destination is on the stack, ok if so */
152 log_suspicious_usage("safe_strcat", src
);
155 src_len
= strlen(src
);
156 dest_len
= strlen(dest
);
158 if (src_len
+ dest_len
> maxlength
) {
159 DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
160 (int)(src_len
+ dest_len
- maxlength
), src
));
161 if (maxlength
> dest_len
) {
162 memcpy(&dest
[dest_len
], src
, maxlength
- dest_len
);
168 memcpy(&dest
[dest_len
], src
, src_len
);
169 dest
[dest_len
+ src_len
] = 0;
174 Routine to get hex characters and turn them into a 16 byte array.
175 the array can be variable length, and any non-hex-numeric
176 characters are skipped. "0xnn" or "0Xnn" is specially catered
179 valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
183 _PUBLIC_
size_t strhex_to_str(char *p
, size_t len
, const char *strhex
)
186 size_t num_chars
= 0;
187 uint8_t lonybble
, hinybble
;
188 const char *hexchars
= "0123456789ABCDEF";
189 char *p1
= NULL
, *p2
= NULL
;
191 for (i
= 0; i
< len
&& strhex
[i
] != 0; i
++) {
192 if (strncasecmp(hexchars
, "0x", 2) == 0) {
193 i
++; /* skip two chars */
197 if (!(p1
= strchr(hexchars
, toupper((unsigned char)strhex
[i
]))))
200 i
++; /* next hex digit */
202 if (!(p2
= strchr(hexchars
, toupper((unsigned char)strhex
[i
]))))
205 /* get the two nybbles */
206 hinybble
= PTR_DIFF(p1
, hexchars
);
207 lonybble
= PTR_DIFF(p2
, hexchars
);
209 p
[num_chars
] = (hinybble
<< 4) | lonybble
;
219 * Parse a hex string and return a data blob.
221 _PUBLIC_ DATA_BLOB
strhex_to_data_blob(const char *strhex
)
223 DATA_BLOB ret_blob
= data_blob(NULL
, strlen(strhex
)/2+1);
225 ret_blob
.length
= strhex_to_str((char *)ret_blob
.data
,
234 * Routine to print a buffer as HEX digits, into an allocated string.
236 _PUBLIC_
void hex_encode(const unsigned char *buff_in
, size_t len
, char **out_hex_buffer
)
241 *out_hex_buffer
= smb_xmalloc((len
*2)+1);
242 hex_buffer
= *out_hex_buffer
;
244 for (i
= 0; i
< len
; i
++)
245 slprintf(&hex_buffer
[i
*2], 3, "%02X", buff_in
[i
]);
249 Set a string value, allocing the space for the string
251 static BOOL
string_init(char **dest
,const char *src
)
255 (*dest
) = strdup(src
);
256 if ((*dest
) == NULL
) {
257 DEBUG(0,("Out of memory in string_init\n"));
266 _PUBLIC_
void string_free(char **s
)
268 if (s
) SAFE_FREE(*s
);
272 Set a string value, deallocating any existing space, and allocing the space
275 _PUBLIC_ BOOL
string_set(char **dest
, const char *src
)
278 return string_init(dest
,src
);
282 Substitute a string for a pattern in another string. Make sure there is
285 This routine looks for pattern in s and replaces it with
286 insert. It may do multiple replacements.
288 Any of " ; ' $ or ` in the insert string are replaced with _
289 if len==0 then the string cannot be extended. This is different from the old
290 use of len==0 which was for no length checks to be done.
293 _PUBLIC_
void string_sub(char *s
,const char *pattern
, const char *insert
, size_t len
)
298 if (!insert
|| !pattern
|| !*pattern
|| !s
)
301 ls
= (ssize_t
)strlen(s
);
302 lp
= (ssize_t
)strlen(pattern
);
303 li
= (ssize_t
)strlen(insert
);
306 len
= ls
+ 1; /* len is number of *bytes* */
308 while (lp
<= ls
&& (p
= strstr(s
,pattern
))) {
309 if (ls
+ (li
-lp
) >= len
) {
310 DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n",
311 (int)(ls
+ (li
-lp
) - len
),
316 memmove(p
+li
,p
+lp
,strlen(p
+lp
)+1);
341 Similar to string_sub() but allows for any character to be substituted.
343 if len==0 then the string cannot be extended. This is different from the old
344 use of len==0 which was for no length checks to be done.
347 _PUBLIC_
void all_string_sub(char *s
,const char *pattern
,const char *insert
, size_t len
)
352 if (!insert
|| !pattern
|| !s
)
355 ls
= (ssize_t
)strlen(s
);
356 lp
= (ssize_t
)strlen(pattern
);
357 li
= (ssize_t
)strlen(insert
);
363 len
= ls
+ 1; /* len is number of *bytes* */
365 while (lp
<= ls
&& (p
= strstr(s
,pattern
))) {
366 if (ls
+ (li
-lp
) >= len
) {
367 DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n",
368 (int)(ls
+ (li
-lp
) - len
),
373 memmove(p
+li
,p
+lp
,strlen(p
+lp
)+1);
375 memcpy(p
, insert
, li
);
384 Unescape a URL encoded string, in place.
387 _PUBLIC_
void rfc1738_unescape(char *buf
)
391 while ((p
=strchr(p
,'+')))
396 while (p
&& *p
&& (p
=strchr(p
,'%'))) {
400 if (c1
>= '0' && c1
<= '9')
402 else if (c1
>= 'A' && c1
<= 'F')
404 else if (c1
>= 'a' && c1
<= 'f')
406 else {p
++; continue;}
408 if (c2
>= '0' && c2
<= '9')
410 else if (c2
>= 'A' && c2
<= 'F')
412 else if (c2
>= 'a' && c2
<= 'f')
414 else {p
++; continue;}
418 memmove(p
+1, p
+3, strlen(p
+3)+1);
424 size_t valgrind_strlen(const char *s
)
427 for(count
= 0; *s
++; count
++)
435 format a string into length-prefixed dotted domain format, as used in NBT
436 and in some ADS structures
438 _PUBLIC_
const char *str_format_nbt_domain(TALLOC_CTX
*mem_ctx
, const char *s
)
443 return talloc_strdup(mem_ctx
, "");
445 ret
= talloc_size(mem_ctx
, strlen(s
)+2);
450 memcpy(ret
+1, s
, strlen(s
)+1);
453 for (i
=0;ret
[i
];i
++) {
455 char *p
= strchr(ret
+i
+1, '.');
457 ret
[i
] = p
-(ret
+i
+1);
459 ret
[i
] = strlen(ret
+i
+1);
468 * Add a string to an array of strings.
470 * num should be a pointer to an integer that holds the current
471 * number of elements in strings. It will be updated by this function.
473 _PUBLIC_ BOOL
add_string_to_array(TALLOC_CTX
*mem_ctx
,
474 const char *str
, const char ***strings
, int *num
)
476 char *dup_str
= talloc_strdup(mem_ctx
, str
);
478 *strings
= talloc_realloc(mem_ctx
,
480 const char *, ((*num
)+1));
482 if ((*strings
== NULL
) || (dup_str
== NULL
))
485 (*strings
)[*num
] = dup_str
;
494 varient of strcmp() that handles NULL ptrs
496 _PUBLIC_
int strcmp_safe(const char *s1
, const char *s2
)
501 if (s1
== NULL
|| s2
== NULL
) {
504 return strcmp(s1
, s2
);
509 return the number of bytes occupied by a buffer in ASCII format
510 the result includes the null termination
513 _PUBLIC_
size_t ascii_len_n(const char *src
, size_t n
)
517 len
= strnlen(src
, n
);
527 Return a string representing a CIFS attribute for a file.
529 _PUBLIC_
char *attrib_string(TALLOC_CTX
*mem_ctx
, uint32_t attrib
)
536 {'V', FILE_ATTRIBUTE_VOLUME
},
537 {'D', FILE_ATTRIBUTE_DIRECTORY
},
538 {'A', FILE_ATTRIBUTE_ARCHIVE
},
539 {'H', FILE_ATTRIBUTE_HIDDEN
},
540 {'S', FILE_ATTRIBUTE_SYSTEM
},
541 {'N', FILE_ATTRIBUTE_NORMAL
},
542 {'R', FILE_ATTRIBUTE_READONLY
},
543 {'d', FILE_ATTRIBUTE_DEVICE
},
544 {'t', FILE_ATTRIBUTE_TEMPORARY
},
545 {'s', FILE_ATTRIBUTE_SPARSE
},
546 {'r', FILE_ATTRIBUTE_REPARSE_POINT
},
547 {'c', FILE_ATTRIBUTE_COMPRESSED
},
548 {'o', FILE_ATTRIBUTE_OFFLINE
},
549 {'n', FILE_ATTRIBUTE_NONINDEXED
},
550 {'e', FILE_ATTRIBUTE_ENCRYPTED
}
554 ret
= talloc_size(mem_ctx
, ARRAY_SIZE(attr_strs
)+1);
559 for (len
=i
=0; i
<ARRAY_SIZE(attr_strs
); i
++) {
560 if (attrib
& attr_strs
[i
].attr
) {
561 ret
[len
++] = attr_strs
[i
].c
;
571 Set a boolean variable from the text value stored in the passed string.
572 Returns True in success, False if the passed string does not correctly
576 _PUBLIC_ BOOL
set_boolean(const char *boolean_string
, BOOL
*boolean
)
578 if (strwicmp(boolean_string
, "yes") == 0 ||
579 strwicmp(boolean_string
, "true") == 0 ||
580 strwicmp(boolean_string
, "on") == 0 ||
581 strwicmp(boolean_string
, "1") == 0) {
584 } else if (strwicmp(boolean_string
, "no") == 0 ||
585 strwicmp(boolean_string
, "false") == 0 ||
586 strwicmp(boolean_string
, "off") == 0 ||
587 strwicmp(boolean_string
, "0") == 0) {
595 * Parse a string containing a boolean value.
597 * val will be set to the read value.
599 * @retval True if a boolean value was parsed, False otherwise.
601 _PUBLIC_ BOOL
conv_str_bool(const char * str
, BOOL
* val
)
606 if (str
== NULL
|| *str
== '\0') {
610 lval
= strtol(str
, &end
, 10 /* base */);
611 if (end
== NULL
|| *end
!= '\0' || end
== str
) {
612 return set_boolean(str
, val
);
615 *val
= (lval
) ? True
: False
;
620 * Convert a size specification like 16K into an integral number of bytes.
622 _PUBLIC_ BOOL
conv_str_size(const char * str
, uint64_t * val
)
625 unsigned long long lval
;
627 if (str
== NULL
|| *str
== '\0') {
631 lval
= strtoull(str
, &end
, 10 /* base */);
632 if (end
== NULL
|| end
== str
) {
637 if (strwicmp(end
, "K") == 0) {
639 } else if (strwicmp(end
, "M") == 0) {
640 lval
*= (1024ULL * 1024ULL);
641 } else if (strwicmp(end
, "G") == 0) {
642 lval
*= (1024ULL * 1024ULL * 1024ULL);
643 } else if (strwicmp(end
, "T") == 0) {
644 lval
*= (1024ULL * 1024ULL * 1024ULL * 1024ULL);
645 } else if (strwicmp(end
, "P") == 0) {
646 lval
*= (1024ULL * 1024ULL * 1024ULL * 1024ULL * 1024ULL);
652 *val
= (uint64_t)lval
;
657 * Parse a uint64_t value from a string
659 * val will be set to the value read.
661 * @retval True if parsing was successful, False otherwise
663 _PUBLIC_ BOOL
conv_str_u64(const char * str
, uint64_t * val
)
666 unsigned long long lval
;
668 if (str
== NULL
|| *str
== '\0') {
672 lval
= strtoull(str
, &end
, 10 /* base */);
673 if (end
== NULL
|| *end
!= '\0' || end
== str
) {
677 *val
= (uint64_t)lval
;
682 return the number of bytes occupied by a buffer in CH_UTF16 format
683 the result includes the null termination
685 _PUBLIC_
size_t utf16_len(const void *buf
)
689 for (len
= 0; SVAL(buf
,len
); len
+= 2) ;
695 return the number of bytes occupied by a buffer in CH_UTF16 format
696 the result includes the null termination
699 _PUBLIC_
size_t utf16_len_n(const void *src
, size_t n
)
703 for (len
= 0; (len
+2 < n
) && SVAL(src
, len
); len
+= 2) ;
712 _PUBLIC_
size_t ucs2_align(const void *base_ptr
, const void *p
, int flags
)
714 if (flags
& (STR_NOALIGN
|STR_ASCII
))
716 return PTR_DIFF(p
, base_ptr
) & 1;
720 Do a case-insensitive, whitespace-ignoring string compare.
722 _PUBLIC_
int strwicmp(const char *psz1
, const char *psz2
)
724 /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
725 /* appropriate value. */
728 else if (psz1
== NULL
)
730 else if (psz2
== NULL
)
733 /* sync the strings on first non-whitespace */
735 while (isspace((int)*psz1
))
737 while (isspace((int)*psz2
))
739 if (toupper((unsigned char)*psz1
) != toupper((unsigned char)*psz2
)
746 return (*psz1
- *psz2
);
752 _PUBLIC_
void string_replace(char *s
, char oldc
, char newc
)
755 if (*s
== oldc
) *s
= newc
;
763 * @note The comparison is case-insensitive.
765 _PUBLIC_ BOOL
strequal(const char *s1
, const char *s2
)
772 return strcasecmp(s1
,s2
) == 0;