зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
79d9fd9989
Коммит
1c1fe64948
|
@ -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
|
#endif
|
||||||
|
|
||||||
PRInt64 fileSize = LL_Zero();
|
PRInt64 fileSize = 0;
|
||||||
current->GetFileSize( &fileSize );
|
current->GetFileSize( &fileSize );
|
||||||
|
|
||||||
PRInt64 tmpTime = LL_Zero();
|
PRInt64 fileInfoModifyTime = 0;
|
||||||
PRInt64 fileInfoModifyTime = LL_Zero();
|
current->GetLastModifiedTime( &fileInfoModifyTime );
|
||||||
current->GetLastModifiedTime( &tmpTime );
|
fileInfoModifyTime *= PR_USEC_PER_MSEC;
|
||||||
// Why does nsIFile give this back in milliseconds?
|
|
||||||
LL_MUL(fileInfoModifyTime, tmpTime, PR_USEC_PER_MSEC);
|
|
||||||
|
|
||||||
mBuf.AppendLiteral("201: ");
|
mBuf.AppendLiteral("201: ");
|
||||||
|
|
||||||
// The "filename" field
|
// The "filename" field
|
||||||
{
|
char* escaped = nsnull;
|
||||||
#ifdef THREADSAFE_I18N
|
if (!NS_IsNativeUTF8()) {
|
||||||
nsXPIDLString leafname;
|
nsAutoString leafname;
|
||||||
rv = current->GetUnicodeLeafName(getter_Copies(leafname));
|
rv = current->GetLeafName(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;
|
if (NS_FAILED(rv)) return rv;
|
||||||
mBuf.Append(escaped);
|
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(' ');
|
mBuf.Append(' ');
|
||||||
|
nsMemory::Free(escaped);
|
||||||
}
|
}
|
||||||
#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
|
|
||||||
}
|
|
||||||
|
|
||||||
// The "content-length" field
|
// The "content-length" field
|
||||||
mBuf.AppendInt(fileSize, 10);
|
mBuf.AppendInt(fileSize, 10);
|
||||||
|
|
|
@ -55,11 +55,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();
|
||||||
/**
|
/**
|
||||||
* aDir will only be used on the calling thread.
|
* aDir will only be used on the calling thread.
|
||||||
|
|
|
@ -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,6 +300,20 @@ 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;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче