Bug 78148. Reorg directory viewer backend to allow file and gopher to use

the html view as well. (This is currently disabled for file because of
i18n issues)

Should also fix dirviewer bugs 38014, 68651, 72724, 78474, and part
of 83881.

r/sr=darin, dougt
This commit is contained in:
bbaetz%cs.mcgill.ca 2001-10-03 00:43:30 +00:00
Родитель a730dea42d
Коммит 0a07e3a5be
25 изменённых файлов: 835 добавлений и 1110 удалений

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

@ -33,6 +33,8 @@ REQUIRES = xpcom \
exthandler \
mimetype \
intl \
uconv \
locale \
pref \
$(NULL)

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

@ -25,6 +25,8 @@ REQUIRES = xpcom \
exthandler \
mimetype \
intl \
uconv \
locale \
pref \
$(NULL)
include <$(DEPTH)/config/config.mak>

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

@ -19,7 +19,7 @@
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Contributor(s): Bradley Baetz <bbaetz@cs.mcgill.ca>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -55,8 +55,29 @@
static PRLogModuleInfo* gLog;
#endif
#include "nsISimpleEnumerator.h"
#include "nsICollation.h"
#include "nsILocale.h"
#include "nsILocaleService.h"
#include "nsCollationCID.h"
#include "nsIPlatformCharset.h"
#include "nsReadableUtils.h"
static NS_DEFINE_CID(kCollationFactoryCID, NS_COLLATIONFACTORY_CID);
// NOTE: This runs on the _file transport_ thread.
// 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
// is threadsafe, and stuff like GetUnicodeLeafName spews warnings on a debug
// build, because the singletons were initialised on the UI thread.
// So THIS CODE IS ASCII ONLY!!!!!!!! This is no worse than the current
// behaviour, though. See bug 99382.
// When this is fixed, #define THREADSAFE_I18N to get this code working
//#define THREADSAFE_I18N
nsDirectoryIndexStream::nsDirectoryIndexStream()
: mOffset(0)
: mOffset(0), mPos(0)
{
NS_INIT_REFCNT();
@ -69,6 +90,52 @@ nsDirectoryIndexStream::nsDirectoryIndexStream()
("nsDirectoryIndexStream[%p]: created", this));
}
static int PR_CALLBACK compare(const void* aElement1,
const void* aElement2,
void* aData)
{
nsIFile* a = (nsIFile*)aElement1;
nsIFile* b = (nsIFile*)aElement2;
// Not that this #ifdef makes much of a difference... We need it
// to work out which version of GetLeafName to use, though
#ifdef THREADSAFE_I18N
// don't check for errors, because we can't report them anyway
nsXPIDLString name1, name2;
a->GetUnicodeLeafName(getter_Copies(name1));
b->GetUnicodeLeafName(getter_Copies(name2));
// Note - we should be the collation to do sorting. Why don't we?
// Because that is _slow_. Using TestProtocols to list file:///dev/
// goes from 3 seconds to 22. (This may be why nsXULSortService is
// so slow as well).
// Does this have bad effects? Probably, but since nsXULOutliner appears
// to use the raw RDF literal value as the sort key (which ammounts to an
// strcmp), it won't be any worse, I think.
// This could be made faster, by creating the keys once,
// but CompareString could still be smarter - see bug 99383 - bbaetz
// 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
// struct { nsIFile*, PRUint8* } with the pre-calculated key.
return Compare(name1, name2);
/*PRInt32 res;
// CompareString takes an nsString...
nsString str1(name1);
nsString str2(name2);
nsICollation* coll = (nsICollation*)aData;
coll->CompareString(kCollationStrengthDefault, str1, str2, &res);
return res;*/
#else
nsXPIDLCString name1, name2;
a->GetLeafName(getter_Copies(name1));
b->GetLeafName(getter_Copies(name2));
return Compare(name1, name2);
#endif
}
nsresult
nsDirectoryIndexStream::Init(nsIFile* aDir)
{
@ -90,19 +157,99 @@ nsDirectoryIndexStream::Init(nsIFile* aDir)
}
#endif
mDir = aDir;
#ifdef THREADSAFE_I18N
if (!mTextToSubURI) {
mTextToSubURI = do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
}
#endif
mDir = aDir;
// Sigh. We have to allocate on the heap because there are no
// assignment operators defined.
rv = mDir->GetDirectoryEntries(getter_AddRefs(mIter));
nsCOMPtr<nsISimpleEnumerator> iter;
rv = mDir->GetDirectoryEntries(getter_AddRefs(iter));
if (NS_FAILED(rv)) return rv;
mBuf = "200: filename content-length last-modified file-type\n";
// Now lets sort, because clients expect it that way
// XXX - should we do so here, or when the first item is requested?
// XXX - use insertion sort instead?
PRBool more;
nsCOMPtr<nsISupports> elem;
while (NS_SUCCEEDED(iter->HasMoreElements(&more)) && more) {
rv = iter->GetNext(getter_AddRefs(elem));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIFile> file = do_QueryInterface(elem);
if (file) {
nsIFile* f = file;
NS_ADDREF(f);
mArray.AppendElement(f);
}
}
#ifdef THREADSAFE_I18N
nsCOMPtr<nsILocaleService> ls = do_GetService(NS_LOCALESERVICE_CONTRACTID,
&rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsILocale> locale;
rv = ls->GetApplicationLocale(getter_AddRefs(locale));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsICollationFactory> cf = do_CreateInstance(kCollationFactoryCID,
&rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsICollation> coll;
rv = cf->CreateCollation(locale, getter_AddRefs(coll));
if (NS_FAILED(rv)) return rv;
mArray.Sort(compare, coll);
#else
mArray.Sort(compare, nsnull);
#endif
mBuf.Append("300: ");
nsXPIDLCString url;
rv = mDir->GetURL(getter_Copies(url));
if (NS_FAILED(rv)) return rv;
mBuf.Append(url);
mBuf.Append('\n');
mBuf.Append("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;
mFSCharset.Adopt(ToNewCString(tmp));
#else
mFSCharset.Adopt(nsCRT::strdup("ISO-8859-1"));
#endif
}
mBuf.Append("301: ");
mBuf.Append(mFSCharset);
mBuf.Append('\n');
return NS_OK;
}
nsDirectoryIndexStream::~nsDirectoryIndexStream()
{
PRInt32 i;
for (i=0; i<mArray.Count(); ++i) {
nsIFile* elem = (nsIFile*)mArray.ElementAt(i);
NS_RELEASE(elem);
}
PR_LOG(gLog, PR_LOG_DEBUG,
("nsDirectoryIndexStream[%p]: destroyed", this));
}
@ -126,8 +273,9 @@ nsDirectoryIndexStream::Create(nsIFile* aDir, nsIInputStream** aResult)
return NS_OK;
}
NS_IMPL_ISUPPORTS1(nsDirectoryIndexStream, nsIInputStream)
NS_IMPL_THREADSAFE_ISUPPORTS1(nsDirectoryIndexStream, nsIInputStream)
// The below routines are proxied to the UI thread!
NS_IMETHODIMP
nsDirectoryIndexStream::Close()
{
@ -139,9 +287,7 @@ nsDirectoryIndexStream::Available(PRUint32* aLength)
{
// Lie, and tell the caller that the stream is endless (until we
// actually don't have anything left).
PRBool more;
nsresult rv = mIter->HasMoreElements(&more);
if (NS_FAILED(rv)) return rv;
PRBool more = mPos < mArray.Count();
if (more) {
*aLength = PRUint32(-1);
return NS_OK;
@ -172,15 +318,11 @@ nsDirectoryIndexStream::Read(char* aBuf, PRUint32 aCount, PRUint32* aReadCount)
// Okay, now we'll suck stuff off of our iterator into the mBuf...
while (PRUint32(mBuf.Length()) < aCount) {
PRBool more;
nsresult rv = mIter->HasMoreElements(&more);
if (NS_FAILED(rv)) return rv;
PRBool more = mPos < mArray.Count();
if (!more) break;
nsCOMPtr<nsISupports> cur;
rv = mIter->GetNext(getter_AddRefs(cur));
nsCOMPtr<nsIFile> current = do_QueryInterface(cur, &rv);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIFile> current = (nsIFile*)mArray.ElementAt(mPos);
++mPos;
#ifdef PR_LOGGING
if (PR_LOG_TEST(gLog, PR_LOG_DEBUG)) {
@ -193,6 +335,9 @@ nsDirectoryIndexStream::Read(char* aBuf, PRUint32 aCount, PRUint32* aReadCount)
#endif
// rjc: don't return hidden files/directories!
// bbaetz: why not?
nsresult rv;
#ifndef XP_UNIX
PRBool hidden;
rv = current->IsHidden(&hidden);
if (NS_FAILED(rv)) return rv;
@ -202,34 +347,53 @@ nsDirectoryIndexStream::Read(char* aBuf, PRUint32 aCount, PRUint32* aReadCount)
this));
continue;
}
PRInt64 fileSize;
PRInt64 fileInfoModifyTime;
rv = current->GetFileSize( &fileSize );
if (NS_FAILED(rv)) return rv;
PROffset32 fileInfoSize;
LL_L2I( fileInfoSize,fileSize );
rv = current->GetLastModificationDate( &fileInfoModifyTime );
if (NS_FAILED(rv)) return rv;
mBuf += "201: ";
#endif
// The "filename" field
{
char* leafname;
rv = current->GetLeafName(&leafname);
if (NS_FAILED(rv)) return rv;
if (leafname) {
char* escaped = nsEscape(leafname, url_Path);
if (escaped) {
mBuf += escaped;
mBuf.Append(' ');
nsCRT::free(escaped);
}
nsCRT::free(leafname);
PRInt64 fileSize;
rv = current->GetFileSize( &fileSize );
if (NS_FAILED(rv)) return rv;
PROffset32 fileInfoSize;
LL_L2I( fileInfoSize,fileSize );
PRInt64 tmpTime, fileInfoModifyTime;
rv = current->GetLastModificationDate( &tmpTime );
// Why does nsIFile give this back in milliseconds?
LL_MUL(fileInfoModifyTime, tmpTime, PR_USEC_PER_MSEC);
if (NS_FAILED(rv)) return rv;
mBuf += "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
nsXPIDLCString leafname;
rv = current->GetLeafName(getter_Copies(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
mBuf.AppendInt(fileInfoSize, 10);

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

@ -42,7 +42,8 @@
#include "nsString.h"
#include "nsIInputStream.h"
#include "nsCOMPtr.h"
#include "nsISimpleEnumerator.h"
#include "nsVoidArray.h"
#include "nsITextToSubURI.h"
class nsDirectoryIndexStream : public nsIInputStream
{
@ -51,7 +52,13 @@ protected:
PRInt32 mOffset;
nsCOMPtr<nsIFile> mDir;
nsCOMPtr<nsISimpleEnumerator> mIter;
PRInt32 mPos;
nsVoidArray mArray;
// XXX - we could make these statics, and share them. But we're only going to have one
// of directoryindexstream at once, so theres no point
nsXPIDLCString mFSCharset;
nsCOMPtr<nsITextToSubURI> mTextToSubURI;
nsDirectoryIndexStream();
nsresult Init(nsIFile* aDir);

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

@ -40,6 +40,7 @@ REQUIRES = xpcom \
jar \
locale \
intl \
uconv \
$(ZLIB_REQUIRES) \
$(NULL)

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

@ -33,6 +33,7 @@ REQUIRES = xpcom \
jar \
locale \
intl \
uconv \
zlib \
$(NULL)

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

@ -90,12 +90,16 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMIMEInfoImpl)
#include "nsStreamProviderProxy.h"
#include "nsSimpleStreamListener.h"
#include "nsSimpleStreamProvider.h"
#include "nsDirIndexParser.h"
#include "nsDirIndex.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsRequestObserverProxy)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsStreamListenerProxy)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsStreamProviderProxy)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSimpleStreamListener)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSimpleStreamProvider)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsDirIndexParser, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDirIndex)
///////////////////////////////////////////////////////////////////////////////
@ -752,7 +756,13 @@ static nsModuleComponentInfo gNetModuleInfo[] = {
NS_ISTREAMCONVERTER_KEY INDEX_TO_HTML,
nsIndexedToHTML::Create
},
{ "Directory Index Parser",
NS_DIRINDEXPARSER_CID,
NS_DIRINDEXPARSER_CONTRACTID,
nsDirIndexParserConstructor
},
{ "MultiMixedConverter",
NS_MULTIMIXEDCONVERTER_CID,
NS_ISTREAMCONVERTER_KEY MULTI_MIXED_X,
@ -832,6 +842,13 @@ static nsModuleComponentInfo gNetModuleInfo[] = {
NS_ISTREAMCONVERTER_KEY,
CreateNewTXTToHTMLConvFactory
},
{ "Directory Index",
NS_DIRINDEX_CID,
"@mozilla.org/dirIndex;1",
nsDirIndexConstructor
},
#if defined(OLD_CACHE)
// from netwerk/cache:
{ "Memory Cache", NS_MEM_CACHE_FACTORY_CID, NS_NETWORK_MEMORY_CACHE_CONTRACTID, nsMemCacheConstructor },

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

@ -373,11 +373,10 @@ nsFtpState::nsFtpState() {
mControlConnection = nsnull;
mDRequestForwarder = nsnull;
mGenerateRawContent = mGenerateHTMLContent = PR_FALSE;
mGenerateRawContent = PR_FALSE;
nsresult rv;
nsCOMPtr<nsIPref> pPref(do_GetService(kPrefCID, &rv));
if (NS_SUCCEEDED(rv) || pPref) {
pPref->GetBoolPref("network.dir.generate_html", &mGenerateHTMLContent);
pPref->GetBoolPref("network.ftp.raw_output", &mGenerateRawContent);
}
}
@ -1232,9 +1231,6 @@ nsFtpState::SetContentType()
return mChannel->SetContentType(contentType);
}
if (mGenerateHTMLContent)
return mChannel->SetContentType("text/html");
return mChannel->SetContentType("application/http-index-format");
}
@ -2022,13 +2018,6 @@ nsFtpState::BuildStreamConverter(nsIStreamListener** convertStreamListener)
if (mGenerateRawContent) {
converterListener = listener;
}
else if (mGenerateHTMLContent) {
rv = scs->AsyncConvertData(fromStr.get(),
NS_LITERAL_STRING("text/html").get(),
listener,
mURL,
getter_AddRefs(converterListener));
}
else
{
rv = scs->AsyncConvertData(fromStr.get(),

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

@ -209,7 +209,6 @@ private:
nsCOMPtr<nsIInputStream> mWriteStream; // This stream is written to the server.
PRPackedBool mFireCallbacks; // Fire the listener callback.
PRPackedBool mIPv6Checked;
PRBool mGenerateHTMLContent;
PRBool mGenerateRawContent;
nsCOMPtr<nsIPrompt> mPrompter;
nsCOMPtr<nsIFTPEventSink> mFTPEventSink;

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

@ -34,6 +34,7 @@ REQUIRES = xpcom \
locale \
util \
pref \
uconv \
exthandler \
$(ZLIB_REQUIRES) \
$(NULL)
@ -51,6 +52,8 @@ CPPSRCS = \
nsHTTPChunkConv.cpp \
nsHTTPCompressConv.cpp \
nsTXTToHTMLConv.cpp \
nsDirIndex.cpp \
nsDirIndexParser.cpp \
nsIndexedToHTML.cpp \
nsBinHexDecoder.cpp \
$(NULL)

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

@ -27,6 +27,7 @@ REQUIRES = xpcom \
util \
pref \
exthandler \
uconv \
zlib \
$(NULL)
include <$(DEPTH)/config/config.mak>
@ -49,6 +50,8 @@ CPP_OBJS = \
.\$(OBJDIR)\nsHTTPCompressConv.obj \
.\$(OBJDIR)\nsUnknownDecoder.obj \
.\$(OBJDIR)\nsTXTToHTMLConv.obj \
.\$(OBJDIR)\nsDirIndex.obj \
.\$(OBJDIR)\nsDirIndexParser.obj \
.\$(OBJDIR)\nsIndexedToHTML.obj \
.\$(OBJDIR)\nsBinHexDecoder.obj \
$(NULL)

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

@ -19,7 +19,7 @@
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Contributor(s): Bradley Baetz <bbaetz@cs.mcgill.ca>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -1030,8 +1030,12 @@ nsFTPDirListingConv::DigestBufferLines(char *aBuffer, nsCAutoString &aString) {
// MODIFIED DATE
char buffer[256] = "";
// Note: The below is the RFC822/1123 format, as required by
// the application/http-index-format specs
// viewers of such a format can then reformat this into the
// current locale (or anything else they choose)
PR_FormatTimeUSEnglish(buffer, sizeof(buffer),
"%m/%d/%y %I:%M:%S %p", &thisEntry->mMDTM );
"%a, %d %b %Y %H:%M:%S GMT", &thisEntry->mMDTM );
char *escapedDate = nsEscape(buffer, url_Path);
aString.Append(escapedDate);

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

@ -19,7 +19,7 @@
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Contributor(s): Bradley Baetz <bbaetz@cs.mcgill.ca>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -39,17 +39,38 @@
#include "nsNetUtil.h"
#include "nsIStringStream.h"
#include "nsEscape.h"
#include "nsIDirIndex.h"
#include "prtime.h"
#include "nsDateTimeFormatCID.h"
NS_IMPL_THREADSAFE_ISUPPORTS3(nsIndexedToHTML,
NS_IMPL_THREADSAFE_ISUPPORTS4(nsIndexedToHTML,
nsIDirIndexListener,
nsIStreamConverter,
nsIRequestObserver,
nsIStreamListener);
nsIStreamListener)
static NS_DEFINE_CID(kDateTimeFormatCID, NS_DATETIMEFORMAT_CID);
NS_IMETHODIMP
nsIndexedToHTML::Convert(nsIInputStream *aFromStream,
const PRUnichar *aFromType, const PRUnichar *aToType,
nsISupports *aCtxt, nsIInputStream * *_retval) {
nsIndexedToHTML::Init(nsIStreamListener* aListener) {
nsresult rv = NS_OK;
mListener = aListener;
nsCOMPtr<nsILocaleService> localeServ = do_GetService(NS_LOCALESERVICE_CONTRACTID);
localeServ->GetApplicationLocale(getter_AddRefs(mLocale));
mDateTime = do_CreateInstance(kDateTimeFormatCID, &rv);
return rv;
}
NS_IMETHODIMP
nsIndexedToHTML::Convert(nsIInputStream* aFromStream,
const PRUnichar* aFromType,
const PRUnichar* aToType,
nsISupports* aCtxt,
nsIInputStream** res) {
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -58,48 +79,93 @@ nsIndexedToHTML::AsyncConvertData(const PRUnichar *aFromType,
const PRUnichar *aToType,
nsIStreamListener *aListener,
nsISupports *aCtxt) {
NS_ASSERTION(aListener, "null pointer");
mListener = aListener;
return NS_OK;
return Init(aListener);
}
NS_IMETHODIMP
nsIndexedToHTML::OnStartRequest(nsIRequest* request, nsISupports *aContext)
{
nsIndexedToHTML::OnStartRequest(nsIRequest* request, nsISupports *aContext) {
nsresult rv;
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
nsCOMPtr<nsIURI> uri;
channel->GetURI(getter_AddRefs(uri));
uri->GetPath(getter_Copies(mCurrentPath));
rv = channel->GetURI(getter_AddRefs(uri));
if (NS_FAILED(rv)) return rv;
nsString buffer;
// buffer.AssignWithConversion("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">");
buffer.AssignWithConversion("");
mParser = do_CreateInstance("@mozilla.org/dirIndexParser;1",&rv);
if (NS_FAILED(rv)) return rv;
rv = mParser->SetListener(this);
if (NS_FAILED(rv)) return rv;
buffer.AppendWithConversion("<html>\n<head><title> Index of "); //FIX i18n.
buffer.AppendWithConversion(mCurrentPath);
buffer.StripChar('/', buffer.Length() - 1);
buffer.AppendWithConversion("</title></head>\n<body><pre>\n");
rv = mParser->OnStartRequest(request, aContext);
if (NS_FAILED(rv)) return rv;
buffer.AppendWithConversion("<H1> Index of "); //FIX i18n.
buffer.AppendWithConversion(mCurrentPath);
buffer.AppendWithConversion("</H1>\n");
buffer.AppendWithConversion("<hr><table border=0>\n");
nsXPIDLCString tmp;
rv = uri->GetSpec(getter_Copies(tmp));
if (NS_FAILED(rv)) return rv;
nsAutoString baseUri;
baseUri.AssignWithConversion(tmp);
nsXPIDLCString scheme;
rv = uri->GetScheme(getter_Copies(scheme));
if (NS_FAILED(rv)) return rv;
nsString buffer;
buffer.AssignWithConversion("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n");
// Anything but a gopher url needs to end in a /,
// otherwise we end up linking to file:///foo/dirfile
const char gopherProt[] = "gopher";
if (nsCRT::strncmp(scheme.get(),gopherProt,sizeof(gopherProt)-1)) {
PRUnichar sep;
const char fileProt[] = "file";
if (!nsCRT::strncmp(scheme.get(),fileProt,sizeof(fileProt)-1)) {
// How do I do this in an XP way???
#ifdef XP_MAC
sep = ':';
#else
sep = '/';
#endif
} else {
sep = '/';
}
if (baseUri[baseUri.Length()-1] != sep) {
baseUri.Append(sep);
}
}
char* spec = nsCRT::strdup(tmp.get());
nsUnescape(spec);
buffer.Append(NS_LITERAL_STRING("<html>\n<head><title>Index of ")); //FIX i18n.
buffer.AppendWithConversion(spec);
buffer.Append(NS_LITERAL_STRING("</title><base href=\""));
buffer.Append(baseUri);
buffer.Append(NS_LITERAL_STRING("\">\n"));
nsXPIDLCString encoding;
rv = mParser->GetEncoding(getter_Copies(encoding));
if (NS_SUCCEEDED(rv)) {
buffer.Append(NS_LITERAL_STRING("<meta http-equiv=\"Content-Type\" content=\"text/html; charset="));
buffer.AppendWithConversion(encoding);
buffer.Append(NS_LITERAL_STRING("\">\n"));
}
buffer.Append(NS_LITERAL_STRING("</head>\n<body><pre>\n"));
buffer.Append(NS_LITERAL_STRING("<H1> Index of ")); //FIX i18n.
char* escaped = nsEscapeHTML(spec);
buffer.AppendWithConversion(escaped);
nsMemory::Free(escaped);
buffer.Append(NS_LITERAL_STRING("</H1>\n"));
buffer.Append(NS_LITERAL_STRING("<hr><table border=0>\n"));
// buffer.AppendWithConversion("<tr><th>Name</th><th>Size</th><th>Last modified</th><th>Description</th></tr>\n"); //FIX i18n.
const char * path = mCurrentPath.get();
if (path && *path && path[1] != '\0')
{
buffer.AppendWithConversion("<tr>\n <td><a HREF=\"");
buffer.AppendWithConversion(mCurrentPath);
buffer.StripChar('/', buffer.Length() - 1);
buffer.AppendWithConversion("/../\"> ..</a></td>\n");
}
// Push buffer to the listener now, so the initial HTML will not
// be parsed in OnDataAvailable().
nsresult rv = mListener->OnStartRequest(request, aContext);
rv = mListener->OnStartRequest(request, aContext);
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIInputStream> inputData;
@ -108,10 +174,9 @@ nsIndexedToHTML::OnStartRequest(nsIRequest* request, nsISupports *aContext)
if (NS_FAILED(rv)) return rv;
inputData = do_QueryInterface(inputDataSup);
rv = mListener->OnDataAvailable(request, aContext,
inputData, 0, buffer.Length());
if (NS_FAILED(rv)) return rv;
buffer.AssignWithConversion("");
return rv;
}
@ -120,170 +185,130 @@ nsIndexedToHTML::OnStopRequest(nsIRequest* request, nsISupports *aContext,
nsresult aStatus) {
nsresult rv = NS_OK;
nsString buffer;
buffer.AssignWithConversion("</table><hr></pre></body></html>\n");
buffer.Assign(NS_LITERAL_STRING("</table><hr></pre></body></html>\n"));
nsCOMPtr<nsIInputStream> inputData;
nsCOMPtr<nsISupports> inputDataSup;
rv = NS_NewStringInputStream(getter_AddRefs(inputDataSup), buffer);
if (NS_FAILED(rv)) return rv;
inputData = do_QueryInterface(inputDataSup);
rv = mListener->OnDataAvailable(request, aContext,
inputData, 0, buffer.Length());
if (NS_FAILED(rv)) return rv;
rv = mParser->OnStopRequest(request, aContext, aStatus);
if (NS_FAILED(rv)) return rv;
mParser = 0;
return mListener->OnStopRequest(request, aContext, aStatus);
}
nsresult
nsIndexedToHTML::Handle201(char* buffer, nsString &pushBuffer)
{
// buffer should be in the format:
// filename content-length last-modified file-type
if (buffer == nsnull)
return NS_ERROR_NULL_POINTER;
char* bufferOffset = nsnull;
if (*buffer == '\"') {
buffer++;
bufferOffset = PL_strchr((const char*)buffer, '\"');
} else {
bufferOffset = PL_strchr((const char*)buffer, ' ');
}
if (bufferOffset == nsnull)
return NS_ERROR_FAILURE;
*bufferOffset = '\0';
nsCString filename(buffer);
++bufferOffset;
pushBuffer.AppendWithConversion("<tr>\n <td>");
pushBuffer.AppendWithConversion("<a HREF=\"");
const char * path = mCurrentPath.get();
if (path && *path && path[1] != '\0') {
pushBuffer.AppendWithConversion(mCurrentPath);
pushBuffer.StripChar('/', pushBuffer.Length() - 1);
}
pushBuffer.AppendWithConversion("/");
pushBuffer.AppendWithConversion(filename);
pushBuffer.AppendWithConversion("\"> ");
nsUnescape(NS_CONST_CAST(char*, filename.get()));
pushBuffer.AppendWithConversion(filename);
pushBuffer.AppendWithConversion("</a>");
pushBuffer.AppendWithConversion("</td>\n");
while (*bufferOffset)
{
char* bufferStart = bufferOffset;
if (*bufferStart == '\"') {
bufferStart++;
bufferOffset = PL_strchr((const char*)bufferStart, '\"');
} else {
bufferOffset = PL_strchr((const char*)bufferStart, ' ');
}
if (bufferOffset == nsnull)
return NS_ERROR_FAILURE;
*bufferOffset = '\0';
++bufferOffset;
nsUnescape(bufferStart);
nsCString cstring(bufferStart);
cstring.ToLowerCase();
pushBuffer.AppendWithConversion(" <td>");
pushBuffer.AppendWithConversion(cstring);
pushBuffer.AppendWithConversion("</td>\n");
}
pushBuffer.AppendWithConversion("</tr>");
pushBuffer.AppendWithConversion(CRLF);
// nsCString x; x.AssignWithConversion(pushBuffer);
// printf("/n/n%s/n/n", (const char*)x);
return NS_OK;
NS_IMETHODIMP
nsIndexedToHTML::OnDataAvailable(nsIRequest *aRequest,
nsISupports *aCtxt,
nsIInputStream* aInput,
PRUint32 aOffset,
PRUint32 aCount) {
return mParser->OnDataAvailable(aRequest, aCtxt, aInput, aOffset, aCount);
}
#define NSINDEXTOHTML_BUFFER_SIZE 4096
NS_IMETHODIMP
nsIndexedToHTML::OnDataAvailable(nsIRequest* request, nsISupports *aContext,
nsIInputStream *aInStream,
PRUint32 aOffset, PRUint32 aCount)
{
nsresult rv = NS_OK;
nsIndexedToHTML::OnIndexAvailable(nsIRequest *aRequest,
nsISupports *aCtxt,
nsIDirIndex *aIndex) {
if (!aIndex)
return NS_ERROR_NULL_POINTER;
nsString pushBuffer;
pushBuffer.Append(NS_LITERAL_STRING("<tr>\n <td>"));
pushBuffer.Append(NS_LITERAL_STRING("<a HREF=\""));
char buffer[NSINDEXTOHTML_BUFFER_SIZE+1];
char* startOffset = nsnull;
char* endOffset = nsnull;
nsXPIDLCString loc;
aIndex->GetLocation(getter_Copies(loc));
pushBuffer.AppendWithConversion(loc);
while (aCount)
{
PRUint32 read = 0;
rv = aInStream->Read(buffer, NSINDEXTOHTML_BUFFER_SIZE, &read);
if (NS_FAILED(rv)) return rv;
pushBuffer.Append(NS_LITERAL_STRING("\"> <img border=\"0\" align=\"absbottom\" src=\""));
buffer[read] = '\0';
aCount -= read;
startOffset = (char*)&buffer;
PRUint32 type;
aIndex->GetType(&type);
switch (type) {
case nsIDirIndex::TYPE_DIRECTORY:
case nsIDirIndex::TYPE_SYMLINK:
pushBuffer.Append(NS_LITERAL_STRING("internal-gopher-menu"));
break;
case nsIDirIndex::TYPE_FILE:
case nsIDirIndex::TYPE_UNKNOWN:
pushBuffer.Append(NS_LITERAL_STRING("internal-gopher-unknown"));
break;
}
pushBuffer.Append(NS_LITERAL_STRING("\"> "));
while (startOffset)
{
// TODO: we should handle the 200 line. For now,
// we assume that it contains:
//
// 200: filename content-length last-modified file-type\n
nsXPIDLString tmp;
aIndex->GetDescription(getter_Copies(tmp));
PRUnichar* escaped = nsEscapeHTML2(tmp.get(), tmp.Length());
pushBuffer.Append(escaped);
nsMemory::Free(escaped);
pushBuffer.Append(NS_LITERAL_STRING("</a>"));
pushBuffer.Append(NS_LITERAL_STRING("</td>\n"));
// Look for a line begining with "201: "
startOffset = PL_strstr((const char*)startOffset, "201: ");
if (startOffset == nsnull)
break;
pushBuffer.Append(NS_LITERAL_STRING(" <td>"));
endOffset = PL_strchr((const char*)startOffset, '\n');
if (endOffset == nsnull)
break;
*endOffset = '\0';
rv = Handle201(startOffset + 5, pushBuffer);
if (NS_FAILED(rv)) return rv;
startOffset = ++endOffset;
}
PRUint32 size;
aIndex->GetSize(&size);
if (size != PRUint32(-1)) {
pushBuffer.AppendInt(size);
} else {
pushBuffer.Append(NS_LITERAL_STRING("&nbsp;"));
}
if (!pushBuffer.IsEmpty()) {
nsCOMPtr<nsIInputStream> inputData;
nsCOMPtr<nsISupports> inputDataSup;
rv = NS_NewStringInputStream(getter_AddRefs(inputDataSup), pushBuffer);
pushBuffer.Append(NS_LITERAL_STRING("</td>\n"));
if (NS_FAILED(rv))
return rv;
pushBuffer.Append(NS_LITERAL_STRING(" <td>"));
inputData = do_QueryInterface(inputDataSup);
rv = mListener->OnDataAvailable(request,
aContext,
inputData,
0,
pushBuffer.Length());
PRTime t;
aIndex->GetLastModified(&t);
if (t == -1) {
pushBuffer.Append(NS_LITERAL_STRING("&nbsp;"));
} else {
nsAutoString formatted;
mDateTime->FormatPRTime(mLocale,
kDateFormatShort,
kTimeFormatSeconds,
t,
formatted);
pushBuffer.Append(formatted);
}
pushBuffer.Append(NS_LITERAL_STRING("</td>\n"));
pushBuffer.Append(NS_LITERAL_STRING("</tr>\n"));
nsCOMPtr<nsIInputStream> inputData;
nsCOMPtr<nsISupports> inputDataSup;
nsresult rv = NS_NewStringInputStream(getter_AddRefs(inputDataSup),
pushBuffer);
if (NS_FAILED(rv))
return rv;
inputData = do_QueryInterface(inputDataSup);
rv = mListener->OnDataAvailable(aRequest,
aCtxt,
inputData,
0,
pushBuffer.Length());
return rv;
}
}
nsIndexedToHTML::nsIndexedToHTML() {
NS_INIT_REFCNT();

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

@ -44,23 +44,29 @@
#include "nsString.h"
#include "nsIStreamConverter.h"
#include "nsXPIDLString.h"
#include "nsIDirIndexListener.h"
#include "nsILocaleService.h"
#include "nsIDateTimeFormat.h"
#define NS_NSINDEXEDTOHTMLCONVERTER_CID \
{ 0xcf0f71fd, 0xfafd, 0x4e2b, {0x9f, 0xdc, 0x13, 0x4d, 0x97, 0x2e, 0x16, 0xe2} }
class nsIndexedToHTML : public nsIStreamConverter
class nsIndexedToHTML : public nsIStreamConverter,
public nsIDirIndexListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMCONVERTER
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIDIRINDEXLISTENER
nsIndexedToHTML();
virtual ~nsIndexedToHTML();
// For factory creation.
nsresult Init(nsIStreamListener *aListener);
static NS_METHOD
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) {
nsresult rv;
@ -76,10 +82,11 @@ public:
}
protected:
nsresult Handle201(char* buffer, nsString &pushBuffer);
nsCOMPtr<nsIDirIndexParser> mParser;
nsCOMPtr<nsIStreamListener> mListener; // final listener (consumer)
nsXPIDLCString mCurrentPath;
nsCOMPtr<nsILocale> mLocale;
nsCOMPtr<nsIDateTimeFormat> mDateTime;
};
#endif

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

@ -34,6 +34,8 @@ XPIDLSRCS = \
nsIStreamConverterService.idl \
mozITXTToHTMLConv.idl \
nsITXTToHTMLConv.idl \
nsIDirIndex.idl \
nsIDirIndexListener.idl \
$(NULL)
include $(topsrcdir)/config/rules.mk

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

@ -1,40 +0,0 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
MODULE = necko
XPIDL_MODULE = necko_strconv
DEPTH = ..\..\..
XPIDLSRCS = \
.\nsIStreamConverter.idl \
.\nsIStreamConverterService.idl \
.\mozITXTToHTMLConv.idl \
.\nsITXTToHTMLConv.idl \
$(NULL)
include <$(DEPTH)/config/rules.mak>
$(DEPTH)\netwerk\dist\include:
-mkdir $(DEPTH)\netwerk\dist
-mkdir $(DEPTH)\netwerk\dist\include

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

@ -37,6 +37,7 @@ REQUIRES = xpcom \
content \
rdf \
necko \
necko2 \
timer \
intl \
locale \

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

@ -28,6 +28,7 @@ REQUIRES = xpcom \
layout \
rdf \
necko \
necko2 \
timer \
intl \
locale \

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

@ -98,6 +98,14 @@ RegisterProc(nsIComponentManager *aCompMgr,
PR_TRUE,
PR_TRUE,
getter_Copies(previous));
if (NS_FAILED(rv)) return rv;
rv = catman->AddCategoryEntry("Gecko-Content-Viewers", "application/http-index-format; x-view-type=view-source",
NS_DOCUMENT_LOADER_FACTORY_CONTRACTID_PREFIX "view;1?type=application/http-index-format; x-view-type=view-source",
PR_TRUE,
PR_TRUE,
getter_Copies(previous));
return rv;
}
static NS_METHOD
@ -112,8 +120,12 @@ UnregisterProc(nsIComponentManager *aCompMgr,
rv = catman->DeleteCategoryEntry("Gecko-Content-Viewers",
"application/http-index-format", PR_TRUE);
if (NS_FAILED(rv)) return rv;
return NS_OK;
rv = catman->DeleteCategoryEntry("Gecko-Content-Viewers",
"application/http-index-format; x-view-type=view-source", PR_TRUE);
return rv;
}
static nsModuleComponentInfo components[] = {
@ -128,6 +140,9 @@ static nsModuleComponentInfo components[] = {
{ "Directory Viewer", NS_DIRECTORYVIEWERFACTORY_CID,
NS_DOCUMENT_LOADER_FACTORY_CONTRACTID_PREFIX "view;1?type=application/http-index-format",
nsDirectoryViewerFactoryConstructor, RegisterProc, UnregisterProc },
{ "Directory Viewer", NS_DIRECTORYVIEWERFACTORY_CID,
NS_DOCUMENT_LOADER_FACTORY_CONTRACTID_PREFIX "view;1?type=application/http-index-format; x-view-type=view-source",
nsDirectoryViewerFactoryConstructor }, // Let the standard type do the registration
{ "Directory Viewer", NS_HTTPINDEX_SERVICE_CID, NS_HTTPINDEX_SERVICE_CONTRACTID,
nsHTTPIndexConstructor },
{ "Directory Viewer", NS_HTTPINDEX_SERVICE_CID, NS_HTTPINDEX_DATASOURCE_CONTRACTID,

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

@ -45,6 +45,7 @@ REQUIRES = xpcom \
dom \
webshell \
uconv \
pref \
uriloader \
windowwatcher \
$(NULL)

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

@ -258,7 +258,7 @@ function OnClick(event, node)
if( tree.selectedItems.length == 1 ) {
var selectedItem = tree.selectedItems[0];
var url = selectedItem.getAttribute("URL");
window._content.location.href = url;
// set window title

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

@ -51,6 +51,7 @@ REQUIRES = xpcom \
dom \
webshell \
uconv \
pref \
uriloader \
windowwatcher \
content \
@ -79,4 +80,4 @@ install:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -52,7 +52,8 @@
#include "nsISupportsArray.h"
#include "nsIRDFLiteral.h"
#include "nsXPIDLString.h"
#include "nsIDirIndexListener.h"
#include "nsIFTPChannel.h"
class nsDirectoryViewerFactory : public nsIDocumentLoaderFactory
{
@ -67,7 +68,7 @@ public:
NS_IMETHOD CreateInstance(const char *aCommand,
nsIChannel* aChannel,
nsILoadGroup* aLoadGroup,
const char* aContentType,
const char* aContentType,
nsISupports* aContainer,
nsISupports* aExtraInfo,
nsIStreamListener** aDocListenerResult,
@ -80,21 +81,32 @@ public:
};
class nsHTTPIndex : public nsIHTTPIndex, public nsIRDFDataSource
class nsHTTPIndex : public nsIHTTPIndex,
public nsIRDFDataSource,
public nsIStreamListener,
public nsIDirIndexListener,
public nsIInterfaceRequestor,
public nsIFTPEventSink
{
private:
// note: these are NOT statics due to the native of nsHTTPIndex
// where it may or may not be treated as a singleton
nsIRDFResource *kNC_Child;
nsIRDFResource *kNC_loading;
nsIRDFResource *kNC_URL;
nsIRDFResource *kNC_IsContainer;
nsIRDFLiteral *kTrueLiteral;
nsIRDFLiteral *kFalseLiteral;
nsCOMPtr<nsIRDFResource> kNC_Child;
nsCOMPtr<nsIRDFResource> kNC_Comment;
nsCOMPtr<nsIRDFResource> kNC_Loading;
nsCOMPtr<nsIRDFResource> kNC_URL;
nsCOMPtr<nsIRDFResource> kNC_Description;
nsCOMPtr<nsIRDFResource> kNC_ContentLength;
nsCOMPtr<nsIRDFResource> kNC_LastModified;
nsCOMPtr<nsIRDFResource> kNC_ContentType;
nsCOMPtr<nsIRDFResource> kNC_FileType;
nsCOMPtr<nsIRDFResource> kNC_IsContainer;
nsCOMPtr<nsIRDFLiteral> kTrueLiteral;
nsCOMPtr<nsIRDFLiteral> kFalseLiteral;
nsCOMPtr<nsIRDFService> mDirRDF;
nsCOMPtr<nsIRDFService> mDirRDF;
protected:
// We grab a reference to the content viewer container (which
@ -103,21 +115,25 @@ protected:
// content viewer. We'll know that this has happened once we receive
// an OnStartRequest() notification
nsCOMPtr<nsIRDFDataSource> mInner;
nsCOMPtr<nsISupportsArray> mConnectionList;
nsCOMPtr<nsISupportsArray> mNodeList;
nsCOMPtr<nsITimer> mTimer;
nsISupports *mContainer; // [WEAK]
nsCString mBaseURL;
nsCString mEncoding;
nsCOMPtr<nsIRDFDataSource> mInner;
nsCOMPtr<nsISupportsArray> mConnectionList;
nsCOMPtr<nsISupportsArray> mNodeList;
nsCOMPtr<nsITimer> mTimer;
nsCOMPtr<nsIDirIndexParser> mParser;
nsCString mBaseURL;
nsCString mEncoding;
PRBool mBindToGlobalObject;
nsIInterfaceRequestor* mRequestor; // WEAK
nsCOMPtr<nsIRDFResource> mDirectory;
nsHTTPIndex(nsISupports* aContainer);
nsHTTPIndex(nsIInterfaceRequestor* aRequestor);
nsresult CommonInit(void);
nsresult Init(nsIURI* aBaseURL);
void GetDestination(nsIRDFResource* r, nsXPIDLCString& dest);
PRBool isWellknownContainerURI(nsIRDFResource *r);
// Get the destination of the nsIRDFResource
void GetDestination(nsIRDFResource *r, nsXPIDLCString& dest);
nsresult AddElement(nsIRDFResource *parent, nsIRDFResource *prop,
nsIRDFNode *child);
static void FireTimer(nsITimer* aTimer, void* aClosure);
public:
@ -125,7 +141,8 @@ public:
virtual ~nsHTTPIndex();
nsresult Init(void);
static nsresult Create(nsIURI* aBaseURI, nsISupports* aContainer, nsIHTTPIndex** aResult);
static nsresult Create(nsIURI* aBaseURI, nsIInterfaceRequestor* aContainer,
nsIHTTPIndex** aResult);
// nsIHTTPIndex interface
NS_DECL_NSIHTTPINDEX
@ -133,6 +150,13 @@ public:
// NSIRDFDataSource interface
NS_DECL_NSIRDFDATASOURCE
NS_DECL_NSIREQUESTOBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSIDIRINDEXLISTENER
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIFTPEVENTSINK
// nsISupports interface
NS_DECL_ISUPPORTS
};

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

@ -61,20 +61,10 @@ interface nsIHTTPIndex : nsISupports
*/
readonly attribute nsIRDFDataSource DataSource;
/**
* Create a stream listener that can be used to populate the HTTP index.
*/
nsIStreamListener CreateListener();
/**
* The charset to use for decoding FTP filenames
*/
attribute string encoding;
/**
* secret method to add parent<->child relationship(s)
*/
[noscript] void AddElement(in nsIRDFResource parent, in nsIRDFResource prop, in nsIRDFNode child);
};
%{C++