/* Unix SMB/Netbios implementation. Version 1.9. Name mangling Copyright (C) Andrew Tridgell 1992-1995 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 (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 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. */ #include "includes.h" #include "loadparm.h" extern int DEBUGLEVEL; extern int case_default; extern BOOL case_mangle; /**************************************************************************** provide a checksum on a string ****************************************************************************/ int str_checksum(char *s) { int res = 0; int c; int i=0; while (*s) { c = *s; res ^= (c << (i % 15)) ^ (c >> (15-(i%15))); s++; i++; } return(res); } /**************************************************************************** return True if a name is a special msdos reserved name ****************************************************************************/ 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); if ((strcmp(upperFname,"CLOCK$") == 0) || (strcmp(upperFname,"CON") == 0) || (strcmp(upperFname,"AUX") == 0) || (strcmp(upperFname,"COM1") == 0) || (strcmp(upperFname,"COM2") == 0) || (strcmp(upperFname,"COM3") == 0) || (strcmp(upperFname,"COM4") == 0) || (strcmp(upperFname,"LPT1") == 0) || (strcmp(upperFname,"LPT2") == 0) || (strcmp(upperFname,"LPT3") == 0) || (strcmp(upperFname,"NUL") == 0) || (strcmp(upperFname,"PRN") == 0)) return (True) ; return (False); } /**************************************************************************** return True if a name is in 8.3 dos format ****************************************************************************/ BOOL is_8_3(char *fname) { int len; char *dot_pos; char *slash_pos = strrchr(fname,'/'); int l; if (slash_pos) fname = slash_pos+1; len = strlen(fname); dot_pos = strchr(fname,'.'); DEBUG(5,("checking %s for 8.3\n",fname)); if (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 be longer than 12 chars */ if (len == 0 || len > 12) return(False); /* can't be an MS-DOS Special file such as lpt1 or even lpt1.txt */ if (is_reserved_msdos(fname)) return(False); /* 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 */ { char *p = fname; #ifdef KANJI dot_pos = 0; while (*p) { if (is_shift_jis (*p)) { p += 2; } else if (is_kana (*p)) { p ++; } else { if (*p == '.' && !dot_pos) dot_pos = (char *) p; if (!isdoschar(*p)) return(False); p++; } } #else while (*p) { if (!isdoschar(*p)) return(False); p++; } #endif /* KANJI */ } /* 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(strcmp(fname,".") == 0 || strcmp(fname,"..") == 0); /* base can't be greater than 8 */ if (l > 8) return(False); if (lp_strip_dot() && len - l == 1 && !strchr(dot_pos+1,'.')) { *dot_pos = 0; return(True); } /* extension must be between 1 and 3 */ if ( (len - l < 2 ) || (len - l > 4) ) return(False); /* extension can't have a dot */ if (strchr(dot_pos+1,'.')) return(False); /* must be in 8.3 format */ return(True); } /* keep a stack of name mangling results - just so file moves and copies have a chance of working */ fstring *mangled_stack = NULL; int mangled_stack_size = 0; int mangled_stack_len = 0; /**************************************************************************** create the mangled stack ****************************************************************************/ void create_mangled_stack(int size) { if (mangled_stack) { free(mangled_stack); mangled_stack_size = 0; mangled_stack_len = 0; } if (size > 0) mangled_stack = (fstring *)malloc(sizeof(fstring)*size); if (mangled_stack) mangled_stack_size = size; } /**************************************************************************** push a mangled name onto the stack ****************************************************************************/ static void push_mangled_name(char *s) { int i; char *p; if (!mangled_stack) return; for (i=0;i