summaryrefslogtreecommitdiffstats
path: root/source/smbd/mangle_hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/smbd/mangle_hash.c')
-rw-r--r--source/smbd/mangle_hash.c935
1 files changed, 518 insertions, 417 deletions
diff --git a/source/smbd/mangle_hash.c b/source/smbd/mangle_hash.c
index 0446a953ff5..7fef891f633 100644
--- a/source/smbd/mangle_hash.c
+++ b/source/smbd/mangle_hash.c
@@ -1,9 +1,8 @@
/*
- Unix SMB/CIFS implementation.
+ Unix SMB/Netbios implementation.
+ Version 1.9.
Name mangling
- Copyright (C) Andrew Tridgell 1992-2002
- Copyright (C) Simo Sorce 2001
- Copyright (C) Andrew Bartlett 2002
+ Copyright (C) Andrew Tridgell 1992-1998
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
@@ -20,16 +19,15 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
/* -------------------------------------------------------------------------- **
* Notable problems...
*
* March/April 1998 CRH
* - Many of the functions in this module overwrite string buffers passed to
* them. This causes a variety of problems and is, generally speaking,
- * dangerous and scarry. See the kludge notes in name_map()
+ * dangerous and scarry. See the kludge notes in name_map_mangle()
* below.
- * - It seems that something is calling name_map() twice. The
+ * - It seems that something is calling name_map_mangle() twice. The
* first call is probably some sort of test. Names which contain
* illegal characters are being doubly mangled. I'm not sure, but
* I'm guessing the problem is in server.c.
@@ -86,11 +84,11 @@ extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */
*
* isbasecahr() - Given a character, check the chartest array to see
* if that character is in the basechars set. This is
- * faster than using strchr_m().
+ * faster than using strchr().
*
* isillegal() - Given a character, check the chartest array to see
* if that character is in the illegal characters set.
- * This is faster than using strchr_m().
+ * This is faster than using strchr().
*
* mangled_cache - Cache header used for storing mangled -> original
* reverse maps.
@@ -128,252 +126,158 @@ static BOOL ct_initialized = False;
static ubi_cacheRoot mangled_cache[1] = { { { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0 } };
static BOOL mc_initialized = False;
#define MANGLED_CACHE_MAX_ENTRIES 1024
-#define MANGLED_CACHE_MAX_MEMORY 0
+#define MANGLED_CACHE_MAX_MEMORY 0
+
/* -------------------------------------------------------------------------- **
- * External Variables...
+ * Functions...
*/
-extern int case_default; /* Are conforming 8.3 names all upper or lower? */
-extern BOOL case_mangle; /* If true, all chars in 8.3 should be same case. */
-
-/* -------------------------------------------------------------------- */
-
-static NTSTATUS has_valid_chars(const smb_ucs2_t *s, BOOL allow_wildcards)
-{
- if (!s || !*s)
- return NT_STATUS_INVALID_PARAMETER;
-
- /* CHECK: this should not be necessary if the ms wild chars
- are not valid in valid.dat --- simo */
- if (!allow_wildcards && ms_has_wild_w(s))
- return NT_STATUS_UNSUCCESSFUL;
-
- while (*s) {
- if(!isvalid83_w(*s))
- return NT_STATUS_UNSUCCESSFUL;
- s++;
- }
-
- return NT_STATUS_OK;
-}
-
-/* return False if something fail and
- * return 2 alloced unicode strings that contain prefix and extension
+/* ************************************************************************** **
+ * Initialize the static character test array.
+ *
+ * Input: none
+ *
+ * Output: none
+ *
+ * Notes: This function changes (loads) the contents of the <chartest>
+ * array. The scope of <chartest> is this file.
+ *
+ * ************************************************************************** **
*/
+static void init_chartest( void )
+ {
+ char *illegalchars = "*\\/?<>|\":";
+ unsigned char *s;
+
+ memset( (char *)chartest, '\0', 256 );
-static NTSTATUS mangle_get_prefix(const smb_ucs2_t *ucs2_string, smb_ucs2_t **prefix,
- smb_ucs2_t **extension, BOOL allow_wildcards)
-{
- size_t ext_len;
- smb_ucs2_t *p;
+ for( s = (unsigned char *)illegalchars; *s; s++ )
+ chartest[*s] = ILLEGAL_MASK;
- *extension = 0;
- *prefix = strdup_w(ucs2_string);
- if (!*prefix) {
- return NT_STATUS_NO_MEMORY;
- }
- if ((p = strrchr_w(*prefix, UCS2_CHAR('.')))) {
- ext_len = strlen_w(p+1);
- if ((ext_len > 0) && (ext_len < 4) && (p != *prefix) &&
- (NT_STATUS_IS_OK(has_valid_chars(p+1,allow_wildcards)))) /* check extension */ {
- *p = 0;
- *extension = strdup_w(p+1);
- if (!*extension) {
- SAFE_FREE(*prefix);
- return NT_STATUS_NO_MEMORY;
- }
- }
- }
- return NT_STATUS_OK;
-}
+ for( s = (unsigned char *)basechars; *s; s++ )
+ chartest[*s] |= BASECHAR_MASK;
+
+ ct_initialized = True;
+ } /* init_chartest */
/* ************************************************************************** **
- * Return NT_STATUS_UNSUCCESSFUL if a name is a special msdos reserved name.
+ * Return True if a name is a special msdos reserved name.
*
* Input: fname - String containing the name to be tested.
*
- * Output: NT_STATUS_UNSUCCESSFUL, if the name matches one of the list of reserved names.
+ * Output: True, if the name matches one of the list of reserved names.
*
* Notes: This is a static function called by is_8_3(), below.
*
* ************************************************************************** **
*/
-
-static NTSTATUS is_valid_name(const smb_ucs2_t *fname, BOOL allow_wildcards)
-{
- smb_ucs2_t *str, *p;
- NTSTATUS ret = NT_STATUS_OK;
-
- if (!fname || !*fname)
- return NT_STATUS_INVALID_PARAMETER;
-
- /* . and .. are valid names. */
- if (strcmp_wa(fname, ".")==0 || strcmp_wa(fname, "..")==0)
- return NT_STATUS_OK;
-
- /* Name cannot start with '.' */
- if (*fname == UCS2_CHAR('.'))
- return NT_STATUS_UNSUCCESSFUL;
-
- ret = has_valid_chars(fname, allow_wildcards);
- if (NT_STATUS_IS_ERR(ret))
- return ret;
-
- str = strdup_w(fname);
- p = strchr_w(str, UCS2_CHAR('.'));
- if (p && p[1] == UCS2_CHAR(0)) {
- /* Name cannot end in '.' */
- SAFE_FREE(str);
- return NT_STATUS_UNSUCCESSFUL;
- }
- if (p) *p = 0;
- strupper_w(str);
- p = &(str[1]);
-
- switch(str[0])
- {
- case UCS2_CHAR('A'):
- if(strcmp_wa(p, "UX") == 0)
- ret = NT_STATUS_UNSUCCESSFUL;
- break;
- case UCS2_CHAR('C'):
- if((strcmp_wa(p, "LOCK$") == 0)
- || (strcmp_wa(p, "ON") == 0)
- || (strcmp_wa(p, "OM1") == 0)
- || (strcmp_wa(p, "OM2") == 0)
- || (strcmp_wa(p, "OM3") == 0)
- || (strcmp_wa(p, "OM4") == 0)
- )
- ret = NT_STATUS_UNSUCCESSFUL;
- break;
- case UCS2_CHAR('L'):
- if((strcmp_wa(p, "PT1") == 0)
- || (strcmp_wa(p, "PT2") == 0)
- || (strcmp_wa(p, "PT3") == 0)
- )
- ret = NT_STATUS_UNSUCCESSFUL;
- break;
- case UCS2_CHAR('N'):
- if(strcmp_wa(p, "UL") == 0)
- ret = NT_STATUS_UNSUCCESSFUL;
- break;
- case UCS2_CHAR('P'):
- if(strcmp_wa(p, "RN") == 0)
- ret = NT_STATUS_UNSUCCESSFUL;
- break;
- default:
- break;
- }
-
- SAFE_FREE(str);
- return ret;
-}
-
-static NTSTATUS is_8_3_w(const smb_ucs2_t *fname, BOOL allow_wildcards)
-{
- smb_ucs2_t *pref = 0, *ext = 0;
- size_t plen;
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-
- if (!fname || !*fname)
- return NT_STATUS_INVALID_PARAMETER;
-
- if (strlen_w(fname) > 12)
- return NT_STATUS_UNSUCCESSFUL;
-
- if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0)
- return NT_STATUS_OK;
-
- if (NT_STATUS_IS_ERR(is_valid_name(fname, allow_wildcards)))
- goto done;
-
- if (NT_STATUS_IS_ERR(mangle_get_prefix(fname, &pref, &ext, allow_wildcards)))
- goto done;
- plen = strlen_w(pref);
-
- if (strchr_wa(pref, '.'))
- goto done;
- if (plen < 1 || plen > 8)
- goto done;
- if (ext && (strlen_w(ext) > 3))
- goto done;
-
- ret = NT_STATUS_OK;
-
-done:
- SAFE_FREE(pref);
- SAFE_FREE(ext);
- return ret;
-}
-
-static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards)
-{
- const char *f;
- smb_ucs2_t *ucs2name;
- NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-
- if (!fname || !*fname)
- return False;
- if ((f = strrchr(fname, '/')) == NULL)
- f = fname;
- else
- f++;
-
- if (strlen(f) > 12)
- return False;
-
- ucs2name = acnv_uxu2(f);
- if (!ucs2name) {
- DEBUG(0,("is_8_3: internal error acnv_uxu2() failed!\n"));
- goto done;
- }
-
- ret = is_8_3_w(ucs2name, allow_wildcards);
-
-done:
- SAFE_FREE(ucs2name);
-
- if (!NT_STATUS_IS_OK(ret)) {
- return False;
- }
-
- return True;
-}
-
-
-
-/* -------------------------------------------------------------------------- **
- * Functions...
- */
+static BOOL is_reserved_msdos( char *fname )
+ {
+ char upperFname[13];
+ char *p;
+
+ StrnCpy (upperFname, fname, 12);
+
+ /* lpt1.txt and con.txt etc are also illegal */
+ p = strchr(upperFname,'.');
+ if( p )
+ *p = '\0';
+
+ strupper( upperFname );
+ p = upperFname + 1;
+ switch( upperFname[0] )
+ {
+ case 'A':
+ if( 0 == strcmp( p, "UX" ) )
+ return( True );
+ break;
+ case 'C':
+ if( (0 == strcmp( p, "LOCK$" ))
+ || (0 == strcmp( p, "ON" ))
+ || (0 == strcmp( p, "OM1" ))
+ || (0 == strcmp( p, "OM2" ))
+ || (0 == strcmp( p, "OM3" ))
+ || (0 == strcmp( p, "OM4" ))
+ )
+ return( True );
+ break;
+ case 'L':
+ if( (0 == strcmp( p, "PT1" ))
+ || (0 == strcmp( p, "PT2" ))
+ || (0 == strcmp( p, "PT3" ))
+ )
+ return( True );
+ break;
+ case 'N':
+ if( 0 == strcmp( p, "UL" ) )
+ return( True );
+ break;
+ case 'P':
+ if( 0 == strcmp( p, "RN" ) )
+ return( True );
+ break;
+ }
+
+ return( False );
+ } /* is_reserved_msdos */
/* ************************************************************************** **
- * Initialize the static character test array.
+ * Determine whether or not a given name contains illegal characters, even
+ * long names.
*
- * Input: none
+ * Input: name - The name to be tested.
*
- * Output: none
+ * Output: True if an illegal character was found in <name>, else False.
*
- * Notes: This function changes (loads) the contents of the <chartest>
- * array. The scope of <chartest> is this file.
+ * Notes: This is used to test a name on the host system, long or short,
+ * for characters that would be illegal on most client systems,
+ * particularly DOS and Windows systems. Unix and AmigaOS, for
+ * example, allow a filenames which contain such oddities as
+ * quotes ("). If a name is found which does contain an illegal
+ * character, it is mangled even if it conforms to the 8.3
+ * format.
*
* ************************************************************************** **
*/
-static void init_chartest( void )
-{
- char *illegalchars = "*\\/?<>|\":";
- unsigned char *s;
-
- memset( (char *)chartest, '\0', 256 );
-
- for( s = (unsigned char *)illegalchars; *s; s++ )
- chartest[*s] = ILLEGAL_MASK;
-
- for( s = (unsigned char *)basechars; *s; s++ )
- chartest[*s] |= BASECHAR_MASK;
-
- ct_initialized = True;
-}
+static BOOL is_illegal_name( char *name )
+ {
+ unsigned char *s;
+ int skip;
+ int namelen;
+
+ if( !name )
+ return( True );
+
+ if( !ct_initialized )
+ init_chartest();
+
+ namelen = strlen(name);
+ if (namelen &&
+ name[namelen-1] == '.' &&
+ !strequal(name, ".") &&
+ !strequal(name, ".."))
+ return True;
+
+ s = (unsigned char *)name;
+ while( *s )
+ {
+ skip = get_character_len( *s );
+ if( skip != 0 )
+ {
+ s += skip;
+ }
+ else
+ {
+ if( isillegal( *s ) )
+ return( True );
+ else
+ s++;
+ }
+ }
+
+ return( False );
+ } /* is_illegal_name */
/* ************************************************************************** **
* Return True if the name *could be* a mangled name.
@@ -392,22 +296,152 @@ static void init_chartest( void )
*
* ************************************************************************** **
*/
-static BOOL is_mangled(const char *s)
+static BOOL is_mangled( const char *s )
{
char *magic;
+ BOOL ret = False;
if( !ct_initialized )
init_chartest();
- magic = strchr_m( s, magic_char );
- while( magic && magic[1] && magic[2] ) { /* 3 chars, 1st is magic. */
+ magic = strchr( s, magic_char );
+ while( magic && magic[1] && magic[2] ) {
+ /* 3 chars, 1st is magic. */
if( ('.' == magic[3] || '/' == magic[3] || !(magic[3])) /* Ends with '.' or nul or '/' ? */
&& isbasechar( toupper(magic[1]) ) /* is 2nd char basechar? */
&& isbasechar( toupper(magic[2]) ) ) /* is 3rd char basechar? */
- return( True ); /* If all above, then true, */
- magic = strchr_m( magic+1, magic_char ); /* else seek next magic. */
+ ret = ( True ); /* If all above, then true, */
+ magic = strchr( magic+1, magic_char ); /* else seek next magic. */
+ }
+
+ DEBUG(10,("is_mangled: %s : %s\n", s, ret ? "True" : "False"));
+
+ return ret;
+} /* is_mangled */
+
+static BOOL is_ms_wildchar(const char c)
+{
+ switch(c) {
+ case '*':
+ case '?':
+ case '<':
+ case '>':
+ case '"':
+ return True;
+ default:
+ return False;
}
- return( False );
+}
+
+/* ************************************************************************** **
+ * Return True if the name is a valid DOS name in 8.3 DOS format.
+ *
+ * Input: fname - File name to be checked.
+ * check_case - If True, and if case_mangle is True, then the
+ * name will be checked to see if all characters
+ * are the correct case. See case_mangle and
+ * case_default above.
+ * allow_wildcards - If True dos wildcard characters *?<>" are allowed as 8.3.
+ *
+ * Output: True if the name is a valid DOS name, else False.
+ *
+ * ************************************************************************** **
+ */
+
+static BOOL is_8_3( const char *cfname, BOOL check_case, BOOL allow_wildcards )
+{
+ int len;
+ int l;
+ int skip;
+ char *p;
+ char *dot_pos;
+ char *slash_pos;
+ char *fname = (char *)cfname;
+
+ slash_pos = strrchr( fname, '/' );
+
+ /* If there is a directory path, skip it. */
+ if( slash_pos )
+ fname = slash_pos + 1;
+ len = strlen( fname );
+
+ DEBUG( 5, ( "Checking %s for 8.3\n", fname ) );
+
+ /* Can't be 0 chars or longer than 12 chars */
+ if( (len == 0) || (len > 12) )
+ return( False );
+
+ /* Mustn't be an MS-DOS Special file such as lpt1 or even lpt1.txt */
+ if( is_reserved_msdos( fname ) )
+ return( False );
+
+ /* Check that all characters are the correct case, if asked to do so. */
+ if( check_case && case_mangle ) {
+ switch( case_default ) {
+ case CASE_LOWER:
+ if( strhasupper( fname ) )
+ return(False);
+ break;
+ case CASE_UPPER:
+ if( strhaslower( fname ) )
+ return(False);
+ break;
+ }
+ }
+
+ /* Can't contain invalid dos chars */
+ /* Windows use the ANSI charset.
+ But filenames are translated in the PC charset.
+ This Translation may be more or less relaxed depending
+ the Windows application. */
+
+ /* %%% A nice improvment to name mangling would be to translate
+ filename to ANSI charset on the smb server host */
+
+ p = fname;
+ dot_pos = NULL;
+ while( *p ) {
+ if( (skip = get_character_len( *p )) != 0 )
+ p += skip;
+ else {
+ if( *p == '.' && !dot_pos )
+ dot_pos = (char *)p;
+ else {
+ if( !isdoschar( *p )) {
+ if (!allow_wildcards)
+ return False;
+ if (!is_ms_wildchar(*p))
+ return False;
+ }
+ }
+ p++;
+ }
+ }
+
+ /* no dot and less than 9 means OK */
+ if( !dot_pos )
+ return( len <= 8 );
+
+ l = PTR_DIFF( dot_pos, fname );
+
+ /* base must be at least 1 char except special cases . and .. */
+ if( l == 0 )
+ return( 0 == strcmp( fname, "." ) || 0 == strcmp( fname, ".." ) );
+
+ /* base can't be greater than 8 */
+ if( l > 8 )
+ return( False );
+
+ /* extension must be between 1 and 3 */
+ if( (len - l < 2 ) || (len - l > 4) )
+ return( False );
+
+ /* extensions may not have a dot */
+ if( strchr( dot_pos+1, '.' ) )
+ return( False );
+
+ /* must be in 8.3 format */
+ return( True );
}
/* ************************************************************************** **
@@ -429,11 +463,14 @@ static BOOL is_mangled(const char *s)
*
* ************************************************************************** **
*/
+
static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr )
{
char *Key1 = (char *)ItemPtr;
char *Key2 = (char *)(((ubi_cacheEntryPtr)NodePtr) + 1);
+ DEBUG(100,("cache_compare: %s %s\n", Key1, Key2));
+
return( StrCaseCmp( Key1, Key2 ) );
}
@@ -450,6 +487,7 @@ static signed int cache_compare( ubi_btItemPtr ItemPtr, ubi_btNodePtr NodePtr )
*
* ************************************************************************** **
*/
+
static void cache_free_entry( ubi_trNodePtr WarrenZevon )
{
ZERO_STRUCTP(WarrenZevon);
@@ -473,22 +511,22 @@ static void cache_free_entry( ubi_trNodePtr WarrenZevon )
* ************************************************************************** **
*/
-static void mangle_reset( void )
+static void reset_mangled_cache( void )
{
if( !mc_initialized ) {
(void)ubi_cacheInit( mangled_cache,
- cache_compare,
- cache_free_entry,
- MANGLED_CACHE_MAX_ENTRIES,
- MANGLED_CACHE_MAX_MEMORY );
+ cache_compare,
+ cache_free_entry,
+ MANGLED_CACHE_MAX_ENTRIES,
+ MANGLED_CACHE_MAX_MEMORY );
mc_initialized = True;
} else {
(void)ubi_cacheClear( mangled_cache );
}
/*
- (void)ubi_cacheSetMaxEntries( mangled_cache, lp_mangled_cache_entries() );
- (void)ubi_cacheSetMaxMemory( mangled_cache, lp_mangled_cache_memory() );
+ (void)ubi_cacheSetMaxEntries( mangled_cache, lp_mangled_cache_entries() );
+ (void)ubi_cacheSetMaxMemory( mangled_cache, lp_mangled_cache_memory() );
*/
}
@@ -518,47 +556,49 @@ static void mangle_reset( void )
*/
static void cache_mangled_name( char *mangled_name, char *raw_name )
{
- ubi_cacheEntryPtr new_entry;
- char *s1;
- char *s2;
- size_t mangled_len;
- size_t raw_len;
- size_t i;
-
- /* If the cache isn't initialized, give up. */
- if( !mc_initialized )
- return;
-
- /* Init the string lengths. */
- mangled_len = strlen( mangled_name );
- raw_len = strlen( raw_name );
-
- /* See if the extensions are unmangled. If so, store the entry
- * without the extension, thus creating a "group" reverse map.
- */
- s1 = strrchr( mangled_name, '.' );
- if( s1 && (s2 = strrchr( raw_name, '.' )) ) {
- i = 1;
- while( s1[i] && (tolower( s1[i] ) == s2[i]) )
- i++;
- if( !s1[i] && !s2[i] ) {
- mangled_len -= i;
- raw_len -= i;
- }
- }
-
- /* Allocate a new cache entry. If the allocation fails, just return. */
- i = sizeof( ubi_cacheEntry ) + mangled_len + raw_len + 2;
- new_entry = malloc( i );
- if( !new_entry )
- return;
-
- /* Fill the new cache entry, and add it to the cache. */
- s1 = (char *)(new_entry + 1);
- s2 = (char *)&(s1[mangled_len + 1]);
- (void)StrnCpy( s1, mangled_name, mangled_len );
- (void)StrnCpy( s2, raw_name, raw_len );
- ubi_cachePut( mangled_cache, i, new_entry, s1 );
+ ubi_cacheEntryPtr new_entry;
+ char *s1;
+ char *s2;
+ size_t mangled_len;
+ size_t raw_len;
+ size_t i;
+
+ /* If the cache isn't initialized, give up. */
+ if( !mc_initialized )
+ return;
+
+ /* Init the string lengths. */
+ mangled_len = strlen( mangled_name );
+ raw_len = strlen( raw_name );
+
+ /* See if the extensions are unmangled. If so, store the entry
+ * without the extension, thus creating a "group" reverse map.
+ */
+ s1 = strrchr( mangled_name, '.' );
+ if( s1 && (s2 = strrchr( raw_name, '.' )) )
+ {
+ i = 1;
+ while( s1[i] && (tolower( s1[i] ) == s2[i]) )
+ i++;
+ if( !s1[i] && !s2[i] )
+ {
+ mangled_len -= i;
+ raw_len -= i;
+ }
+ }
+
+ /* Allocate a new cache entry. If the allocation fails, just return. */
+ i = sizeof( ubi_cacheEntry ) + mangled_len + raw_len + 2;
+ new_entry = malloc( i );
+ if( !new_entry )
+ return;
+
+ /* Fill the new cache entry, and add it to the cache. */
+ s1 = (char *)(new_entry + 1);
+ s2 = (char *)&(s1[mangled_len + 1]);
+ (void)StrnCpy( s1, mangled_name, mangled_len );
+ (void)StrnCpy( s2, raw_name, raw_len );
+ ubi_cachePut( mangled_cache, i, new_entry, s1 );
}
/* ************************************************************************** **
@@ -576,58 +616,67 @@ static void cache_mangled_name( char *mangled_name, char *raw_name )
* ************************************************************************** **
*/
-static BOOL check_cache( char *s )
+static BOOL check_mangled_cache( char *s )
{
- ubi_cacheEntryPtr FoundPtr;
- char *ext_start = NULL;
- char *found_name;
- char *saved_ext = NULL;
-
- /* If the cache isn't initialized, give up. */
- if( !mc_initialized )
- return( False );
-
- FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s );
-
- /* If we didn't find the name *with* the extension, try without. */
- if( !FoundPtr ) {
- ext_start = strrchr( s, '.' );
- if( ext_start ) {
- if((saved_ext = strdup(ext_start)) == NULL)
- return False;
-
- *ext_start = '\0';
- FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s );
- /*
- * At this point s is the name without the
- * extension. We re-add the extension if saved_ext
- * is not null, before freeing saved_ext.
- */
- }
- }
-
- /* Okay, if we haven't found it we're done. */
- if( !FoundPtr ) {
- if(saved_ext) {
- /* Replace the saved_ext as it was truncated. */
- (void)pstrcat( s, saved_ext );
- SAFE_FREE(saved_ext);
- }
- return( False );
- }
-
- /* If we *did* find it, we need to copy it into the string buffer. */
- found_name = (char *)(FoundPtr + 1);
- found_name += (strlen( found_name ) + 1);
-
- (void)pstrcpy( s, found_name );
- if( saved_ext ) {
- /* Replace the saved_ext as it was truncated. */
- (void)pstrcat( s, saved_ext );
- SAFE_FREE(saved_ext);
- }
-
- return( True );
+ ubi_cacheEntryPtr FoundPtr;
+ char *ext_start = NULL;
+ char *found_name;
+ char *saved_ext = NULL;
+
+ /* If the cache isn't initialized, give up. */
+ if( !mc_initialized )
+ return( False );
+
+ FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s );
+
+ /* If we didn't find the name *with* the extension, try without. */
+ if( !FoundPtr )
+ {
+ ext_start = strrchr( s, '.' );
+ if( ext_start )
+ {
+ if((saved_ext = strdup(ext_start)) == NULL)
+ return False;
+
+ *ext_start = '\0';
+ FoundPtr = ubi_cacheGet( mangled_cache, (ubi_trItemPtr)s );
+ /*
+ * At this point s is the name without the
+ * extension. We re-add the extension if saved_ext
+ * is not null, before freeing saved_ext.
+ */
+ }
+ }
+
+ /* Okay, if we haven't found it we're done. */
+ if( !FoundPtr )
+ {
+ if(saved_ext)
+ {
+ /* Replace the saved_ext as it was truncated. */
+ (void)pstrcat( s, saved_ext );
+ SAFE_FREE(saved_ext);
+ }
+ return( False );
+ }
+
+ /* If we *did* find it, we need to copy it into the string buffer. */
+ found_name = (char *)(FoundPtr + 1);
+ found_name += (strlen( found_name ) + 1);
+
+ DEBUG( 3, ("Found %s on mangled stack ", s) );
+
+ (void)pstrcpy( s, found_name );
+ if( saved_ext )
+ {
+ /* Replace the saved_ext as it was truncated. */
+ (void)pstrcat( s, saved_ext );
+ SAFE_FREE(saved_ext);
+ }
+
+ DEBUG( 3, ("as %s\n", s) );
+
+ return( True );
}
/*****************************************************************************
@@ -635,67 +684,124 @@ static BOOL check_cache( char *s )
* the buffer must be able to hold 13 characters (including the null)
*****************************************************************************
*/
-static void to_8_3(char *s)
+static void mangle_name_83( char *s)
{
- int csum;
- char *p;
- char extension[4];
- char base[9];
- int baselen = 0;
- int extlen = 0;
-
- extension[0] = 0;
- base[0] = 0;
-
- p = strrchr(s,'.');
- if( p && (strlen(p+1) < (size_t)4) ) {
- BOOL all_normal = ( strisnormal(p+1) ); /* XXXXXXXXX */
-
- if( all_normal && p[1] != 0 ) {
- *p = 0;
- csum = str_checksum( s );
- *p = '.';
- } else
- csum = str_checksum(s);
- } else
- csum = str_checksum(s);
-
- strupper( s );
-
- if( p ) {
- if( p == s )
- safe_strcpy( extension, "___", 3 );
- else {
- *p++ = 0;
- while( *p && extlen < 3 ) {
- if ( *p != '.') {
- extension[extlen++] = p[0];
- }
- p++;
- }
- extension[extlen] = 0;
- }
- }
-
- p = s;
+ int csum;
+ char *p;
+ char extension[4];
+ char base[9];
+ int baselen = 0;
+ int extlen = 0;
+ int skip;
+
+ extension[0] = 0;
+ base[0] = 0;
+
+ p = strrchr(s,'.');
+ if( p && (strlen(p+1) < (size_t)4) )
+ {
+ BOOL all_normal = ( strisnormal(p+1) ); /* XXXXXXXXX */
+
+ if( all_normal && p[1] != 0 )
+ {
+ *p = 0;
+ csum = str_checksum( s );
+ *p = '.';
+ }
+ else
+ csum = str_checksum(s);
+ }
+ else
+ csum = str_checksum(s);
+
+ strupper( s );
+
+ DEBUG( 5, ("Mangling name %s to ",s) );
+
+ if( p )
+ {
+ if( p == s )
+ safe_strcpy( extension, "___", 3 );
+ else
+ {
+ *p++ = 0;
+ while( *p && extlen < 3 )
+ {
+ skip = get_character_len( *p );
+ switch( skip )
+ {
+ case 2:
+ if( extlen < 2 )
+ {
+ extension[extlen++] = p[0];
+ extension[extlen++] = p[1];
+ }
+ else
+ {
+ extension[extlen++] = mangle( (unsigned char)*p );
+ }
+ p += 2;
+ break;
+ case 1:
+ extension[extlen++] = p[0];
+ p++;
+ break;
+ default:
+ if( isdoschar (*p) && *p != '.' )
+ extension[extlen++] = p[0];
+ p++;
+ break;
+ }
+ }
+ extension[extlen] = 0;
+ }
+ }
+
+ p = s;
+
+ while( *p && baselen < 5 )
+ {
+ skip = get_character_len(*p);
+ switch( skip )
+ {
+ case 2:
+ if( baselen < 4 )
+ {
+ base[baselen++] = p[0];
+ base[baselen++] = p[1];
+ }
+ else
+ {
+ base[baselen++] = mangle( (unsigned char)*p );
+ }
+ p += 2;
+ break;
+ case 1:
+ base[baselen++] = p[0];
+ p++;
+ break;
+ default:
+ if( isdoschar( *p ) && *p != '.' )
+ base[baselen++] = p[0];
+ p++;
+ break;
+ }
+ }
+ base[baselen] = 0;
+
+ csum = csum % (MANGLE_BASE*MANGLE_BASE);
+
+ (void)slprintf(s, 12, "%s%c%c%c",
+ base, magic_char, mangle( csum/MANGLE_BASE ), mangle( csum ) );
+
+ if( *extension )
+ {
+ (void)pstrcat( s, "." );
+ (void)pstrcat( s, extension );
+ }
+
+ DEBUG( 5, ( "%s\n", s ) );
- while( *p && baselen < 5 ) {
- if (*p != '.') {
- base[baselen++] = p[0];
- }
- p++;
- }
- base[baselen] = 0;
-
- csum = csum % (MANGLE_BASE*MANGLE_BASE);
-
- (void)slprintf(s, 12, "%s%c%c%c",
- base, magic_char, mangle( csum/MANGLE_BASE ), mangle( csum ) );
-
- if( *extension ) {
- (void)pstrcat( s, "." );
- (void)pstrcat( s, extension );
- }
}
/*****************************************************************************
@@ -717,36 +823,33 @@ static void to_8_3(char *s)
* a conflicting cache entry prematurely, i.e. before
* we know whether the client is really interested in the
* current name. (See PR#13758). UKD.
+ * snum - Share number. This identifies the share in which the
+ * name exists.
*
* Output: Returns False only if the name wanted mangling but the share does
* not have name mangling turned on.
*
* ****************************************************************************
*/
-
-static void name_map(char *OutName, BOOL need83, BOOL cache83)
+static void name_map_mangle(char *OutName, BOOL need83, BOOL cache83)
{
- smb_ucs2_t *OutName_ucs2;
- DEBUG(5,("name_map( %s, need83 = %s, cache83 = %s)\n", OutName,
- need83 ? "True" : "False", cache83 ? "True" : "False"));
-
- if (push_ucs2_allocate(&OutName_ucs2, OutName) < 0) {
- DEBUG(0, ("push_ucs2_allocate failed!\n"));
- return;
- }
+ DEBUG(5,("name_map_mangle( %s, need83 = %s, cache83 = %s )\n", OutName,
+ need83 ? "True" : "False", cache83 ? "True" : "False" ));
- if( !need83 && NT_STATUS_IS_ERR(is_valid_name(OutName_ucs2, False)))
+#ifdef MANGLE_LONG_FILENAMES
+ if( !need83 && is_illegal_name(OutName) )
need83 = True;
+#endif
/* check if it's already in 8.3 format */
- if (need83 && !NT_STATUS_IS_OK(is_8_3_w(OutName_ucs2, False))) {
+ if (need83 && !is_8_3(OutName, True, False)) {
char *tmp = NULL;
/* mangle it into 8.3 */
if (cache83)
tmp = strdup(OutName);
- to_8_3(OutName);
+ mangle_name_83(OutName);
if(tmp != NULL) {
cache_mangled_name(OutName, tmp);
@@ -754,26 +857,24 @@ static void name_map(char *OutName, BOOL need83, BOOL cache83)
}
}
- DEBUG(5,("name_map() ==> [%s]\n", OutName));
- SAFE_FREE(OutName_ucs2);
+ DEBUG(5,("name_map_mangle() ==> [%s]\n", OutName));
}
/*
- the following provides the abstraction layer to make it easier
- to drop in an alternative mangling implementation
-*/
+ * the following provides the abstraction layer to make it easier
+ * to drop in an alternative mangling implementation
+ * */
static struct mangle_fns mangle_fns = {
is_mangled,
is_8_3,
- mangle_reset,
- check_cache,
- name_map
+ reset_mangled_cache,
+ check_mangled_cache,
+ name_map_mangle
};
/* return the methods for this mangling implementation */
struct mangle_fns *mangle_hash_init(void)
{
- mangle_reset();
-
+ reset_mangled_cache();
return &mangle_fns;
}