Tiny fixes to init_valid_table()
[samba.git] / source / lib / util_unistr.c
index c4569e102e38a87ebe66af06d25231982d420ddf..2949d7d795e8f76f975f1eb4074d41845dfa0743 100644 (file)
@@ -81,12 +81,15 @@ void load_case_tables(void)
        static int initialised;
        char *old_locale = NULL, *saved_locale = NULL;
        int i;
+       TALLOC_CTX *frame = NULL;
 
        if (initialised) {
                return;
        }
        initialised = 1;
 
+       frame = talloc_stackframe();
+
        upcase_table = (smb_ucs2_t *)map_file(data_path("upcase.dat"),
                                              0x20000);
        upcase_table_use_unmap = ( upcase_table != NULL );
@@ -147,6 +150,7 @@ void load_case_tables(void)
                SAFE_FREE(saved_locale);
        }
 #endif
+       TALLOC_FREE(frame);
 }
 
 /*
@@ -154,10 +158,10 @@ void load_case_tables(void)
   and mapped back to the same character in ucs2
 */
 
-int check_dos_char(smb_ucs2_t c)
+static int check_dos_char(smb_ucs2_t c)
 {
        lazy_initialize_conv();
-       
+
        /* Find the right byte, and right bit within the byte; return
         * 1 or 0 */
        return (doschar_table[(c & 0xffff) / 8] & (1 << (c & 7))) != 0;
@@ -186,7 +190,7 @@ static int check_dos_char_slowly(smb_ucs2_t c)
  * Fill out doschar table the hard way, by examining each character
  **/
 
-void init_doschar_table(void)
+static void init_doschar_table(void)
 {
        int i, j, byteval;
 
@@ -224,6 +228,8 @@ void init_valid_table(void)
        const char *allowed = ".!#$%&'()_-@^`~";
        uint8 *valid_file;
 
+       init_doschar_table();
+
        if (mapped_file) {
                /* Can't unmap files, so stick with what we have */
                return;
@@ -241,14 +247,14 @@ void init_valid_table(void)
         * It might need to be regenerated if the code page changed.
         * We know that we're not using a mapped file, so we can
         * free() the old one. */
-       if (valid_table) 
-               SAFE_FREE(valid_table);
+       SAFE_FREE(valid_table);
 
        /* use free rather than unmap */
        valid_table_use_unmap = False;
 
        DEBUG(2,("creating default valid table\n"));
        valid_table = (uint8 *)SMB_MALLOC(0x10000);
+       SMB_ASSERT(valid_table != NULL);
        for (i=0;i<128;i++) {
                valid_table[i] = isalnum(i) || strchr(allowed,i);
        }
@@ -315,6 +321,25 @@ int rpcstr_pull(char* dest, void *src, int dest_len, int src_len, int flags)
        return pull_ucs2(NULL, dest, src, dest_len, src_len, flags|STR_UNICODE|STR_NOALIGN);
 }
 
+/* Copy a string from little-endian or big-endian unicode source (depending
+ * on flags) to internal samba format destination. Allocates on talloc ctx.
+ */
+
+int rpcstr_pull_talloc(TALLOC_CTX *ctx,
+                       char **dest,
+                       void *src,
+                       int src_len,
+                       int flags)
+{
+       return pull_ucs2_base_talloc(ctx,
+                       NULL,
+                       dest,
+                       src,
+                       src_len,
+                       flags|STR_UNICODE|STR_NOALIGN);
+
+}
+
 /* Copy a string from a unistr2 source to internal samba format
    destination.  Use this instead of direct calls to rpcstr_pull() to avoid
    having to determine whether the source string is null terminated. */
@@ -329,26 +354,54 @@ int rpcstr_pull_unistr2_fstring(char *dest, UNISTR2 *src)
  * copy because I don't really know how pull_ucs2 and friends calculate the
  * target size. If this turns out to be a major bottleneck someone with deeper
  * multi-byte knowledge needs to revisit this.
+ * I just did (JRA :-). No longer uses copy.
  * My (VL) use is dsr_getdcname, which returns 6 strings, the alternative would
  * have been to manually talloc_strdup them in rpc_client/cli_netlogon.c.
  */
 
-char *rpcstr_pull_unistr2_talloc(TALLOC_CTX *mem_ctx, const UNISTR2 *src)
+char *rpcstr_pull_unistr2_talloc(TALLOC_CTX *ctx, const UNISTR2 *src)
 {
-       pstring tmp;
-       size_t result;
-
-       result = pull_ucs2(NULL, tmp, src->buffer, sizeof(tmp),
-                          src->uni_str_len * 2, 0);
-       if (result == (size_t)-1) {
+       char *dest = NULL;
+       size_t dest_len = convert_string_talloc(ctx,
+                               CH_UTF16LE,
+                               CH_UNIX,
+                               src->buffer,
+                               src->uni_str_len * 2,
+                               (void *)&dest,
+                               true);
+       if (dest_len == (size_t)-1) {
                return NULL;
        }
 
-       return talloc_strdup(mem_ctx, tmp);
+       /* Ensure we're returning a null terminated string. */
+       if (dest_len) {
+               /* Did we already process the terminating zero ? */
+               if (dest[dest_len-1] != 0) {
+                       size_t size = talloc_get_size(dest);
+                       /* Have we got space to append the '\0' ? */
+                       if (size <= dest_len) {
+                               /* No, realloc. */
+                               dest = TALLOC_REALLOC_ARRAY(ctx, dest, char,
+                                               dest_len+1);
+                               if (!dest) {
+                                       /* talloc fail. */
+                                       dest_len = (size_t)-1;
+                                       return NULL;
+                               }
+                       }
+                       /* Yay - space ! */
+                       dest[dest_len] = '\0';
+                       dest_len++;
+               }
+       } else if (dest) {
+               dest[0] = 0;
+       }
+
+       return dest;
 }
 
 /* Converts a string from internal samba format to unicode
- */ 
+ */
 
 int rpcstr_push(void *dest, const char *src, size_t dest_len, int flags)
 {
@@ -357,7 +410,7 @@ int rpcstr_push(void *dest, const char *src, size_t dest_len, int flags)
 
 /* Converts a string from internal samba format to unicode. Always terminates.
  * Actually just a wrapper round push_ucs2_talloc().
- */ 
+ */
 
 int rpcstr_push_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
 {
@@ -377,6 +430,7 @@ void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen)
        pull_ucs2(NULL, dest, str->buffer, maxlen, str->uni_str_len*2, STR_NOALIGN);
 }
 
+#if 0
 /*******************************************************************
  Convert a (little-endian) UNISTR3 structure to an ASCII string.
 ********************************************************************/
@@ -390,38 +444,53 @@ void unistr3_to_ascii(char *dest, const UNISTR3 *str, size_t maxlen)
        pull_ucs2(NULL, dest, str->str.buffer, maxlen, str->uni_str_len*2,
                  STR_NOALIGN);
 }
-       
-/*******************************************************************
- Give a static string for displaying a UNISTR2.
-********************************************************************/
-
-const char *unistr2_static(const UNISTR2 *str)
-{
-       static pstring ret;
-       unistr2_to_ascii(ret, str, sizeof(ret));
-       return ret;
-}
+#endif
 
 /*******************************************************************
  Duplicate a UNISTR2 string into a null terminated char*
  using a talloc context.
 ********************************************************************/
 
-char *unistr2_tdup(TALLOC_CTX *ctx, const UNISTR2 *str)
+char *unistr2_to_ascii_talloc(TALLOC_CTX *ctx, const UNISTR2 *str)
 {
-       char *s;
-       int maxlen = (str->uni_str_len+1)*4;
-       if (!str->buffer) {
+       char *s = NULL;
+
+       if (!str || !str->buffer) {
                return NULL;
        }
-       s = (char *)TALLOC(ctx, maxlen); /* convervative */
-       if (!s) {
+       if (pull_ucs2_base_talloc(ctx,
+                               NULL,
+                               &s,
+                               str->buffer,
+                               str->uni_str_len*2,
+                               STR_NOALIGN) == (size_t)-1) {
                return NULL;
        }
-       pull_ucs2(NULL, s, str->buffer, maxlen, str->uni_str_len*2, STR_NOALIGN);
        return s;
 }
 
+/*******************************************************************
+ Return a string for displaying a UNISTR2. Guarentees to return a
+ valid string - "" if nothing else.
+ Changed to use talloc_tos() under the covers.... JRA.
+********************************************************************/
+
+const char *unistr2_static(const UNISTR2 *str)
+{
+       char *dest = NULL;
+
+       if ((str == NULL) || (str->uni_str_len == 0)) {
+               return "";
+       }
+
+       dest = unistr2_to_ascii_talloc(talloc_tos(), str);
+       if (!dest) {
+               return "";
+       }
+
+       return dest;
+}
+
 /*******************************************************************
  Convert a wchar to upper case.
 ********************************************************************/
@@ -960,24 +1029,6 @@ smb_ucs2_t *strstr_wa(const smb_ucs2_t *s, const char *ins)
        return NULL;
 }
 
-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);
-}
-
 /*******************************************************************
  Returns the length in number of wide characters.
 ******************************************************************/