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"
static smb_ucs2_t *upcase_table;
static smb_ucs2_t *lowcase_table;
static uint8 *valid_table;
+static bool upcase_table_use_unmap;
+static bool lowcase_table_use_unmap;
+static bool valid_table_use_unmap;
/**
* This table says which Unicode characters are valid dos
**/
static uint8 doschar_table[8192]; /* 65536 characters / 8 bits/byte */
+/**
+ * Destroy global objects allocated by load_case_tables()
+ **/
+void gfree_case_tables(void)
+{
+ if ( upcase_table ) {
+ if ( upcase_table_use_unmap )
+ unmap_file(upcase_table, 0x20000);
+ else
+ SAFE_FREE(upcase_table);
+ }
+
+ if ( lowcase_table ) {
+ if ( lowcase_table_use_unmap )
+ unmap_file(lowcase_table, 0x20000);
+ else
+ SAFE_FREE(lowcase_table);
+ }
+
+ if ( valid_table ) {
+ if ( valid_table_use_unmap )
+ unmap_file(valid_table, 0x10000);
+ else
+ SAFE_FREE(valid_table);
+ }
+}
/**
* Load or generate the case handling tables.
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;
- upcase_table = map_file(lib_path("upcase.dat"), 0x20000);
- lowcase_table = map_file(lib_path("lowcase.dat"), 0x20000);
+ frame = talloc_stackframe();
+
+ upcase_table = (smb_ucs2_t *)map_file(data_path("upcase.dat"),
+ 0x20000);
+ upcase_table_use_unmap = ( upcase_table != NULL );
+
+ lowcase_table = (smb_ucs2_t *)map_file(data_path("lowcase.dat"),
+ 0x20000);
+ lowcase_table_use_unmap = ( lowcase_table != NULL );
+
+#ifdef HAVE_SETLOCALE
+ /* Get the name of the current locale. */
+ old_locale = setlocale(LC_ALL, NULL);
+
+ if (old_locale) {
+ /* Save it as it is in static storage. */
+ saved_locale = SMB_STRDUP(old_locale);
+ }
+
+ /* We set back the locale to C to get ASCII-compatible toupper/lower functions. */
+ setlocale(LC_ALL, "C");
+#endif
/* we would like Samba to limp along even if these tables are
not available */
if (!upcase_table) {
DEBUG(1,("creating lame upcase table\n"));
- upcase_table = SMB_MALLOC(0x20000);
+ upcase_table = (smb_ucs2_t *)SMB_MALLOC(0x20000);
for (i=0;i<0x10000;i++) {
smb_ucs2_t v;
SSVAL(&v, 0, i);
if (!lowcase_table) {
DEBUG(1,("creating lame lowcase table\n"));
- lowcase_table = SMB_MALLOC(0x20000);
+ lowcase_table = (smb_ucs2_t *)SMB_MALLOC(0x20000);
for (i=0;i<0x10000;i++) {
smb_ucs2_t v;
SSVAL(&v, 0, i);
lowcase_table[v] = UCS2_CHAR(isupper(i)?tolower(i):i);
}
}
+
+#ifdef HAVE_SETLOCALE
+ /* Restore the old locale. */
+ if (saved_locale) {
+ setlocale (LC_ALL, saved_locale);
+ SAFE_FREE(saved_locale);
+ }
+#endif
+ TALLOC_FREE(frame);
}
/*
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;
smb_ucs2_t c2 = 0;
int len1, len2;
- len1 = convert_string(CH_UCS2, CH_DOS, &c, 2, buf, sizeof(buf),False);
+ len1 = convert_string(CH_UTF16LE, CH_DOS, &c, 2, buf, sizeof(buf),False);
if (len1 == 0) {
return 0;
}
- len2 = convert_string(CH_DOS, CH_UCS2, buf, len1, &c2, 2,False);
+ len2 = convert_string(CH_DOS, CH_UTF16LE, buf, len1, &c2, 2,False);
if (len2 != 2) {
return 0;
}
* 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;
const char *allowed = ".!#$%&'()_-@^`~";
uint8 *valid_file;
+ init_doschar_table();
+
if (mapped_file) {
/* Can't unmap files, so stick with what we have */
return;
}
- valid_file = map_file(lib_path("valid.dat"), 0x10000);
+ valid_file = (uint8 *)map_file(data_path("valid.dat"), 0x10000);
if (valid_file) {
valid_table = valid_file;
mapped_file = 1;
+ valid_table_use_unmap = True;
return;
}
* 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) 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 = SMB_MALLOC(0x10000);
+ 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);
}
null termination if applied
********************************************************************/
-size_t dos_PutUniCode(char *dst,const char *src, ssize_t len, BOOL null_terminate)
+size_t dos_PutUniCode(char *dst,const char *src, size_t len, bool null_terminate)
{
- return push_ucs2(NULL, dst, src, len,
- STR_UNICODE|STR_NOALIGN | (null_terminate?STR_TERMINATE:0));
+ int flags = null_terminate ? STR_UNICODE|STR_NOALIGN|STR_TERMINATE
+ : STR_UNICODE|STR_NOALIGN;
+ return push_ucs2(NULL, dst, src, len, 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. */
src->uni_str_len * 2, 0);
}
+/* Helper function to return a talloc'ed string. I have implemented it with a
+ * 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 *ctx, const UNISTR2 *src)
+{
+ 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;
+ }
+
+ /* 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, int dest_len, int flags)
+int rpcstr_push(void *dest, const char *src, size_t dest_len, int flags)
{
return push_ucs2(NULL, dest, src, dest_len, flags|STR_UNICODE|STR_NOALIGN);
}
+/* 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)
+{
+ return push_ucs2_talloc(ctx, dest, src);
+}
+
/*******************************************************************
Convert a (little-endian) UNISTR2 structure to an ASCII string.
********************************************************************/
void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen)
{
- if (str == NULL) {
+ if ((str == NULL) || (str->uni_str_len == 0)) {
*dest='\0';
return;
}
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.
********************************************************************/
void unistr3_to_ascii(char *dest, const UNISTR3 *str, size_t maxlen)
{
- if (str == NULL) {
+ if ((str == NULL) || (str->uni_str_len == 0)) {
*dest='\0';
return;
}
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.
********************************************************************/
Determine if a character is lowercase.
********************************************************************/
-BOOL islower_w(smb_ucs2_t c)
+bool islower_w(smb_ucs2_t c)
{
return upcase_table[SVAL(&c,0)] != c;
}
Determine if a character is uppercase.
********************************************************************/
-BOOL isupper_w(smb_ucs2_t c)
+bool isupper_w(smb_ucs2_t c)
{
return lowcase_table[SVAL(&c,0)] != c;
}
Determine if a character is valid in a 8.3 name.
********************************************************************/
-BOOL isvalid83_w(smb_ucs2_t c)
+bool isvalid83_w(smb_ucs2_t c)
{
return valid_table[SVAL(&c,0)] != 0;
}
size_t len;
smb_ucs2_t c;
- for(len = 0; *(COPY_UCS2_CHAR(&c,src)) && (len < max); src++, len++) {
+ for(len = 0; (len < max) && *(COPY_UCS2_CHAR(&c,src)); src++, len++) {
;
}
return True if any char is converted
********************************************************************/
-BOOL strlower_w(smb_ucs2_t *s)
+bool strlower_w(smb_ucs2_t *s)
{
smb_ucs2_t cp;
- BOOL ret = False;
+ bool ret = False;
while (*(COPY_UCS2_CHAR(&cp,s))) {
smb_ucs2_t v = tolower_w(cp);
return True if any char is converted
********************************************************************/
-BOOL strupper_w(smb_ucs2_t *s)
+bool strupper_w(smb_ucs2_t *s)
{
smb_ucs2_t cp;
- BOOL ret = False;
+ bool ret = False;
while (*(COPY_UCS2_CHAR(&cp,s))) {
smb_ucs2_t v = toupper_w(cp);
if (v != cp) {
Compare 2 strings.
********************************************************************/
-BOOL strequal_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
+bool strequal_w(const smb_ucs2_t *s1, const smb_ucs2_t *s2)
{
if (s1 == s2) {
return(True);
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)
+bool strnequal_w(const smb_ucs2_t *s1,const smb_ucs2_t *s2,size_t n)
{
if (s1 == s2) {
return(True);
Trim unicode string.
********************************************************************/
-BOOL trim_string_w(smb_ucs2_t *s, const smb_ucs2_t *front,
+bool trim_string_w(smb_ucs2_t *s, const smb_ucs2_t *front,
const smb_ucs2_t *back)
{
- BOOL ret = False;
+ bool ret = False;
size_t len, front_len, back_len;
if (!s) {
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.
******************************************************************/
return dst;
}
+
+/*************************************************************
+ ascii only toupper - saves the need for smbd to be in C locale.
+*************************************************************/
+
+int toupper_ascii(int c)
+{
+ smb_ucs2_t uc = toupper_w(UCS2_CHAR(c));
+ return UCS2_TO_CHAR(uc);
+}
+
+/*************************************************************
+ ascii only tolower - saves the need for smbd to be in C locale.
+*************************************************************/
+
+int tolower_ascii(int c)
+{
+ smb_ucs2_t uc = tolower_w(UCS2_CHAR(c));
+ return UCS2_TO_CHAR(uc);
+}
+
+/*************************************************************
+ ascii only isupper - saves the need for smbd to be in C locale.
+*************************************************************/
+
+int isupper_ascii(int c)
+{
+ return isupper_w(UCS2_CHAR(c));
+}
+
+/*************************************************************
+ ascii only islower - saves the need for smbd to be in C locale.
+*************************************************************/
+
+int islower_ascii(int c)
+{
+ return islower_w(UCS2_CHAR(c));
+}