r1570: merging changes from 3.0.5
[tprouty/samba.git] / source / smbd / mangle_hash2.c
index bbc9020eabc78b04fa008fa63fecf012a194b82f..f68873687bdc277783d8e0a7cb6f2dba7d93736a 100644 (file)
@@ -53,7 +53,7 @@
 
 #include "includes.h"
 
-#if 0
+#if 1
 #define M_DEBUG(level, x) DEBUG(level, x)
 #else
 #define M_DEBUG(level, x)
@@ -201,23 +201,25 @@ static const char *cache_lookup(u32 hash)
    In this algorithm, mangled names use only pure ascii characters (no
    multi-byte) so we can avoid doing a UCS2 conversion 
  */
-static BOOL is_mangled_component(const char *name)
+static BOOL is_mangled_component(const char *name, size_t len)
 {
-       int len, i;
+       unsigned int i;
 
-       M_DEBUG(10,("is_mangled_component %s ?\n", name));
+       M_DEBUG(10,("is_mangled_component %s (len %u) ?\n", name, (unsigned int)len));
 
        /* check the length */
-       len = strlen(name);
-       if (len > 12 || len < 8) return False;
+       if (len > 12 || len < 8)
+               return False;
 
        /* the best distinguishing characteristic is the ~ */
-       if (name[6] != '~') return False;
+       if (name[6] != '~')
+               return False;
 
        /* check extension */
        if (len > 8) {
-               if (name[8] != '.') return False;
-               for (i=9; name[i]; i++) {
+               if (name[8] != '.')
+                       return False;
+               for (i=9; name[i] && i < len; i++) {
                        if (! FLAG_CHECK(name[i], FLAG_ASCII)) {
                                return False;
                        }
@@ -241,7 +243,7 @@ static BOOL is_mangled_component(const char *name)
                }
        }
 
-       M_DEBUG(10,("is_mangled %s -> yes\n", name));
+       M_DEBUG(10,("is_mangled_component %s (len %u) -> yes\n", name, (unsigned int)len));
 
        return True;
 }
@@ -267,16 +269,13 @@ static BOOL is_mangled(const char *name)
        M_DEBUG(10,("is_mangled %s ?\n", name));
 
        for (s=name; (p=strchr(s, '/')); s=p+1) {
-               char *component = strndup(s, PTR_DIFF(p, s));
-               if (is_mangled_component(component)) {
-                       free(component);
+               if (is_mangled_component(s, PTR_DIFF(p, s))) {
                        return True;
                }
-               free(component);
        }
        
        /* and the last part ... */
-       return is_mangled_component(s);
+       return is_mangled_component(s,strlen(s));
 }
 
 
@@ -305,7 +304,8 @@ static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards)
         the result we need in this case. Using strlen_m would not
         only be slower, it would be incorrect */
        len = strlen(name);
-       if (len > 12) return False;
+       if (len > 12)
+               return False;
 
        /* find the '.'. Note that once again we use the non-multibyte
            function */
@@ -325,7 +325,7 @@ static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards)
                prefix_len = PTR_DIFF(dot_p, name);
                suffix_len = len - (prefix_len+1);
 
-               if (prefix_len > 8 || suffix_len > 3) {
+               if (prefix_len > 8 || suffix_len > 3 || suffix_len == 0) {
                        return False;
                }
 
@@ -362,13 +362,11 @@ static void mangle_reset(void)
 /*
   try to find a 8.3 name in the cache, and if found then
   replace the string with the original long name. 
-
-  The filename must be able to hold at least sizeof(fstring) 
 */
-static BOOL check_cache(char *name)
+static BOOL check_cache(char *name, size_t maxlen)
 {
        u32 hash, multiplier;
-       int i;
+       unsigned int i;
        const char *prefix;
        char extension[4];
 
@@ -403,10 +401,10 @@ static BOOL check_cache(char *name)
 
        if (extension[0]) {
                M_DEBUG(10,("check_cache: %s -> %s.%s\n", name, prefix, extension));
-               slprintf(name, sizeof(fstring), "%s.%s", prefix, extension);
+               slprintf(name, maxlen, "%s.%s", prefix, extension);
        } else {
                M_DEBUG(10,("check_cache: %s -> %s\n", name, prefix));
-               fstrcpy(name, prefix);
+               safe_strcpy(name, prefix, maxlen);
        }
 
        return True;
@@ -427,7 +425,7 @@ static BOOL is_reserved_name(const char *name)
                for (i=0; reserved_names[i]; i++) {
                        int len = strlen(reserved_names[i]);
                        /* note that we match on COM1 as well as COM1.foo */
-                       if (strncasecmp(name, reserved_names[i], len) == 0 &&
+                       if (strnequal(name, reserved_names[i], len) &&
                            (name[len] == '.' || name[len] == 0)) {
                                return True;
                        }
@@ -449,6 +447,23 @@ static BOOL is_legal_name(const char *name)
        size_t numdots = 0;
 
        while (*name) {
+               if (((unsigned int)name[0]) > 128 && (name[1] != 0)) {
+                       /* Possible start of mb character. */
+                       char mbc[2];
+                       /*
+                        * Note that if CH_UNIX is utf8 a string may be 3
+                        * bytes, but this is ok as mb utf8 characters don't
+                        * contain embedded ascii bytes. We are really checking
+                        * for mb UNIX asian characters like Japanese (SJIS) here.
+                        * JRA.
+                        */
+                       if (convert_string(CH_UNIX, CH_UCS2, name, 2, mbc, 2, False) == 2) {
+                               /* Was a good mb string. */
+                               name += 2;
+                               continue;
+                       }
+               }
+
                if (FLAG_CHECK(name[0], FLAG_ILLEGAL)) {
                        return False;
                }
@@ -484,13 +499,13 @@ static BOOL is_legal_name(const char *name)
 
   the name parameter must be able to hold 13 bytes
 */
-static void name_map(char *name, BOOL need83, BOOL cache83)
+static void name_map(fstring name, BOOL need83, BOOL cache83, int default_case)
 {
        char *dot_p;
        char lead_chars[7];
        char extension[4];
-       int extension_length, i;
-       int prefix_len;
+       unsigned int extension_length, i;
+       unsigned int prefix_len;
        u32 hash, v;
        char new_name[13];