Copyright (C) Simo Sorce 2001-2002
Copyright (C) Martin Pool 2003
Copyright (C) James Peach 2006
+ Copyright (C) Jeremy Allison 1992-2007
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
return ret;
}
-static uint16 tmpbuf[sizeof(pstring)];
-
void set_first_token(char *ptr)
{
last_ptr = ptr;
/**
Case insensitive string compararison, length limited.
**/
-int StrnCaseCmp(const char *s, const char *t, size_t n)
+int StrnCaseCmp(const char *s, const char *t, size_t len)
{
- pstring buf1, buf2;
- unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1));
- unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2));
- return strncmp(buf1,buf2,n);
+ size_t n = 0;
+ const char *ps, *pt;
+ size_t size;
+ smb_ucs2_t *buffer_s, *buffer_t;
+ int ret;
+
+ for (ps = s, pt = t; n < len ; ps++, pt++, n++) {
+ char us, ut;
+
+ if (!*ps && !*pt)
+ return 0; /* both ended */
+ else if (!*ps)
+ return -1; /* s is a prefix */
+ else if (!*pt)
+ return +1; /* t is a prefix */
+ else if ((*ps & 0x80) || (*pt & 0x80))
+ /* not ascii anymore, do it the
+ * hard way from here on in */
+ break;
+
+ us = toupper_ascii(*ps);
+ ut = toupper_ascii(*pt);
+ if (us == ut)
+ continue;
+ else if (us < ut)
+ return -1;
+ else if (us > ut)
+ return +1;
+ }
+
+ if (n == len) {
+ return 0;
+ }
+
+ size = push_ucs2_allocate(&buffer_s, ps);
+ if (size == (size_t)-1) {
+ return strncmp(ps, pt, len-n);
+ /* Not quite the right answer, but finding the right one
+ under this failure case is expensive,
+ and it's pretty close */
+ }
+
+ size = push_ucs2_allocate(&buffer_t, pt);
+ if (size == (size_t)-1) {
+ SAFE_FREE(buffer_s);
+ return strncmp(ps, pt, len-n);
+ /* Not quite the right answer, but finding the right one
+ under this failure case is expensive,
+ and it's pretty close */
+ }
+
+ ret = strncasecmp_w(buffer_s, buffer_t, len-n);
+ SAFE_FREE(buffer_s);
+ SAFE_FREE(buffer_t);
+ return ret;
}
/**
return(True);
if (!s1 || !s2)
return(False);
-
+
return(StrCaseCmp(s1,s2)==0);
}
return(True);
if (!s1 || !s2 || !n)
return(False);
-
+
return(StrnCaseCmp(s1,s2,n)==0);
}
char *strupper_static(const char *s)
{
- static pstring str;
+ static char *str = NULL;
- pstrcpy(str, s);
+ if (str) {
+ SAFE_FREE(str);
+ }
+ str = SMB_STRDUP(s);
+ if (!str) {
+ return CONST_DISCARD(char *,s);
+ }
strupper_m(str);
-
return str;
}
{
if (case_default == CASE_UPPER)
return(!strhaslower(s));
-
+
return(!strhasupper(s));
}
String replace.
NOTE: oldc and newc must be 7 bit characters
**/
-
-void string_replace( pstring s, char oldc, char newc )
+void string_replace( char *s, char oldc, char newc )
{
char *p;
for (p = s; *p; p++) {
if (*p & 0x80) /* mb string - slow path. */
break;
- if (*p == oldc)
+ if (*p == oldc) {
*p = newc;
+ }
}
if (!*p)
/* With compose characters we must restart from the beginning. JRA. */
p = s;
#endif
- push_ucs2(NULL, tmpbuf, p, sizeof(tmpbuf), STR_TERMINATE);
- string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc));
- pull_ucs2(NULL, p, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE);
+
+ while (*p) {
+ size_t c_size;
+ next_codepoint(p, &c_size);
+
+ if (c_size == 1) {
+ if (*p == oldc) {
+ *p = newc;
+ }
+ }
+ p += c_size;
+ }
}
/**
* Skip past some strings in a buffer - old version - no checks.
* **/
-char *push_skip_string(char *buf,size_t n)
+char *push_skip_string(char *buf)
{
- while (n--)
- buf += strlen(buf) + 1;
+ buf += strlen(buf) + 1;
return(buf);
}
/**
- Skip past some strings in a buffer. Buffer may not be
+ Skip past a string in a buffer. Buffer may not be
null terminated. end_ptr points to the first byte after
then end of the buffer.
**/
-char *skip_string(const char *base, size_t len, char *buf, size_t n)
+char *skip_string(const char *base, size_t len, char *buf)
{
const char *end_ptr = base + len;
return NULL;
}
- while (n--) {
- /* Skip the string */
- while (*buf) {
- buf++;
- if (buf >= end_ptr) {
- return NULL;
- }
- }
- /* Skip the '\0' */
+ /* Skip the string */
+ while (*buf) {
buf++;
+ if (buf >= end_ptr) {
+ return NULL;
+ }
}
-
+ /* Skip the '\0' */
+ buf++;
return buf;
}
size_t str_charnum(const char *s)
{
- uint16 tmpbuf2[sizeof(pstring)];
- push_ucs2(NULL, tmpbuf2,s, sizeof(tmpbuf2), STR_TERMINATE);
- return strlen_w(tmpbuf2);
+ size_t ret;
+ smb_ucs2_t *tmpbuf2 = NULL;
+ if (push_ucs2_allocate(&tmpbuf2, s) == (size_t)-1) {
+ return 0;
+ }
+ ret = strlen_w(tmpbuf2);
+ SAFE_FREE(tmpbuf2);
+ return ret;
}
/**
size_t str_ascii_charnum(const char *s)
{
- pstring tmpbuf2;
- push_ascii(tmpbuf2, s, sizeof(tmpbuf2), STR_TERMINATE);
- return strlen(tmpbuf2);
+ size_t ret;
+ char *tmpbuf2 = NULL;
+ if (push_ascii_allocate(&tmpbuf2, s) == (size_t)-1) {
+ return 0;
+ }
+ ret = strlen(tmpbuf2);
+ SAFE_FREE(tmpbuf2);
+ return ret;
}
BOOL trim_char(char *s,char cfront,char cback)
BOOL strhasupper(const char *s)
{
- smb_ucs2_t *ptr;
- push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
- for(ptr=tmpbuf;*ptr;ptr++)
- if(isupper_w(*ptr))
- return True;
- return(False);
+ smb_ucs2_t *tmp, *p;
+ BOOL ret;
+
+ if (push_ucs2_allocate(&tmp, s) == -1) {
+ return False;
+ }
+
+ for(p = tmp; *p != 0; p++) {
+ if(isupper_w(*p)) {
+ break;
+ }
+ }
+
+ ret = (*p != 0);
+ SAFE_FREE(tmp);
+ return ret;
}
/**
BOOL strhaslower(const char *s)
{
- smb_ucs2_t *ptr;
- push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
- for(ptr=tmpbuf;*ptr;ptr++)
- if(islower_w(*ptr))
- return True;
- return(False);
+ smb_ucs2_t *tmp, *p;
+ BOOL ret;
+
+ if (push_ucs2_allocate(&tmp, s) == -1) {
+ return False;
+ }
+
+ for(p = tmp; *p != 0; p++) {
+ if(islower_w(*p)) {
+ break;
+ }
+ }
+
+ ret = (*p != 0);
+ SAFE_FREE(tmp);
+ return ret;
}
/**
BOOL in_list(const char *s, const char *list, BOOL casesensitive)
{
- pstring tok;
+ char *tok;
const char *p=list;
+ size_t bufsize = strlen(list);
+ BOOL ret = False;
if (!list)
return(False);
- while (next_token(&p,tok,LIST_SEP,sizeof(tok))) {
+ /* We know a token can't be larger
+ * than the entire list. */
+
+ tok = SMB_MALLOC_ARRAY(char, bufsize+1);
+ if (!tok) {
+ return False;
+ }
+
+ while (next_token(&p,tok,LIST_SEP,bufsize+1)) {
if (casesensitive) {
- if (strcmp(tok,s) == 0)
- return(True);
+ if (strcmp(tok,s) == 0) {
+ ret = True;
+ break;
+ }
} else {
- if (StrCaseCmp(tok,s) == 0)
- return(True);
+ if (StrCaseCmp(tok,s) == 0) {
+ ret = True;
+ break;
+ }
}
}
- return(False);
+
+ SAFE_FREE(tok);
+ return ret;
}
/* this is used to prevent lots of mallocs of size 1 */
char *strchr_m(const char *src, char c)
{
- wpstring ws;
- pstring s2;
+ smb_ucs2_t *ws = NULL;
+ char *s2 = NULL;
smb_ucs2_t *p;
const char *s;
+ char *ret;
/* characters below 0x3F are guaranteed to not appear in
non-initial position in multi-byte charsets */
s = src;
#endif
- push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
+ if (push_ucs2_allocate(&ws, s)==(size_t)-1) {
+ /* Wrong answer, but what can we do... */
+ return strchr(src, c);
+ }
p = strchr_w(ws, UCS2_CHAR(c));
- if (!p)
+ if (!p) {
+ SAFE_FREE(ws);
return NULL;
+ }
*p = 0;
- pull_ucs2_pstring(s2, ws);
- return (char *)(s+strlen(s2));
+ if (pull_ucs2_allocate(&s2, ws)==(size_t)-1) {
+ SAFE_FREE(ws);
+ /* Wrong answer, but what can we do... */
+ return strchr(src, c);
+ }
+ ret = (char *)(s+strlen(s2));
+ SAFE_FREE(ws);
+ SAFE_FREE(s2);
+ return ret;
}
char *strrchr_m(const char *s, char c)
/* String contained a non-ascii char. Slow path. */
{
- wpstring ws;
- pstring s2;
+ smb_ucs2_t *ws = NULL;
+ char *s2 = NULL;
smb_ucs2_t *p;
+ char *ret;
- push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
+ if (push_ucs2_allocate(&ws,s)==(size_t)-1) {
+ /* Wrong answer, but what can we do. */
+ return strrchr(s, c);
+ }
p = strrchr_w(ws, UCS2_CHAR(c));
- if (!p)
+ if (!p) {
+ SAFE_FREE(ws);
return NULL;
+ }
*p = 0;
- pull_ucs2_pstring(s2, ws);
- return (char *)(s+strlen(s2));
+ if (pull_ucs2_allocate(&s2,ws)==(size_t)-1) {
+ SAFE_FREE(ws);
+ /* Wrong answer, but what can we do. */
+ return strrchr(s, c);
+ }
+ ret = (char *)(s+strlen(s2));
+ SAFE_FREE(ws);
+ SAFE_FREE(s2);
+ return ret;
}
}
char *strnrchr_m(const char *s, char c, unsigned int n)
{
- wpstring ws;
- pstring s2;
+ smb_ucs2_t *ws = NULL;
+ char *s2 = NULL;
smb_ucs2_t *p;
+ char *ret;
- push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
+ if (push_ucs2_allocate(&ws,s)==(size_t)-1) {
+ /* Too hard to try and get right. */
+ return NULL;
+ }
p = strnrchr_w(ws, UCS2_CHAR(c), n);
- if (!p)
+ if (!p) {
+ SAFE_FREE(ws);
return NULL;
+ }
*p = 0;
- pull_ucs2_pstring(s2, ws);
- return (char *)(s+strlen(s2));
+ if (pull_ucs2_allocate(&s2,ws)==(size_t)-1) {
+ SAFE_FREE(ws);
+ /* Too hard to try and get right. */
+ return NULL;
+ }
+ ret = (char *)(s+strlen(s2));
+ SAFE_FREE(ws);
+ SAFE_FREE(s2);
+ return ret;
}
/***********************************************************************
char *s;
int num, lsize;
pstring tok;
-
+
if (!string || !*string)
return NULL;
if (mem_ctx) {
return NULL;
}
if (!sep) sep = LIST_SEP;
-
+
num = lsize = 0;
list = NULL;
-
+
str = s;
- while (next_token(&str, tok, sep, sizeof(tok))) {
+ while (next_token(&str, tok, sep, sizeof(tok))) {
if (num == lsize) {
lsize += S_LIST_ABS;
if (mem_ctx) {
} else {
list[num] = SMB_STRDUP(tok);
}
-
+
if (!list[num]) {
DEBUG(0,("str_list_make: Unable to allocate memory"));
str_list_free(&list);
return len;
}
+
+/*******************************************************************
+ Add a shell escape character '\' to any character not in a known list
+ of characters. UNIX charset format.
+*******************************************************************/
+
+#define INCLUDE_LIST "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_/ \t.,"
+#define INSIDE_DQUOTE_LIST "$`\n\"\\"
+
+char *escape_shell_string(const char *src)
+{
+ size_t srclen = strlen(src);
+ char *ret = SMB_MALLOC_ARRAY(char, (srclen * 2) + 1);
+ char *dest = ret;
+ BOOL in_s_quote = False;
+ BOOL in_d_quote = False;
+ BOOL next_escaped = False;
+
+ if (!ret) {
+ return NULL;
+ }
+
+ while (*src) {
+ size_t c_size;
+ codepoint_t c = next_codepoint(src, &c_size);
+
+ if (c == INVALID_CODEPOINT) {
+ SAFE_FREE(ret);
+ return NULL;
+ }
+
+ if (c_size > 1) {
+ memcpy(dest, src, c_size);
+ src += c_size;
+ dest += c_size;
+ next_escaped = False;
+ continue;
+ }
+
+ /*
+ * Deal with backslash escaped state.
+ * This only lasts for one character.
+ */
+
+ if (next_escaped) {
+ *dest++ = *src++;
+ next_escaped = False;
+ continue;
+ }
+
+ /*
+ * Deal with single quote state. The
+ * only thing we care about is exiting
+ * this state.
+ */
+
+ if (in_s_quote) {
+ if (*src == '\'') {
+ in_s_quote = False;
+ }
+ *dest++ = *src++;
+ continue;
+ }
+
+ /*
+ * Deal with double quote state. The most
+ * complex state. We must cope with \, meaning
+ * possibly escape next char (depending what it
+ * is), ", meaning exit this state, and possibly
+ * add an \ escape to any unprotected character
+ * (listed in INSIDE_DQUOTE_LIST).
+ */
+
+ if (in_d_quote) {
+ if (*src == '\\') {
+ /*
+ * Next character might be escaped.
+ * We have to peek. Inside double
+ * quotes only INSIDE_DQUOTE_LIST
+ * characters are escaped by a \.
+ */
+
+ char nextchar;
+
+ c = next_codepoint(&src[1], &c_size);
+ if (c == INVALID_CODEPOINT) {
+ SAFE_FREE(ret);
+ return NULL;
+ }
+ if (c_size > 1) {
+ /*
+ * Don't escape the next char.
+ * Just copy the \.
+ */
+ *dest++ = *src++;
+ continue;
+ }
+
+ nextchar = src[1];
+
+ if (nextchar && strchr(INSIDE_DQUOTE_LIST, (int)nextchar)) {
+ next_escaped = True;
+ }
+ *dest++ = *src++;
+ continue;
+ }
+
+ if (*src == '\"') {
+ /* Exit double quote state. */
+ in_d_quote = False;
+ *dest++ = *src++;
+ continue;
+ }
+
+ /*
+ * We know the character isn't \ or ",
+ * so escape it if it's any of the other
+ * possible unprotected characters.
+ */
+
+ if (strchr(INSIDE_DQUOTE_LIST, (int)*src)) {
+ *dest++ = '\\';
+ }
+ *dest++ = *src++;
+ continue;
+ }
+
+ /*
+ * From here to the end of the loop we're
+ * not in the single or double quote state.
+ */
+
+ if (*src == '\\') {
+ /* Next character must be escaped. */
+ next_escaped = True;
+ *dest++ = *src++;
+ continue;
+ }
+
+ if (*src == '\'') {
+ /* Go into single quote state. */
+ in_s_quote = True;
+ *dest++ = *src++;
+ continue;
+ }
+
+ if (*src == '\"') {
+ /* Go into double quote state. */
+ in_d_quote = True;
+ *dest++ = *src++;
+ continue;
+ }
+
+ /* Check if we need to escape the character. */
+
+ if (!strchr(INCLUDE_LIST, (int)*src)) {
+ *dest++ = '\\';
+ }
+ *dest++ = *src++;
+ }
+ *dest++ = '\0';
+ return ret;
+}