Index: src/add.c ================================================================== --- src/add.c +++ src/add.c @@ -138,11 +138,12 @@ int vid, /* Add to this VFILE */ int caseSensitive /* True if filenames are case sensitive */ ){ const char *zCollate = caseSensitive ? "binary" : "nocase"; if( !file_is_simple_pathname(zPath) ){ - fossil_fatal("filename contains illegal characters: %s", zPath); + fossil_warning("filename contains illegal characters: %s", zPath); + return 0; } if( db_exists("SELECT 1 FROM vfile" " WHERE pathname=%Q COLLATE %s", zPath, zCollate) ){ db_multi_exec("UPDATE vfile SET deleted=0" " WHERE pathname=%Q COLLATE %s", zPath, zCollate); Index: src/checkout.c ================================================================== --- src/checkout.c +++ src/checkout.c @@ -106,11 +106,11 @@ /* Check the EXE permission status of all files */ pManifest = manifest_get(vid, CFTYPE_MANIFEST); if( pManifest==0 ) return; blob_zero(&filename); - blob_appendf(&filename, "%s/", g.zLocalRoot); + blob_appendf(&filename, "%s", g.zLocalRoot); baseLen = blob_size(&filename); manifest_file_rewind(pManifest); while( (pFile = manifest_file_next(pManifest, 0))!=0 ){ int isExe; blob_append(&filename, pFile->zName, -1); Index: src/db.c ================================================================== --- src/db.c +++ src/db.c @@ -1697,11 +1697,11 @@ ** and a checkout is open. */ if( cacheEntry==0 ){ Blob versionedPathname; char *zVersionedPathname; blob_zero(&versionedPathname); - blob_appendf(&versionedPathname, "%s/.fossil-settings/%s", + blob_appendf(&versionedPathname, "%s.fossil-settings/%s", g.zLocalRoot, zName); zVersionedPathname = blob_str(&versionedPathname); if( file_size(zVersionedPathname)>=0 ){ /* File exists, and contains the value for this setting. Load from ** the file. */ Index: src/file.c ================================================================== --- src/file.c +++ src/file.c @@ -495,10 +495,35 @@ if( c=='.' ){ if( z[1]=='/' || z[1]==0 ) return 0; if( z[1]=='.' && (z[2]=='/' || z[2]==0) ) return 0; } for(i=0; (c=z[i])!=0; i++){ + if( (c & 0xf0) == 0xf0 ) { + /* Unicode characters > U+FFFF are not supported. + * Windows XP and earlier cannot handle them. + */ + return 0; + } + if( (c & 0xf0) == 0xe0 ) { + /* This is a 3-byte UTF-8 character */ + if ( (c & 0xfe) == 0xee ){ + /* Range U+E000 - U+FFFF (Starting with 0xee or 0xef in UTF-8 ) */ + if ( (c & 1) && ((z[i+1] & 0xff) >= 0xa4) ){ + /* But exclude U+F900 - U+FFFF (0xef followed by byte >= 0xa4), + * which contain valid characters. */ + continue; + } + /* Unicode character in the range U+E000 - U+F8FF are for + * private use, they shouldn't occur in filenames. */ + return 0; + } + if( ((c & 0xff) == 0xed) && ((z[i+1] & 0xe0) == 0xa0) ){ + /* Unicode character in the range U+D800 - U+DFFF are for + * surrogate pairs, they shouldn't occur in filenames. */ + return 0; + } + } if( c=='\\' || c=='*' || c=='[' || c==']' || c=='?' ){ return 0; } if( c=='/' ){ if( z[i+1]=='/' ) return 0;