- the inactive core of the new mangling code that use tdb
authorSimo Sorce <idra@samba.org>
Tue, 25 Sep 2001 09:57:06 +0000 (09:57 +0000)
committerSimo Sorce <idra@samba.org>
Tue, 25 Sep 2001 09:57:06 +0000 (09:57 +0000)
- some more utils for unicode string manipulation
(This used to be commit 4ade36446e7dee1c3828d8c822f047c6e891a644)

source3/lib/util_unistr.c
source3/smbd/mangle.c

index d4c71ae13f9beff7bff41d1501c929c52e125b4c..8248ac073cc55bf16fb4eea739f79a9bb84145d3 100644 (file)
@@ -280,6 +280,67 @@ int strcasecmp_w(const smb_ucs2_t *a, const smb_ucs2_t *b)
 }
 
 
+/*******************************************************************
+duplicate string
+********************************************************************/
+smb_ucs2_t *strdup_w(const smb_ucs2_t *src)
+{
+       smb_ucs2_t *dest;
+       uint32 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+1)*sizeof(smb_ucs2_t));
+       
+       return dest;
+}
+
+/*******************************************************************
+copy a string with max len
+********************************************************************/
+
+smb_ucs2_t *strncpy_w(smb_ucs2_t *dest, const smb_ucs2_t *src, const size_t max)
+{
+       size_t len;
+       
+       if (!dest || !src) return NULL;
+       
+       for (len = 0; (src[len] != 0) && (len < max); len++)
+               dest[len] = src[len];
+       while (len < max)
+               dest[len++] = 0;
+       
+       return dest;
+}
+
+
+/*******************************************************************
+append a string of len bytes and add a terminator
+********************************************************************/
+
+smb_ucs2_t *strncat_w(smb_ucs2_t *dest, const smb_ucs2_t *src, const size_t max)
+{      
+       size_t start;
+       size_t len;     
+       
+       if (!dest || !src) return NULL;
+       
+       start = strlen_w(dest);
+       len = strlen_w(src);
+       if (len > max) len = max;
+
+       memcpy(&dest[start], src, len);                 
+       dest[start+len+1] = 0;
+       
+       return dest;
+}
+
+
 /*
   The *_wa() functions take a combination of 7 bit ascii
   and wide characters They are used so that you can use string
@@ -304,6 +365,8 @@ int strcmp_wa(const smb_ucs2_t *a, const char *b)
        return (*a - UCS2_CHAR(*b));
 }
 
+
+
 smb_ucs2_t *strchr_wa(const smb_ucs2_t *s, char c)
 {
        while (*s != 0) {
@@ -337,3 +400,47 @@ smb_ucs2_t *strpbrk_wa(const smb_ucs2_t *s, const char *p)
        return NULL;
 }
 
+
+/*******************************************************************
+copy a string with max len
+********************************************************************/
+
+smb_ucs2_t *strncpy_wa(smb_ucs2_t *dest, const char *src, const size_t max)
+{
+       smb_ucs2_t *ucs2_src;
+
+       if (!dest || !src) return NULL;
+       ucs2_src = (smb_ucs2_t *)malloc((strlen(src)+1)*sizeof(smb_ucs2_t));
+       if (!ucs2_src) {
+               DEBUG(0,("strncpy_wa: out of memory!\n"));
+               return NULL;
+       }
+       push_ucs2(NULL, ucs2_src, src, -1, STR_TERMINATE|STR_NOALIGN);
+       
+       strncpy_w(dest, ucs2_src, max);
+       SAFE_FREE(ucs2_src);
+       return dest;
+}
+
+
+/*******************************************************************
+append a string of len bytes and add a terminator
+********************************************************************/
+
+smb_ucs2_t *strncat_wa(smb_ucs2_t *dest, const char *src, const size_t max)
+{
+       smb_ucs2_t *ucs2_src;
+
+       if (!dest || !src) return NULL;
+       ucs2_src = (smb_ucs2_t *)malloc((strlen(src)+1)*sizeof(smb_ucs2_t));
+       if (!ucs2_src) {
+               DEBUG(0,("strncat_wa: out of memory!\n"));
+               return NULL;
+       }
+       push_ucs2(NULL, ucs2_src, src, -1, STR_TERMINATE|STR_NOALIGN);
+       
+       strncat_w(dest, ucs2_src, max);
+       SAFE_FREE(ucs2_src);
+       return dest;
+}
+
index 0e6689d9d25fb16ea11c7c1f5eb30d7c6fd4dda2..0de2188bcfdebc8db7de455ab74d8afe919f2f09 100644 (file)
@@ -965,3 +965,360 @@ BOOL name_map_mangle(char *OutName, BOOL need83, BOOL cache83, int snum)
        return(True);
 } /* name_map_mangle */
 
+
+
+
+
+#if 0
+
+#define MANGLE_TDB_VERSION             "20010830"
+#define MANGLE_TDB_FILE_NAME           "mangle.tdb"
+#define MANGLE_TDB_STORED_NAME         "B"
+#define MANGLED_PREFIX                 "MANGLED_"
+#define LONG_PREFIX                    "LONG_"
+
+struct mt_enum_info {
+       TDB_CONTEXT     *mangle_tdb;
+       TDB_DATA        key;
+};
+
+
+static struct mt_enum_info     global_mt_ent = {0, 0};
+
+static int POW10(unsigned int exp)
+{
+       int result = 1;
+       
+       while (exp) {
+               result *= 10;
+               exp--;
+       }
+  
+       return result;
+}
+
+static BOOL init_mangle_tdb(void)
+{
+       pstring tdbfile;
+       
+       if (global_mt_ent.mangle_tdb == 0)
+       {
+               slprintf(tdbfile, sizeof(tdbfile)-1, "%s/%s", lp_private_dir(), MANGLE_TDB_FILE_NAME);
+
+               /* Open tdb */
+               if (!(global_mt_ent.mangle_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR, 0600)))
+               {
+                       DEBUG(0, ("Unable to open Mangle TDB, trying create new!\n"));
+                       /* create a new one if it does not exist */
+                       if (!(global_mt_ent.mangle_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT | O_EXCL, 0600)))
+                       {
+                               DEBUG(0, ("Unable to create Mangle TDB (%s) !!!", tdbfile));
+                               return False;
+                       }
+               }
+       }
+
+       return True;
+}
+
+/* see push_ucs2 */
+int dos_to_ucs2(const void *base_ptr, void *dest, const char *src, int dest_len, int flags)
+{
+       int len=0;
+       int src_len = strlen(src);
+       pstring tmpbuf;
+
+       /* treat a pstring as "unlimited" length */
+       if (dest_len == -1) {
+               dest_len = sizeof(pstring);
+       }
+
+       if (flags & STR_UPPER) {
+               pstrcpy(tmpbuf, src);
+               strupper(tmpbuf);
+               src = tmpbuf;
+       }
+
+       if (flags & STR_TERMINATE) {
+               src_len++;
+       }
+
+       if (ucs2_align(base_ptr, dest, flags)) {
+               *(char *)dest = 0;
+               dest = (void *)((char *)dest + 1);
+               if (dest_len) dest_len--;
+               len++;
+       }
+
+       /* ucs2 is always a multiple of 2 bytes */
+       dest_len &= ~1;
+
+       len += convert_string(CH_DOS, CH_UCS2, src, src_len, dest, dest_len);
+       return len;
+}
+
+/* see pull_ucs2 */
+int ucs2_to_dos(const void *base_ptr, char *dest, const void *src, int dest_len, int src_len, int flags)
+{
+       int ret;
+
+       if (dest_len == -1) {
+               dest_len = sizeof(pstring);
+       }
+
+       if (ucs2_align(base_ptr, src, flags)) {
+               src = (const void *)((char *)src + 1);
+               if (src_len > 0) src_len--;
+       }
+
+       if (flags & STR_TERMINATE) src_len = strlen_w(src)*2+2;
+
+       /* ucs2 is always a multiple of 2 bytes */
+       src_len &= ~1;
+       
+       ret = convert_string(CH_UCS2, CH_DOS, src, src_len, dest, dest_len);
+       if (dest_len) dest[MIN(ret, dest_len-1)] = 0;
+
+       return src_len;
+}
+
+
+
+/* the unicode string will be ZERO terminated */
+static smb_ucs2_t *unicode_from_buffer (uint8 *buf, uint32 size)
+{
+       uint32 len = 0;
+       uint32 lfn_len;
+       smb_ucs2_t *long_file_name;
+       
+       len = tdb_unpack (buf, size, MANGLE_TDB_STORED_NAME,
+               &lfn_len, &long_file_name);
+
+       if (len == -1) return NULL;
+       else return long_file_name;
+}
+
+/* the unicode string MUST be ZERO terminated */
+static uint32 buffer_from_unicode (uint8 **buf, smb_ucs2_t *long_file_name)
+{
+       uint32 buflen;
+       uint32 len = 0;
+       uint32 lfn_len = strlen_w(long_file_name)*sizeof(smb_ucs2_t)+1;
+       
+       /* one time to get the size needed */
+       len = tdb_pack(NULL, 0,  MANGLE_TDB_STORED_NAME,
+               lfn_len, long_file_name);
+
+       /* malloc the space needed */
+       if ((*buf=(uint8*)malloc(len)) == NULL)
+       {
+               DEBUG(0,("buffer_from_longname: Unable to malloc() memory for buffer!\n"));
+               return (-1);
+       }
+       
+       /* now for the real call to tdb_pack() */
+       buflen = tdb_pack(*buf, 0,  MANGLE_TDB_STORED_NAME,
+               lfn_len, long_file_name);
+
+       /* check to make sure we got it correct */
+       if (buflen != len)
+       {
+               /* error */
+               free (*buf);
+               return (-1);
+       }
+
+       return (buflen);
+}
+
+/* mangled must contain only the file name, not a path.
+   and MUST be ZERO terminated */
+smb_ucs2_t *unmangle(const smb_ucs2_t *mangled)
+{
+       TDB_DATA data, key;
+       fstring keystr;
+       fstring mufname;
+       smb_ucs2_t *retstr;
+       smb_ucs2_t *temp;
+
+       if (strlen_w(mangled) > 12) return NULL;
+       if (!strchr_wa(mangled, '~')) return NULL;
+       if (!init_mangle_tdb()) return NULL;
+       
+       temp = strdup_w(mangled);
+       if (!temp)
+       {
+               DEBUG(0,("mangle: out of memory!\n"));
+               return NULL;
+       }
+       strupper_w(temp);
+       /* set search key */
+       pull_ucs2(NULL, mufname, temp, sizeof(mufname), 0, STR_TERMINATE);
+       SAFE_FREE(temp);
+       slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname);
+       key.dptr = keystr;
+       key.dsize = strlen (keystr) + 1;
+       
+       /* get the record */
+       data = tdb_fetch(global_mt_ent.mangle_tdb, key);
+       
+       if (!data.dptr) /* not found */
+       {
+               DEBUG(5,("unmangle: %s\n", tdb_errorstr(global_mt_ent.mangle_tdb)));
+               return NULL;
+       }
+       
+       if (!(retstr = unicode_from_buffer (data.dptr, data.dsize)))
+       {
+               DEBUG(0,("unmangle: bad buffer returned from database!\n"));
+               SAFE_FREE(data.dptr);
+               return NULL;
+       }
+
+       SAFE_FREE(data.dptr);
+       return retstr;
+}
+
+/* unmangled must contain only the file name, not a path.
+   and MUST be ZERO terminated */
+smb_ucs2_t *_mangle(const smb_ucs2_t *unmangled)
+{
+       TDB_DATA data, key;
+       pstring keystr;
+       pstring longname;
+       fstring mufname;
+       BOOL db_free = False;
+       smb_ucs2_t *mangled;
+       smb_ucs2_t *um;
+       smb_ucs2_t *ext = NULL;
+       smb_ucs2_t *p;
+       size_t b_len;
+       size_t e_len;
+       size_t um_len;
+       uint32 n, c;
+                       
+
+       /* TODO: if it is a path return a failure */
+                       
+       um = strdup_w(unmangled);
+       if (!um)
+       {
+               DEBUG(0,("mangle: out of memory!\n"));
+               goto error;
+       }
+       um_len = strlen_w(um);
+       if (p = strrchr_wa(um, '.'))
+       {
+               if ((um_len - ((p - um) / sizeof(smb_ucs2_t))) < 4) /* check extension */
+               {
+                       *p = UCS2_CHAR('\0');
+                       ext = p++;
+               }
+       }
+
+       /* test if the same is yet mangled */
+
+       /* set search key */
+       pull_ucs2(NULL, longname, um, sizeof(longname), 0, STR_TERMINATE);
+       slprintf(keystr, sizeof(keystr)-1, "%s%s", LONG_PREFIX, longname);
+       key.dptr = keystr;
+       key.dsize = strlen (keystr) + 1;
+       
+       /* get the record */
+       data = tdb_fetch (global_mt_ent.mangle_tdb, key);
+       if (!data.dptr) /* not found */
+       {
+               if (tdb_error(global_mt_ent.mangle_tdb) != TDB_ERR_NOEXIST)
+               {
+                       DEBUG(0, ("mangle: database retrieval error: %s\n",
+                                       tdb_errorstr(global_mt_ent.mangle_tdb)));
+                       goto error;
+               }
+       
+               /* if not find the first free possibile mangled name */
+               n = c = 1;
+               while (!db_free)
+               {
+                       uint32 pos;
+                       smb_ucs2_t temp[9];
+                       char num[7];
+               
+                       while ((int)POW10(n) <= c) n++;
+                       pos = 7 - n;
+                       if (pos == 0) goto error;
+
+                       strncpy_w(temp, um, pos);
+                       strupper_w(temp);
+                       temp[pos] = UCS2_CHAR('~');
+                       temp[pos+1] = 0;
+                       snprintf(num, 7, "%d", c);
+                       strncat_wa(temp, num, n);
+
+                       pull_ucs2(NULL, mufname, temp, sizeof(mufname), 0, STR_TERMINATE);
+                       if (strlen(mufname) > 8)
+                       {
+                               n++;
+                               continue;
+                       }
+
+                       slprintf(keystr, sizeof(keystr)-1, "%s%s", MANGLED_PREFIX, mufname);
+                       key.dptr = keystr;
+                       key.dsize = strlen (keystr) + 1;
+                       if ((data.dsize=buffer_from_unicode ((uint8 **)(&data.dptr), temp)) == -1)
+                       {
+                               DEBUG(0,("mangle: ERROR - Unable to copy mangled name info buffer!\n"));
+                               goto error;
+                       }
+
+                       if (tdb_store(global_mt_ent.mangle_tdb, key, data, TDB_INSERT) != TDB_SUCCESS)
+                       {
+                               SAFE_FREE(data.dptr);
+                               if (tdb_error(global_mt_ent.mangle_tdb) == TDB_ERR_EXISTS)
+                               {
+                                       continue;
+                               }
+                               else
+                               {
+                                       DEBUG(0, ("mangle: database retrieval error: %s\n",
+                                                       tdb_errorstr(global_mt_ent.mangle_tdb)));
+                                       goto error;
+                               }
+                       }
+                       else
+                       {
+                               db_free = True;
+                               p = strdup_w(temp);
+                       }
+                       c++;
+               }
+       }
+       else /* FOUND */
+       {
+               if (!(p = unicode_from_buffer (data.dptr, data.dsize)))
+               {
+                       DEBUG(0,("mangle: bad buffer returned from database!\n"));
+                       goto error;
+               }
+       }
+               
+       b_len = strlen_w(p);
+       if (ext) e_len = strlen_w(ext);
+       else e_len = 0;
+       mangled = (smb_ucs2_t *)malloc((b_len+e_len+2)*sizeof(smb_ucs2_t));
+       strncpy_w (mangled, p, b_len+1);
+       strncat_w (mangled, ext, e_len);
+
+       SAFE_FREE(p);
+       SAFE_FREE(um);
+       SAFE_FREE(data.dptr);
+
+       return mangled;
+
+error:
+       DEBUG(10, ("mangle: failed to mangle <string from unicode here>!\n"));
+       SAFE_FREE(data.dptr);
+       SAFE_FREE(um);
+       return NULL;
+}
+
+#endif /* 0 */