summaryrefslogtreecommitdiff
path: root/source3/lib
diff options
context:
space:
mode:
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/charcnv.c8
-rw-r--r--source3/lib/util.c68
-rw-r--r--source3/lib/util_str.c67
-rw-r--r--source3/lib/util_unistr.c205
4 files changed, 319 insertions, 29 deletions
diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c
index e55de729c2..ebf316d9dd 100644
--- a/source3/lib/charcnv.c
+++ b/source3/lib/charcnv.c
@@ -123,7 +123,13 @@ size_t convert_string(charset_t from, charset_t to,
{ case EINVAL: reason="Incomplete multibyte sequence"; break;
case E2BIG: reason="No more room";
DEBUG(0, ("Required %d, available %d\n",
- srclen, destlen));
+ srclen, destlen));
+ /* we are not sure we need srclen bytes,
+ may be more, may be less.
+ We only know we need more than destlen
+ bytes ---simo */
+
+
break;
case EILSEQ: reason="Illegal myltibyte sequence"; break;
}
diff --git a/source3/lib/util.c b/source3/lib/util.c
index c833707d62..e2a5fe10d0 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -418,6 +418,58 @@ void unix_clean_name(char *s)
trim_string(s,NULL,"/..");
}
+/*******************************************************************
+convert '\' to '/'
+reduce a file name, removing or reducing /../ , /./ , // elements.
+remove also any trailing . and /
+return a new allocated string.
+********************************************************************/
+smb_ucs2_t *unix_clean_path(const smb_ucs2_t *s)
+{
+ smb_ucs2_t *ns;
+ smb_ucs2_t *p, *r, *t;
+
+ DEBUG(3, ("unix_clean_name_w\n")); /* [%unicode]\n")); */
+
+ /* convert '\' to '/' */
+ ns = strdup_w(s);
+ if (!ns) return NULL;
+ unix_format_w(ns);
+
+ /* remove all double slashes */
+ p = ns;
+ ns = all_string_sub_wa(p, "//", "/");
+ SAFE_FREE(p);
+ if (!ns) return NULL;
+
+ /* remove any /./ */
+ p = ns;
+ ns = all_string_sub_wa(p, "/./", "/");
+ SAFE_FREE(p);
+ if (!ns) return NULL;
+
+ /* reduce any /../ */
+ t = ns;
+ while ((r = strstr_wa(t, "/..")) != NULL) {
+ t = &(r[3]);
+ if (*t == UCS2_CHAR('/') || *t == 0) {
+ *r = 0;
+ p = strrchr_w(ns, UCS2_CHAR('/'));
+ if (!p) p = ns;
+ memmove(p, t, (strlen_w(t) + 1) * sizeof(smb_ucs2_t));
+ t = p;
+ }
+ }
+
+ /* remove any trailing /. */
+ trim_string_wa(ns, NULL, "/.");
+
+ /* remove any leading and trailing / */
+ trim_string_wa(ns, "/", "/");
+
+ return ns;
+}
+
/****************************************************************************
make a dir struct
****************************************************************************/
@@ -1783,6 +1835,22 @@ BOOL ms_has_wild(char *s)
return False;
}
+BOOL ms_has_wild_w(const smb_ucs2_t *s)
+{
+ smb_ucs2_t c;
+ while ((c = *s++)) {
+ switch (c) {
+ case UCS2_CHAR('*'):
+ case UCS2_CHAR('?'):
+ case UCS2_CHAR('<'):
+ case UCS2_CHAR('>'):
+ case UCS2_CHAR('"'):
+ return True;
+ }
+ }
+ return False;
+}
+
/*******************************************************************
a wrapper that handles case sensitivity and the special handling
of the ".." name
diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c
index e97885ae05..dc9dbd8ed7 100644
--- a/source3/lib/util_str.c
+++ b/source3/lib/util_str.c
@@ -245,9 +245,7 @@ void string_replace(char *s,char oldc,char newc)
{
smb_ucs2_t *ptr;
push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
- for(ptr=tmpbuf;*ptr;ptr++) {
- if(*ptr==UCS2_CHAR(oldc)) *ptr = UCS2_CHAR(newc);
- }
+ string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc));
pull_ucs2(NULL, s, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE);
}
@@ -744,6 +742,65 @@ void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
}
/****************************************************************************
+similar to all_string_sub but for unicode strings.
+return a new allocate unicode string.
+len is the number of bytes, not chars
+ similar to string_sub() but allows for any character to be substituted.
+ Use with caution!
+ if len==0 then no length check is performed
+****************************************************************************/
+
+smb_ucs2_t *all_string_sub_w(smb_ucs2_t *s, const smb_ucs2_t *pattern,
+ const smb_ucs2_t *insert)
+{
+ smb_ucs2_t *r, *rp, *sp;
+ size_t ls, lp, li, lt;
+
+ if (!insert || !pattern || !*pattern || !s) return NULL;
+
+ ls = lt = (size_t)strlen_w(s) * sizeof(smb_ucs2_t);
+ lp = (size_t)strlen_w(pattern) * sizeof(smb_ucs2_t);
+ li = (size_t)strlen_w(insert) * sizeof(smb_ucs2_t);
+
+ if (li > lp) {
+ smb_ucs2_t *st = s;
+ int ld = li - lp;
+ while (sp = strstr_w(st, pattern)) {
+ st = sp + lp;
+ lt += ld;
+ }
+ }
+
+ r = rp = (smb_ucs2_t *)malloc((lt + 1)*(sizeof(smb_ucs2_t)));
+ if (!r) {
+ DEBUG(0, ("all_string_sub_w: out of memory!\n"));
+ return NULL;
+ }
+
+ while (sp = strstr_w(s, pattern)) {
+ memcpy(rp, s, sp - s);
+ rp += (sp - s);
+ memcpy(rp, insert, li);
+ s = sp + lp;
+ rp += li;
+ }
+ *rp = 0;
+
+ return r;
+}
+
+smb_ucs2_t *all_string_sub_wa(smb_ucs2_t *s, const char *pattern,
+ const char *insert)
+{
+ wpstring p, i;
+
+ if (!insert || !pattern || !s) return NULL;
+ push_ucs2(NULL, p, pattern, sizeof(wpstring) - 1, STR_TERMINATE);
+ push_ucs2(NULL, i, insert, sizeof(wpstring) - 1, STR_TERMINATE);
+ return all_string_sub_w(s, p, i);
+}
+
+/****************************************************************************
splits out the front and back at a separator.
****************************************************************************/
void split_at_last_component(char *path, char *front, char sep, char *back)
@@ -813,7 +870,7 @@ char *strchr_m(const char *s, char c)
smb_ucs2_t *p;
push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
- p = strchr_wa(ws, c);
+ p = strchr_w(ws, UCS2_CHAR(c));
if (!p) return NULL;
*p = 0;
pull_ucs2_pstring(s2, ws);
@@ -827,7 +884,7 @@ char *strrchr_m(const char *s, char c)
smb_ucs2_t *p;
push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
- p = strrchr_wa(ws, c);
+ p = strrchr_w(ws, UCS2_CHAR(c));
if (!p) return NULL;
*p = 0;
pull_ucs2_pstring(s2, ws);
diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c
index d0e2a119b8..287472ad65 100644
--- a/source3/lib/util_unistr.c
+++ b/source3/lib/util_unistr.c
@@ -242,6 +242,52 @@ smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
return NULL;
}
+smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c)
+{
+ const smb_ucs2_t *p = s;
+ int len = strlen_w(s);
+ if (len == 0) return NULL;
+ p += (len - 1);
+ do {
+ if (c == *p) return (smb_ucs2_t *)p;
+ } while (p-- != s);
+ return NULL;
+}
+
+/*******************************************************************
+wide strstr()
+********************************************************************/
+smb_ucs2_t *strstr_w(const smb_ucs2_t *s, const smb_ucs2_t *ins)
+{
+ smb_ucs2_t *r;
+ size_t slen, inslen;
+
+ if (!s || !*s || !ins || !*ins) return NULL;
+ slen = strlen_w(s);
+ inslen = strlen_w(ins);
+ r = (smb_ucs2_t *)s;
+ while (r = strchr_w(r, *ins)) {
+ if (strncmp_w(r, ins, inslen) == 0) return r;
+ r++;
+ }
+ return NULL;
+}
+
+smb_ucs2_t *strstr_wa(const smb_ucs2_t *s, const char *ins)
+{
+ smb_ucs2_t *r;
+ size_t slen, inslen;
+
+ if (!s || !*s || !ins || !*ins) return NULL;
+ slen = strlen_w(s);
+ inslen = strlen(ins);
+ r = (smb_ucs2_t *)s;
+ while (r = strchr_w(r, UCS2_CHAR(*ins))) {
+ if (strncmp_wa(r, ins, inslen) == 0) return r;
+ r++;
+ }
+ return NULL;
+}
/*******************************************************************
Convert a string to lower case.
@@ -280,6 +326,18 @@ BOOL strupper_w(smb_ucs2_t *s)
}
/*******************************************************************
+ convert a string to "normal" form
+********************************************************************/
+void strnorm_w(smb_ucs2_t *s)
+{
+ extern int case_default;
+ if (case_default == CASE_UPPER)
+ strupper_w(s);
+ else
+ strlower_w(s);
+}
+
+/*******************************************************************
case insensitive string comparison
********************************************************************/
int strcasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b)
@@ -288,23 +346,60 @@ int strcasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b)
return (tolower_w(*a) - tolower_w(*b));
}
+/*******************************************************************
+case insensitive string comparison, lenght limited
+********************************************************************/
+int strncasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len)
+{
+ size_t n = 0;
+ while ((n < len) && *b && (toupper_w(*a) == toupper_w(*b))) { a++; b++; n++; }
+ return (len - n)?(tolower_w(*a) - tolower_w(*b)):0;
+}
+
+/*******************************************************************
+ compare 2 strings
+********************************************************************/
+BOOL strequal_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
+{
+ if (s1 == s2) return(True);
+ if (!s1 || !s2) return(False);
+
+ return(strcasecmp_w(s1,s2)==0);
+}
+
+/*******************************************************************
+ compare 2 strings up to and including the nth char.
+ ******************************************************************/
+BOOL strnequal_w(const smb_ucs2_t *s1,const smb_ucs2_t *s2,size_t n)
+{
+ if (s1 == s2) return(True);
+ if (!s1 || !s2 || !n) return(False);
+
+ return(strncasecmp_w(s1,s2,n)==0);
+}
/*******************************************************************
duplicate string
********************************************************************/
smb_ucs2_t *strdup_w(const smb_ucs2_t *src)
{
+ return strndup_w(src, 0);
+}
+
+/* if len == 0 then duplicate the whole string */
+smb_ucs2_t *strndup_w(const smb_ucs2_t *src, size_t len)
+{
smb_ucs2_t *dest;
- uint32 len;
- len = strlen_w(src) + 1;
- dest = (smb_ucs2_t *)malloc(len*sizeof(smb_ucs2_t));
+ if (!len) len = strlen_w(src);
+ dest = (smb_ucs2_t *)malloc((len + 1) * sizeof(smb_ucs2_t));
if (!dest) {
DEBUG(0,("strdup_w: out of memory!\n"));
return NULL;
}
- memcpy(dest, src, len*sizeof(smb_ucs2_t));
+ memcpy(dest, src, len * sizeof(smb_ucs2_t));
+ dest[len] = 0;
return dest;
}
@@ -368,33 +463,33 @@ void pstrcpy_wa(smb_ucs2_t *dest, const char *src)
}
}
-int strcmp_wa(const smb_ucs2_t *a, const char *b)
+int strcmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b)
{
- while (*b && *a == UCS2_CHAR(*b)) { a++; b++; }
- return (*a - UCS2_CHAR(*b));
+ while (*b && *a == *b) { a++; b++; }
+ return (*a - *b);
+ /* warning: if *a != *b and both are not 0 we retrun a random
+ greater or lesser than 0 number not realted to which
+ string is longer */
}
+int strncmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b, size_t len)
+{
+ size_t n = 0;
+ while ((n < len) && *b && *a == *b) { a++; b++; n++;}
+ return (len - n)?(*a - *b):0;
+}
-
-smb_ucs2_t *strchr_wa(const smb_ucs2_t *s, char c)
+int strcmp_wa(const smb_ucs2_t *a, const char *b)
{
- while (*s != 0) {
- if (UCS2_CHAR(c) == *s) return (smb_ucs2_t *)s;
- s++;
- }
- return NULL;
+ while (*b && *a == UCS2_CHAR(*b)) { a++; b++; }
+ return (*a - UCS2_CHAR(*b));
}
-smb_ucs2_t *strrchr_wa(const smb_ucs2_t *s, char c)
+int strncmp_wa(const smb_ucs2_t *a, const char *b, size_t len)
{
- const smb_ucs2_t *p = s;
- int len = strlen_w(s);
- if (len == 0) return NULL;
- p += (len-1);
- do {
- if (UCS2_CHAR(c) == *p) return (smb_ucs2_t *)p;
- } while (p-- != s);
- return NULL;
+ size_t n = 0;
+ while ((n < len) && *b && *a == UCS2_CHAR(*b)) { a++; b++; n++;}
+ return (len - n)?(*a - UCS2_CHAR(*b)):0;
}
smb_ucs2_t *strpbrk_wa(const smb_ucs2_t *s, const char *p)
@@ -452,3 +547,67 @@ smb_ucs2_t *strncat_wa(smb_ucs2_t *dest, const char *src, const size_t max)
SAFE_FREE(ucs2_src);
return dest;
}
+
+/*******************************************************************
+replace any occurence of oldc with newc in unicode string
+********************************************************************/
+
+void string_replace_w(smb_ucs2_t *s, smb_ucs2_t oldc, smb_ucs2_t newc)
+{
+ for(;*s;s++) {
+ if(*s==oldc) *s=newc;
+ }
+}
+
+/*******************************************************************
+trim unicode string
+********************************************************************/
+
+BOOL trim_string_w(smb_ucs2_t *s, const smb_ucs2_t *front,
+ const smb_ucs2_t *back)
+{
+ BOOL ret = False;
+ size_t len, lw, front_len, flw, back_len, blw;
+
+ if (!s || !*s) return False;
+
+ len = strlen_w(s);
+
+ if (front && *front) {
+ front_len = strlen_w(front);
+ flw = front_len * sizeof(smb_ucs2_t);
+ lw = (len + 1) * sizeof(smb_ucs2_t);
+ while (len && strncmp_w(s, front, front_len) == 0) {
+ memcpy(s, s + flw, lw - flw);
+ len -= front_len;
+ lw -= flw;
+ ret = True;
+ }
+ }
+
+ if (back && *back) {
+ back_len = strlen_w(back);
+ blw = back_len * sizeof(smb_ucs2_t);
+ lw = len * sizeof(smb_ucs2_t);
+ while (len && strncmp_w(s + lw - blw, back, back_len) == 0) {
+ s[len - back_len] = 0;
+ len -= back_len;
+ lw -= blw;
+ ret = True;
+ }
+ }
+
+ return ret;
+}
+
+BOOL trim_string_wa(smb_ucs2_t *s, const char *front,
+ const char *back)
+{
+ wpstring f, b;
+
+ if (front) push_ucs2(NULL, f, front, sizeof(wpstring) - 1, STR_TERMINATE);
+ else *f = 0;
+ if (back) push_ucs2(NULL, b, back, sizeof(wpstring) - 1, STR_TERMINATE);
+ else *b = 0;
+ return trim_string_w(s, f, b);
+}