Bug 333703 Non-ascii directory name is garbled in directory index. patch by Masatoshi Kimura (:emk) <VYV03354@nifty.ne.jp> r=jshin, sr=darin

This commit is contained in:
masayuki%d-toybox.com 2006-05-02 06:24:11 +00:00
Родитель 79d9fd9989
Коммит 1c1fe64948
3 изменённых файлов: 83 добавлений и 127 удалений

Просмотреть файл

@ -67,14 +67,14 @@ static PRLogModuleInfo* gLog;
#include "nsURLHelper.h" #include "nsURLHelper.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "nsCRT.h" #include "nsCRT.h"
#include "nsNativeCharsetUtils.h"
static NS_DEFINE_CID(kCollationFactoryCID, NS_COLLATIONFACTORY_CID); static NS_DEFINE_CID(kCollationFactoryCID, NS_COLLATIONFACTORY_CID);
// NOTE: This runs on the _file transport_ thread. // NOTE: This runs on the _file transport_ thread.
// The problem is that now that we're actually doing something with the data, // The problem is that now that we're actually doing something with the data,
// we want to do stuff like i18n sorting. However, none of the collation stuff // we want to do stuff like i18n sorting. However, none of the collation stuff
// is threadsafe, and stuff like GetUnicodeLeafName spews warnings on a debug // is threadsafe.
// build, because the singletons were initialised on the UI thread.
// So THIS CODE IS ASCII ONLY!!!!!!!! This is no worse than the current // So THIS CODE IS ASCII ONLY!!!!!!!! This is no worse than the current
// behaviour, though. See bug 99382. // behaviour, though. See bug 99382.
// When this is fixed, #define THREADSAFE_I18N to get this code working // When this is fixed, #define THREADSAFE_I18N to get this code working
@ -97,43 +97,32 @@ static int PR_CALLBACK compare(nsIFile* aElement1,
nsIFile* aElement2, nsIFile* aElement2,
void* aData) void* aData)
{ {
// Not that this #ifdef makes much of a difference... We need it if (!NS_IsNativeUTF8()) {
// to work out which version of GetLeafName to use, though // don't check for errors, because we can't report them anyway
#ifdef THREADSAFE_I18N nsAutoString name1, name2;
// don't check for errors, because we can't report them anyway aElement1->GetLeafName(name1);
nsXPIDLString name1, name2; aElement2->GetLeafName(name2);
aElement1->GetUnicodeLeafName(getter_Copies(name1));
aElement2->GetUnicodeLeafName(getter_Copies(name2));
// Note - we should be the collation to do sorting. Why don't we? // Note - we should do the collation to do sorting. Why don't we?
// Because that is _slow_. Using TestProtocols to list file:///dev/ // Because that is _slow_. Using TestProtocols to list file:///dev/
// goes from 3 seconds to 22. (This may be why nsXULSortService is // goes from 3 seconds to 22. (This may be why nsXULSortService is
// so slow as well). // so slow as well).
// Does this have bad effects? Probably, but since nsXULTree appears // Does this have bad effects? Probably, but since nsXULTree appears
// to use the raw RDF literal value as the sort key (which ammounts to an // to use the raw RDF literal value as the sort key (which ammounts to an
// strcmp), it won't be any worse, I think. // strcmp), it won't be any worse, I think.
// This could be made faster, by creating the keys once, // This could be made faster, by creating the keys once,
// but CompareString could still be smarter - see bug 99383 - bbaetz // but CompareString could still be smarter - see bug 99383 - bbaetz
// NB - 99393 has been WONTFIXed. So if the I18N code is ever made // NB - 99393 has been WONTFIXed. So if the I18N code is ever made
// threadsafe so that this matters, we'd have to pass through a // threadsafe so that this matters, we'd have to pass through a
// struct { nsIFile*, PRUint8* } with the pre-calculated key. // struct { nsIFile*, PRUint8* } with the pre-calculated key.
return Compare(name1, name2); return Compare(name1, name2);
}
/*PRInt32 res;
// CompareString takes an nsString...
nsString str1(name1);
nsString str2(name2);
nsICollation* coll = (nsICollation*)aData;
coll->CompareString(nsICollation::kCollationStrengthDefault, str1, str2, &res);
return res;*/
#else
nsCAutoString name1, name2; nsCAutoString name1, name2;
aElement1->GetNativeLeafName(name1); aElement1->GetNativeLeafName(name1);
aElement2->GetNativeLeafName(name2); aElement2->GetNativeLeafName(name2);
return Compare(name1, name2); return Compare(name1, name2);
#endif
} }
nsresult nsresult
@ -157,13 +146,6 @@ nsDirectoryIndexStream::Init(nsIFile* aDir)
} }
#endif #endif
#ifdef THREADSAFE_I18N
if (!mTextToSubURI) {
mTextToSubURI = do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
}
#endif
// Sigh. We have to allocate on the heap because there are no // Sigh. We have to allocate on the heap because there are no
// assignment operators defined. // assignment operators defined.
nsCOMPtr<nsISimpleEnumerator> iter; nsCOMPtr<nsISimpleEnumerator> iter;
@ -216,24 +198,6 @@ nsDirectoryIndexStream::Init(nsIFile* aDir)
mBuf.AppendLiteral("200: filename content-length last-modified file-type\n"); mBuf.AppendLiteral("200: filename content-length last-modified file-type\n");
if (mFSCharset.IsEmpty()) {
// OK, set up the charset
#ifdef THREADSAFE_I18N
nsCOMPtr<nsIPlatformCharset> pc = do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
nsString tmp;
rv = pc->GetCharset(kPlatformCharsetSel_FileName, tmp);
if (NS_FAILED(rv)) return rv;
LossyCopyUTF16toASCII(tmp, mFSCharset);
#endif
}
if (!mFSCharset.IsEmpty()) {
mBuf.AppendLiteral("301: ");
mBuf.Append(mFSCharset);
mBuf.Append('\n');
}
return NS_OK; return NS_OK;
} }
@ -334,62 +298,49 @@ nsDirectoryIndexStream::Read(char* aBuf, PRUint32 aCount, PRUint32* aReadCount)
} }
#endif #endif
// rjc: don't return hidden files/directories! // rjc: don't return hidden files/directories!
// bbaetz: why not? // bbaetz: why not?
nsresult rv; nsresult rv;
#ifndef XP_UNIX #ifndef XP_UNIX
PRBool hidden = PR_FALSE; PRBool hidden = PR_FALSE;
current->IsHidden(&hidden); current->IsHidden(&hidden);
if (hidden) { if (hidden) {
PR_LOG(gLog, PR_LOG_DEBUG, PR_LOG(gLog, PR_LOG_DEBUG,
("nsDirectoryIndexStream[%p]: skipping hidden file/directory", ("nsDirectoryIndexStream[%p]: skipping hidden file/directory",
this)); this));
continue; continue;
}
#endif
PRInt64 fileSize = LL_Zero();
current->GetFileSize( &fileSize );
PRInt64 tmpTime = LL_Zero();
PRInt64 fileInfoModifyTime = LL_Zero();
current->GetLastModifiedTime( &tmpTime );
// Why does nsIFile give this back in milliseconds?
LL_MUL(fileInfoModifyTime, tmpTime, PR_USEC_PER_MSEC);
mBuf.AppendLiteral("201: ");
// The "filename" field
{
#ifdef THREADSAFE_I18N
nsXPIDLString leafname;
rv = current->GetUnicodeLeafName(getter_Copies(leafname));
if (NS_FAILED(rv)) return rv;
if (!leafname.IsEmpty()) {
// XXX - this won't work with directories with spaces
// see bug 99478 - bbaetz
nsXPIDLCString escaped;
rv = mTextToSubURI->ConvertAndEscape(mFSCharset.get(),
leafname.get(),
getter_Copies(escaped));
if (NS_FAILED(rv)) return rv;
mBuf.Append(escaped);
mBuf.Append(' ');
}
#else
nsCAutoString leafname;
rv = current->GetNativeLeafName(leafname);
if (NS_FAILED(rv)) return rv;
if (!leafname.IsEmpty()) {
char* escaped = nsEscape(leafname.get(), url_Path);
if (escaped) {
mBuf += escaped;
mBuf.Append(' ');
nsCRT::free(escaped);
}
} }
#endif #endif
}
PRInt64 fileSize = 0;
current->GetFileSize( &fileSize );
PRInt64 fileInfoModifyTime = 0;
current->GetLastModifiedTime( &fileInfoModifyTime );
fileInfoModifyTime *= PR_USEC_PER_MSEC;
mBuf.AppendLiteral("201: ");
// The "filename" field
char* escaped = nsnull;
if (!NS_IsNativeUTF8()) {
nsAutoString leafname;
rv = current->GetLeafName(leafname);
if (NS_FAILED(rv)) return rv;
if (!leafname.IsEmpty())
escaped = nsEscape(NS_ConvertUTF16toUTF8(leafname).get(), url_Path);
} else {
nsCAutoString leafname;
rv = current->GetNativeLeafName(leafname);
if (NS_FAILED(rv)) return rv;
if (!leafname.IsEmpty())
escaped = nsEscape(leafname.get(), url_Path);
}
if (escaped) {
mBuf += escaped;
mBuf.Append(' ');
nsMemory::Free(escaped);
}
// The "content-length" field // The "content-length" field
mBuf.AppendInt(fileSize, 10); mBuf.AppendInt(fileSize, 10);

Просмотреть файл

@ -54,11 +54,6 @@ private:
PRInt32 mPos; // position within mArray PRInt32 mPos; // position within mArray
nsCOMArray<nsIFile> mArray; // file objects within the directory nsCOMArray<nsIFile> mArray; // file objects within the directory
// XXX - we could make these statics, and share them. But we're only going to have one
// of directoryindexstream at once, so there's no point
nsXPIDLCString mFSCharset;
nsCOMPtr<nsITextToSubURI> mTextToSubURI;
nsDirectoryIndexStream(); nsDirectoryIndexStream();
/** /**

Просмотреть файл

@ -166,6 +166,7 @@ nsIndexedToHTML::OnStartRequest(nsIRequest* request, nsISupports *aContext) {
// - bbaetz // - bbaetz
PRBool isScheme = PR_FALSE; PRBool isScheme = PR_FALSE;
PRBool isSchemeFile = PR_FALSE;
if (NS_SUCCEEDED(uri->SchemeIs("ftp", &isScheme)) && isScheme) { if (NS_SUCCEEDED(uri->SchemeIs("ftp", &isScheme)) && isScheme) {
// ftp urls don't always end in a / // ftp urls don't always end in a /
@ -203,7 +204,7 @@ nsIndexedToHTML::OnStartRequest(nsIRequest* request, nsISupports *aContext) {
rv = uri->Resolve(NS_LITERAL_CSTRING(".."),parentStr); rv = uri->Resolve(NS_LITERAL_CSTRING(".."),parentStr);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
} }
} else if (NS_SUCCEEDED(uri->SchemeIs("file", &isScheme)) && isScheme) { } else if (NS_SUCCEEDED(uri->SchemeIs("file", &isSchemeFile)) && isSchemeFile) {
nsCOMPtr<nsIFileURL> fileUrl = do_QueryInterface(uri); nsCOMPtr<nsIFileURL> fileUrl = do_QueryInterface(uri);
nsCOMPtr<nsIFile> file; nsCOMPtr<nsIFile> file;
rv = fileUrl->GetFile(getter_AddRefs(file)); rv = fileUrl->GetFile(getter_AddRefs(file));
@ -226,13 +227,8 @@ nsIndexedToHTML::OnStartRequest(nsIRequest* request, nsISupports *aContext) {
parentStr.Assign(url); parentStr.Assign(url);
} }
// reset parser's charset to platform's default if this is file url // Directory index will be always encoded in UTF-8 if this is file url
nsCOMPtr<nsIPlatformCharset> platformCharset(do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv)); rv = mParser->SetEncoding("UTF-8");
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString charset;
rv = platformCharset->GetCharset(kPlatformCharsetSel_FileName, charset);
NS_ENSURE_SUCCESS(rv, rv);
rv = mParser->SetEncoding(charset.get());
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
} else if (NS_SUCCEEDED(uri->SchemeIs("gopher", &isScheme)) && isScheme) { } else if (NS_SUCCEEDED(uri->SchemeIs("gopher", &isScheme)) && isScheme) {
@ -304,8 +300,22 @@ nsIndexedToHTML::OnStartRequest(nsIRequest* request, nsISupports *aContext) {
nsXPIDLString unEscapeSpec; nsXPIDLString unEscapeSpec;
rv = mTextToSubURI->UnEscapeAndConvert(encoding, titleUri.get(), rv = mTextToSubURI->UnEscapeAndConvert(encoding, titleUri.get(),
getter_Copies(unEscapeSpec)); getter_Copies(unEscapeSpec));
// unescape may fail because
// 1. file URL may be encoded in platform charset for backward compatibility
// 2. query part may not be encoded in UTF-8 (see bug 261929)
// so try the platform's default if this is file url
if (NS_FAILED(rv) && isSchemeFile) {
nsCOMPtr<nsIPlatformCharset> platformCharset(do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, rv);
nsCAutoString charset;
rv = platformCharset->GetCharset(kPlatformCharsetSel_FileName, charset);
NS_ENSURE_SUCCESS(rv, rv);
rv = mTextToSubURI->UnEscapeAndConvert(charset.get(), titleUri.get(),
getter_Copies(unEscapeSpec));
}
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
nsXPIDLString htmlEscSpec; nsXPIDLString htmlEscSpec;
htmlEscSpec.Adopt(nsEscapeHTML2(unEscapeSpec.get(), htmlEscSpec.Adopt(nsEscapeHTML2(unEscapeSpec.get(),
unEscapeSpec.Length())); unEscapeSpec.Length()));
@ -501,7 +511,7 @@ nsIndexedToHTML::OnIndexAvailable(nsIRequest *aRequest,
mTextToSubURI = do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv); mTextToSubURI = do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
} }
nsXPIDLCString encoding; nsXPIDLCString encoding;
rv = mParser->GetEncoding(getter_Copies(encoding)); rv = mParser->GetEncoding(getter_Copies(encoding));
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
@ -510,7 +520,7 @@ nsIndexedToHTML::OnIndexAvailable(nsIRequest *aRequest,
rv = mTextToSubURI->UnEscapeAndConvert(encoding, loc, rv = mTextToSubURI->UnEscapeAndConvert(encoding, loc,
getter_Copies(unEscapeSpec)); getter_Copies(unEscapeSpec));
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
// need to escape links // need to escape links
nsCAutoString escapeBuf; nsCAutoString escapeBuf;