зеркало из https://github.com/mozilla/gecko-dev.git
Fixes 95590 FTP: SYST limitations. Intergrates Cyrus Patel LIST Parser. r=dougt, sr=darin@Netscape.com.
This commit is contained in:
Родитель
898f7454be
Коммит
c7a5ce8c32
|
@ -251,9 +251,7 @@ nsresult NS_NewHTTPCompressConv (nsHTTPCompressConv ** result);
|
|||
nsresult NS_NewNSTXTToHTMLConv(nsTXTToHTMLConv** result);
|
||||
nsresult NS_NewStreamConv(nsStreamConverterService **aStreamConv);
|
||||
|
||||
#define FTP_UNIX_TO_INDEX "?from=text/ftp-dir-unix&to=application/http-index-format"
|
||||
#define FTP_NT_TO_INDEX "?from=text/ftp-dir-nt&to=application/http-index-format"
|
||||
#define FTP_OS2_TO_INDEX "?from=text/ftp-dir-os2&to=application/http-index-format"
|
||||
#define FTP_TO_INDEX "?from=text/ftp-dir&to=application/http-index-format"
|
||||
#define GOPHER_TO_INDEX "?from=text/gopher-dir&to=application/http-index-format"
|
||||
#define INDEX_TO_HTML "?from=application/http-index-format&to=text/html"
|
||||
#define MULTI_MIXED_X "?from=multipart/x-mixed-replace&to=*/*"
|
||||
|
@ -281,9 +279,7 @@ static PRUint32 g_StreamConverterCount = 16;
|
|||
#endif
|
||||
|
||||
static const char *const g_StreamConverterArray[] = {
|
||||
FTP_UNIX_TO_INDEX,
|
||||
FTP_NT_TO_INDEX,
|
||||
FTP_OS2_TO_INDEX,
|
||||
FTP_TO_INDEX,
|
||||
GOPHER_TO_INDEX,
|
||||
INDEX_TO_HTML,
|
||||
MULTI_MIXED_X,
|
||||
|
@ -772,19 +768,7 @@ static const nsModuleComponentInfo gNetModuleInfo[] = {
|
|||
// from netwerk/streamconv/converters:
|
||||
{ "FTPDirListingConverter",
|
||||
NS_FTPDIRLISTINGCONVERTER_CID,
|
||||
NS_ISTREAMCONVERTER_KEY FTP_UNIX_TO_INDEX,
|
||||
CreateNewFTPDirListingConv
|
||||
},
|
||||
|
||||
{ "FTPDirListingConverter",
|
||||
NS_FTPDIRLISTINGCONVERTER_CID,
|
||||
NS_ISTREAMCONVERTER_KEY FTP_NT_TO_INDEX,
|
||||
CreateNewFTPDirListingConv
|
||||
},
|
||||
|
||||
{ "FTPDirListingConverter",
|
||||
NS_FTPDIRLISTINGCONVERTER_CID,
|
||||
NS_ISTREAMCONVERTER_KEY FTP_OS2_TO_INDEX,
|
||||
NS_ISTREAMCONVERTER_KEY FTP_TO_INDEX,
|
||||
CreateNewFTPDirListingConv
|
||||
},
|
||||
|
||||
|
|
|
@ -1212,6 +1212,13 @@
|
|||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>ParseFTPList.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>mozTXTToHTMLConv.cpp</PATH>
|
||||
|
@ -1788,6 +1795,11 @@
|
|||
<PATH>nsFTPDirListingConv.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>ParseFTPList.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>mozTXTToHTMLConv.cpp</PATH>
|
||||
|
@ -3234,6 +3246,13 @@
|
|||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>ParseFTPList.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>mozTXTToHTMLConv.cpp</PATH>
|
||||
|
@ -3810,6 +3829,11 @@
|
|||
<PATH>nsFTPDirListingConv.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>ParseFTPList.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>mozTXTToHTMLConv.cpp</PATH>
|
||||
|
@ -5256,6 +5280,13 @@
|
|||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>ParseFTPList.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>mozTXTToHTMLConv.cpp</PATH>
|
||||
|
@ -5818,6 +5849,11 @@
|
|||
<PATH>nsFTPDirListingConv.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>ParseFTPList.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>mozTXTToHTMLConv.cpp</PATH>
|
||||
|
@ -7254,6 +7290,13 @@
|
|||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>ParseFTPList.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
<FILEKIND>Text</FILEKIND>
|
||||
<FILEFLAGS>Debug</FILEFLAGS>
|
||||
</FILE>
|
||||
<FILE>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>mozTXTToHTMLConv.cpp</PATH>
|
||||
|
@ -7816,6 +7859,11 @@
|
|||
<PATH>nsFTPDirListingConv.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>ParseFTPList.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>mozTXTToHTMLConv.cpp</PATH>
|
||||
|
@ -8568,6 +8616,12 @@
|
|||
<PATH>nsFTPDirListingConv.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<TARGETNAME>Necko.shlb</TARGETNAME>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
<PATH>ParseFTPList.cpp</PATH>
|
||||
<PATHFORMAT>MacOS</PATHFORMAT>
|
||||
</FILEREF>
|
||||
<FILEREF>
|
||||
<TARGETNAME>Necko.shlb</TARGETNAME>
|
||||
<PATHTYPE>Name</PATHTYPE>
|
||||
|
|
|
@ -1116,9 +1116,11 @@ nsFtpState::S_pass() {
|
|||
nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
|
||||
&passwd, &retval);
|
||||
|
||||
// we want to fail if the user canceled or didn't enter a password.
|
||||
if (!retval || (passwd && !*passwd) )
|
||||
// we want to fail if the user canceled. Note here that if they want
|
||||
// a blank password, we will pass it along.
|
||||
if (!retval)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
mPassword = passwd;
|
||||
}
|
||||
// XXX mPassword may contain non-ASCII characters! what do we do?
|
||||
|
@ -1255,7 +1257,6 @@ nsFtpState::R_syst() {
|
|||
// since we just alerted the user, clear mResponseMsg,
|
||||
// which is displayed to the user.
|
||||
mResponseMsg = "";
|
||||
|
||||
return FTP_ERROR;
|
||||
}
|
||||
|
||||
|
@ -1433,9 +1434,6 @@ nsFtpState::SetContentType()
|
|||
switch (mListFormat) {
|
||||
case nsIDirectoryListing::FORMAT_RAW:
|
||||
{
|
||||
nsAutoString fromStr(NS_LITERAL_STRING("text/ftp-dir-"));
|
||||
SetDirMIMEType(fromStr);
|
||||
|
||||
contentType = NS_LITERAL_CSTRING("text/ftp-dir-");
|
||||
}
|
||||
break;
|
||||
|
@ -2408,27 +2406,6 @@ nsFtpState::StopProcessing() {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsFtpState::SetDirMIMEType(nsString& aString) {
|
||||
// the from content type is a string of the form
|
||||
// "text/ftp-dir-SERVER_TYPE" where SERVER_TYPE represents the server we're talking to.
|
||||
switch (mServerType) {
|
||||
case FTP_UNIX_TYPE:
|
||||
aString.Append(NS_LITERAL_STRING("unix"));
|
||||
break;
|
||||
case FTP_NT_TYPE:
|
||||
aString.Append(NS_LITERAL_STRING("nt"));
|
||||
break;
|
||||
case FTP_OS2_TYPE:
|
||||
aString.Append(NS_LITERAL_STRING("os2"));
|
||||
break;
|
||||
case FTP_VMS_TYPE:
|
||||
aString.Append(NS_LITERAL_STRING("vms"));
|
||||
break;
|
||||
default:
|
||||
aString.Append(NS_LITERAL_STRING("generic"));
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFtpState::BuildStreamConverter(nsIStreamListener** convertStreamListener)
|
||||
|
@ -2446,8 +2423,8 @@ nsFtpState::BuildStreamConverter(nsIStreamListener** convertStreamListener)
|
|||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
nsAutoString fromStr(NS_LITERAL_STRING("text/ftp-dir-"));
|
||||
SetDirMIMEType(fromStr);
|
||||
nsAutoString fromStr(NS_LITERAL_STRING("text/ftp-dir"));
|
||||
|
||||
switch (mListFormat) {
|
||||
case nsIDirectoryListing::FORMAT_RAW:
|
||||
converterListener = listener;
|
||||
|
|
|
@ -157,7 +157,6 @@ private:
|
|||
///////////////////////////////////
|
||||
|
||||
// internal methods
|
||||
void SetDirMIMEType(nsString& aString);
|
||||
void MoveToNextState(FTP_STATE nextState);
|
||||
nsresult Process();
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ EXPORTS = \
|
|||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
ParseFTPList.cpp \
|
||||
nsMultiMixedConv.cpp \
|
||||
nsFTPDirListingConv.cpp \
|
||||
nsGopherDirListingConv.cpp \
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,124 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ----- BEGIN LICENSE BLOCK -----
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 Initial Developer of the Original Code is
|
||||
* Cyrus Patel <cyp@fb14.uni-mainz.de>
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s): Doug Turner <dougt@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the LGPL or the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ----- END LICENSE BLOCK ----- */
|
||||
#include "nspr.h"
|
||||
|
||||
/* ParseFTPList() parses lines from an FTP LIST command.
|
||||
**
|
||||
** Written July 2002 by Cyrus Patel <cyp@fb14.uni-mainz.de>
|
||||
** with acknowledgements to squid, lynx, wget and ftpmirror.
|
||||
**
|
||||
** Arguments:
|
||||
** 'line': line of FTP data connection output. The line is assumed
|
||||
** to end at the first '\0' or '\n' or '\r\n'.
|
||||
** 'state': a structure used internally to track state between
|
||||
** lines. Needs to be bzero()'d at LIST begin.
|
||||
** 'result': where ParseFTPList will store the results of the parse
|
||||
** if 'line' is not a comment and is not junk.
|
||||
**
|
||||
** Returns one of the following:
|
||||
** 'd' - LIST line is a directory entry ('result' is valid)
|
||||
** 'f' - LIST line is a file's entry ('result' is valid)
|
||||
** 'l' - LIST line is a symlink's entry ('result' is valid)
|
||||
** '?' - LIST line is junk. (cwd, non-file/dir/link, etc)
|
||||
** '"' - its not a LIST line (its a "comment")
|
||||
**
|
||||
** It may be advisable to let the end-user see "comments" (particularly when
|
||||
** the listing results in ONLY such lines) because such a listing may be:
|
||||
** - an unknown LIST format (NLST or "custom" format for example)
|
||||
** - an error msg (EPERM,ENOENT,ENFILE,EMFILE,ENOTDIR,ENOTBLK,EEXDEV etc).
|
||||
** - an empty directory and the 'comment' is a "total 0" line or similar.
|
||||
** (warning: a "total 0" can also mean the total size is unknown).
|
||||
**
|
||||
** ParseFTPList() supports all known FTP LISTing formats:
|
||||
** - '/bin/ls -l' and all variants (including Hellsoft FTP for NetWare);
|
||||
** - EPLF (Easily Parsable List Format);
|
||||
** - Windows NT's default "DOS-dirstyle";
|
||||
** - OS/2 basic server format LIST format;
|
||||
** - VMS (MultiNet, UCX, and CMU) LIST format (including multi-line format);
|
||||
** - IBM VM/CMS, VM/ESA LIST format (two known variants);
|
||||
** - SuperTCP FTP Server for Win16 LIST format;
|
||||
** - NetManage Chameleon (NEWT) for Win16 LIST format;
|
||||
** - '/bin/dls' (two known variants, plus multi-line) LIST format;
|
||||
** If there are others, then I'd like to hear about them (send me a sample).
|
||||
**
|
||||
** NLSTings are not supported explicitely because they cannot be machine
|
||||
** parsed consistantly: NLSTings do not have unique characteristics - even
|
||||
** the assumption that there won't be whitespace on the line does not hold
|
||||
** because some nlistings have more than one filename per line and/or
|
||||
** may have filenames that have spaces in them. Moreover, distinguishing
|
||||
** between an error message and an NLST line would require ParseList() to
|
||||
** recognize all the possible strerror() messages in the world.
|
||||
*/
|
||||
|
||||
|
||||
/* #undef anything you don't want to support */
|
||||
#define SUPPORT_LSL /* /bin/ls -l and dozens of variations therof */
|
||||
#define SUPPORT_DLS /* /bin/dls format (very, Very, VERY rare) */
|
||||
#define SUPPORT_EPLF /* Extraordinarily Pathetic List Format */
|
||||
#define SUPPORT_DOS /* WinNT server in 'site dirstyle' dos */
|
||||
#define SUPPORT_VMS /* VMS (all: MultiNet, UCX, CMU-IP) */
|
||||
#define SUPPORT_CMS /* IBM VM/CMS,VM/ESA (z/VM and LISTING forms) */
|
||||
#define SUPPORT_OS2 /* IBM TCP/IP for OS/2 - FTP Server */
|
||||
#define SUPPORT_W16 /* win16 hosts: SuperTCP or NetManage Chameleon */
|
||||
|
||||
struct list_state
|
||||
{
|
||||
void *magic; /* to determine if previously initialized */
|
||||
PRTime now_time; /* needed for year determination */
|
||||
PRExplodedTime now_tm; /* needed for year determination */
|
||||
PRInt32 lstyle; /* LISTing style */
|
||||
PRInt32 parsed_one; /* returned anything yet? */
|
||||
char carry_buf[84]; /* for VMS multiline */
|
||||
PRUint32 carry_buf_len; /* length of name in carry_buf */
|
||||
PRUint32 numlines; /* number of lines seen */
|
||||
};
|
||||
|
||||
struct list_result
|
||||
{
|
||||
PRInt32 fe_type; /* 'd'(dir) or 'l'(link) or 'f'(file) */
|
||||
const char * fe_fname; /* pointer to filename */
|
||||
PRUint32 fe_fnlen; /* length of filename */
|
||||
const char * fe_lname; /* pointer to symlink name */
|
||||
PRUint32 fe_lnlen; /* length of symlink name */
|
||||
char fe_size[40]; /* size of file in bytes (<= (2^128 - 1)) */
|
||||
PRExplodedTime fe_time; /* last-modified time */
|
||||
PRInt32 fe_cinfs; /* file system is definitely case insensitive */
|
||||
/* (converting all-upcase names may be desirable) */
|
||||
};
|
||||
|
||||
int ParseFTPList(const char *line,
|
||||
struct list_state *state,
|
||||
struct list_result *result );
|
||||
|
|
@ -55,15 +55,7 @@
|
|||
#include "nsCRT.h"
|
||||
#include "nsMimeTypes.h"
|
||||
|
||||
#define IS_LWS(c) (PL_strchr(" \t\r\n",c) != 0)
|
||||
#define IS_FTYPE(c) (PL_strchr("-dlbcsp",c) != 0)
|
||||
#define IS_RPERM(c) (PL_strchr("r-",c) != 0)
|
||||
#define IS_WPERM(c) (PL_strchr("w-",c) != 0)
|
||||
#define IS_SPERM(c) (PL_strchr("sSx-",c) != 0)
|
||||
#define IS_TPERM(c) (PL_strchr("tTx-",c) != 0)
|
||||
|
||||
static NS_DEFINE_CID(kLocaleServiceCID, NS_LOCALESERVICE_CID);
|
||||
static NS_DEFINE_CID(kDateTimeCID, NS_DATETIMEFORMAT_CID);
|
||||
#include "ParseFTPList.h"
|
||||
|
||||
#if defined(PR_LOGGING)
|
||||
//
|
||||
|
@ -87,111 +79,17 @@ NS_IMPL_THREADSAFE_ISUPPORTS3(nsFTPDirListingConv,
|
|||
nsIStreamListener,
|
||||
nsIRequestObserver);
|
||||
|
||||
// Common code of Convert and AsyncConvertData function
|
||||
|
||||
static FTP_Server_Type
|
||||
DetermineServerType (nsCString &fromMIMEString, const PRUnichar *aFromType)
|
||||
{
|
||||
fromMIMEString.AssignWithConversion(aFromType);
|
||||
const char *from = fromMIMEString.get();
|
||||
NS_ASSERTION(from, "nsCString/PRUnichar acceptance failed.");
|
||||
|
||||
from = PL_strstr(from, "/ftp-dir-");
|
||||
if (!from) return ERROR_TYPE;
|
||||
from += 9;
|
||||
fromMIMEString = from;
|
||||
|
||||
if (-1 != fromMIMEString.Find("unix")) {
|
||||
return UNIX;
|
||||
} else if (-1 != fromMIMEString.Find("nt")) {
|
||||
return NT;
|
||||
} else if (-1 != fromMIMEString.Find("dcts")) {
|
||||
return DCTS;
|
||||
} else if (-1 != fromMIMEString.Find("ncsa")) {
|
||||
return NCSA;
|
||||
} else if (-1 != fromMIMEString.Find("peter_lewis")) {
|
||||
return PETER_LEWIS;
|
||||
} else if (-1 != fromMIMEString.Find("machten")) {
|
||||
return MACHTEN;
|
||||
} else if (-1 != fromMIMEString.Find("cms")) {
|
||||
return CMS;
|
||||
} else if (-1 != fromMIMEString.Find("tcpc")) {
|
||||
return TCPC;
|
||||
} else if (-1 != fromMIMEString.Find("os2")) {
|
||||
return OS_2;
|
||||
}
|
||||
|
||||
return GENERIC;
|
||||
}
|
||||
|
||||
// nsIStreamConverter implementation
|
||||
|
||||
#define CONV_BUF_SIZE (4*1024)
|
||||
NS_IMETHODIMP
|
||||
nsFTPDirListingConv::Convert(nsIInputStream *aFromStream,
|
||||
const PRUnichar *aFromType,
|
||||
const PRUnichar *aToType,
|
||||
nsISupports *aCtxt, nsIInputStream **_retval) {
|
||||
nsresult rv;
|
||||
|
||||
// set our internal state to reflect the server type
|
||||
nsCString fromMIMEString;
|
||||
|
||||
mServerType = DetermineServerType(fromMIMEString, aFromType);
|
||||
if (mServerType == ERROR_TYPE) return NS_ERROR_FAILURE;
|
||||
|
||||
char buffer[CONV_BUF_SIZE];
|
||||
int i = 0;
|
||||
while (i < CONV_BUF_SIZE) {
|
||||
buffer[i] = '\0';
|
||||
i++;
|
||||
}
|
||||
CBufDescriptor desc(buffer, PR_TRUE, CONV_BUF_SIZE);
|
||||
nsCAutoString aBuffer(desc);
|
||||
nsCString convertedData;
|
||||
|
||||
NS_ASSERTION(aCtxt, "FTP dir conversion needs the context");
|
||||
|
||||
nsCOMPtr<nsIURI> uri(do_QueryInterface(aCtxt, &rv));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = GetHeaders(convertedData, uri);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// build up the body
|
||||
while (1) {
|
||||
PRUint32 amtRead = 0;
|
||||
|
||||
rv = aFromStream->Read(buffer+aBuffer.Length(),
|
||||
CONV_BUF_SIZE-aBuffer.Length(), &amtRead);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (!amtRead) {
|
||||
// EOF
|
||||
break;
|
||||
}
|
||||
|
||||
aBuffer = DigestBufferLines(buffer, convertedData);
|
||||
}
|
||||
// end body building
|
||||
|
||||
#ifndef DEBUG_valeski
|
||||
PR_LOG(gFTPDirListConvLog, PR_LOG_DEBUG, ("::OnData() sending the following %d bytes...\n\n%s\n\n",
|
||||
convertedData.Length(), convertedData.get()) );
|
||||
#else
|
||||
char *unescData = ToNewCString(convertedData);
|
||||
nsUnescape(unescData);
|
||||
printf("::OnData() sending the following %d bytes...\n\n%s\n\n", convertedData.Length(), unescData);
|
||||
nsMemory::Free(unescData);
|
||||
#endif // DEBUG_valeski
|
||||
|
||||
// send the converted data out.
|
||||
return NS_NewCStringInputStream(_retval, convertedData);
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Stream converter service calls this to initialize the actual stream converter (us).
|
||||
NS_IMETHODIMP
|
||||
nsFTPDirListingConv::AsyncConvertData(const PRUnichar *aFromType, const PRUnichar *aToType,
|
||||
|
@ -204,13 +102,6 @@ nsFTPDirListingConv::AsyncConvertData(const PRUnichar *aFromType, const PRUnicha
|
|||
mFinalListener = aListener;
|
||||
NS_ADDREF(mFinalListener);
|
||||
|
||||
// set our internal state to reflect the server type
|
||||
nsCString fromMIMEString;
|
||||
|
||||
mServerType = DetermineServerType(fromMIMEString, aFromType);
|
||||
if (mServerType == ERROR_TYPE) return NS_ERROR_FAILURE;
|
||||
|
||||
|
||||
// we need our own channel that represents the content-type of the
|
||||
// converted data.
|
||||
NS_ASSERTION(aCtxt, "FTP dir listing needs a context (the uri)");
|
||||
|
@ -228,7 +119,7 @@ nsFTPDirListingConv::AsyncConvertData(const PRUnichar *aFromType, const PRUnicha
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PR_LOG(gFTPDirListConvLog, PR_LOG_DEBUG,
|
||||
("nsFTPDirListingConv::AsyncConvertData() converting FROM raw %s, TO application/http-index-format\n", fromMIMEString.get()));
|
||||
("nsFTPDirListingConv::AsyncConvertData() converting FROM raw, TO application/http-index-format\n"));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -268,11 +159,11 @@ nsFTPDirListingConv::OnDataAvailable(nsIRequest* request, nsISupports *ctxt,
|
|||
mBuffer.Truncate();
|
||||
}
|
||||
|
||||
#ifndef DEBUG_valeski
|
||||
#ifndef DEBUG_dougt
|
||||
PR_LOG(gFTPDirListConvLog, PR_LOG_DEBUG, ("::OnData() received the following %d bytes...\n\n%s\n\n", streamLen, buffer) );
|
||||
#else
|
||||
printf("::OnData() received the following %d bytes...\n\n%s\n\n", streamLen, buffer);
|
||||
#endif // DEBUG_valeski
|
||||
#endif // DEBUG_dougt
|
||||
|
||||
nsCString indexFormat;
|
||||
if (!mSentHeading) {
|
||||
|
@ -290,7 +181,7 @@ nsFTPDirListingConv::OnDataAvailable(nsIRequest* request, nsISupports *ctxt,
|
|||
char *line = buffer;
|
||||
line = DigestBufferLines(line, indexFormat);
|
||||
|
||||
#ifndef DEBUG_valeski
|
||||
#ifndef DEBUG_dougt
|
||||
PR_LOG(gFTPDirListConvLog, PR_LOG_DEBUG, ("::OnData() sending the following %d bytes...\n\n%s\n\n",
|
||||
indexFormat.Length(), indexFormat.get()) );
|
||||
#else
|
||||
|
@ -298,7 +189,7 @@ nsFTPDirListingConv::OnDataAvailable(nsIRequest* request, nsISupports *ctxt,
|
|||
nsUnescape(unescData);
|
||||
printf("::OnData() sending the following %d bytes...\n\n%s\n\n", indexFormat.Length(), unescData);
|
||||
nsMemory::Free(unescData);
|
||||
#endif // DEBUG_valeski
|
||||
#endif // DEBUG_dougt
|
||||
|
||||
// if there's any data left over, buffer it.
|
||||
if (line && *line) {
|
||||
|
@ -356,7 +247,6 @@ nsFTPDirListingConv::OnStopRequest(nsIRequest* request, nsISupports *ctxt,
|
|||
nsFTPDirListingConv::nsFTPDirListingConv() {
|
||||
NS_INIT_ISUPPORTS();
|
||||
mFinalListener = nsnull;
|
||||
mServerType = GENERIC;
|
||||
mPartChannel = nsnull;
|
||||
mSentHeading = PR_FALSE;
|
||||
}
|
||||
|
@ -416,368 +306,8 @@ nsFTPDirListingConv::GetHeaders(nsACString& headers,
|
|||
return rv;
|
||||
}
|
||||
|
||||
PRInt8
|
||||
nsFTPDirListingConv::MonthNumber(const char *month) {
|
||||
NS_ASSERTION(month && month[1] && month[2], "bad month");
|
||||
if (!month || !month[0] || !month[1] || !month[2])
|
||||
return -1;
|
||||
|
||||
char c1 = month[1], c2 = month[2];
|
||||
PRInt8 rv = -1;
|
||||
|
||||
//PR_LOG(gFTPDirListConvLog, PR_LOG_DEBUG, ("nsFTPDirListingConv::MonthNumber(month = %s) ", month) );
|
||||
|
||||
switch (*month) {
|
||||
case 'f': case 'F':
|
||||
rv = 1; break;
|
||||
case 'm': case 'M':
|
||||
// c1 == 'a' || c1 == 'A'
|
||||
if (c2 == 'r' || c2 == 'R')
|
||||
rv = 2;
|
||||
else
|
||||
// c2 == 'y' || c2 == 'Y'
|
||||
rv = 4;
|
||||
break;
|
||||
case 'a': case 'A':
|
||||
if (c1 == 'p' || c1 == 'P')
|
||||
rv = 3;
|
||||
else
|
||||
// c1 == 'u' || c1 == 'U'
|
||||
rv = 7;
|
||||
break;
|
||||
case 'j': case 'J':
|
||||
if (c1 == 'u' || c1 == 'U') {
|
||||
if (c2 == 'n' || c2 == 'N')
|
||||
rv = 5;
|
||||
else
|
||||
// c2 == 'l' || c2 == 'L'
|
||||
rv = 6;
|
||||
} else {
|
||||
// c1 == 'a' || c1 == 'A'
|
||||
rv = 0;
|
||||
}
|
||||
break;
|
||||
case 's': case 'S':
|
||||
rv = 8; break;
|
||||
case 'o': case 'O':
|
||||
rv = 9; break;
|
||||
case 'n': case 'N':
|
||||
rv = 10; break;
|
||||
case 'd': case 'D':
|
||||
rv = 11; break;
|
||||
default:
|
||||
rv = -1;
|
||||
}
|
||||
|
||||
//PR_LOG(gFTPDirListConvLog, PR_LOG_DEBUG, ("returning %d\n", rv) );
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
// Return true if the string is of the form:
|
||||
// "Sep 1 1990 " or
|
||||
// "Sep 11 11:59 " or
|
||||
// "Dec 12 1989 " or
|
||||
// "FCv 23 1990 " ...
|
||||
PRBool
|
||||
nsFTPDirListingConv::IsLSDate(char *aCStr) {
|
||||
|
||||
/* must start with three alpha characters */
|
||||
if (!nsCRT::IsAsciiAlpha(*aCStr++) || !nsCRT::IsAsciiAlpha(*aCStr++) || !nsCRT::IsAsciiAlpha(*aCStr++))
|
||||
return PR_FALSE;
|
||||
|
||||
/* space */
|
||||
if (*aCStr != ' ')
|
||||
return PR_FALSE;
|
||||
aCStr++;
|
||||
|
||||
/* space or digit */
|
||||
if ((*aCStr != ' ') && !nsCRT::IsAsciiDigit(*aCStr))
|
||||
return PR_FALSE;
|
||||
aCStr++;
|
||||
|
||||
/* digit */
|
||||
if (!nsCRT::IsAsciiDigit(*aCStr))
|
||||
return PR_FALSE;
|
||||
aCStr++;
|
||||
|
||||
/* space */
|
||||
if (*aCStr != ' ')
|
||||
return PR_FALSE;
|
||||
aCStr++;
|
||||
|
||||
/* space or digit */
|
||||
if ((*aCStr != ' ') && !nsCRT::IsAsciiDigit(*aCStr))
|
||||
return PR_FALSE;
|
||||
aCStr++;
|
||||
|
||||
/* digit */
|
||||
if (!nsCRT::IsAsciiDigit(*aCStr))
|
||||
return PR_FALSE;
|
||||
aCStr++;
|
||||
|
||||
/* colon or digit */
|
||||
if ((*aCStr != ':') && !nsCRT::IsAsciiDigit(*aCStr))
|
||||
return PR_FALSE;
|
||||
aCStr++;
|
||||
|
||||
/* digit */
|
||||
if (!nsCRT::IsAsciiDigit(*aCStr))
|
||||
return PR_FALSE;
|
||||
aCStr++;
|
||||
|
||||
/* space or digit */
|
||||
if ((*aCStr != ' ') && !nsCRT::IsAsciiDigit(*aCStr))
|
||||
return PR_FALSE;
|
||||
aCStr++;
|
||||
|
||||
/* space */
|
||||
if (*aCStr != ' ')
|
||||
return PR_FALSE;
|
||||
aCStr++;
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
// Converts a date string from 'ls -l' to a PRTime number
|
||||
// "Sep 1 1990 " or
|
||||
// "Sep 11 11:59 " or
|
||||
// "Dec 12 1989 " or
|
||||
// "FCv 23 1990 " ...
|
||||
// Returns 0 on error.
|
||||
PRBool
|
||||
nsFTPDirListingConv::ConvertUNIXDate(char *aCStr, PRExplodedTime& outDate) {
|
||||
|
||||
PRExplodedTime curTime;
|
||||
InitPRExplodedTime(curTime);
|
||||
|
||||
char *bcol = aCStr; /* Column begin */
|
||||
char *ecol; /* Column end */
|
||||
|
||||
// MONTH
|
||||
char tmpChar = bcol[3];
|
||||
bcol[3] = '\0';
|
||||
|
||||
if ((curTime.tm_month = MonthNumber(bcol)) < 0)
|
||||
return PR_FALSE;
|
||||
bcol[3] = tmpChar;
|
||||
|
||||
// DAY
|
||||
ecol = &bcol[3];
|
||||
while (*(++ecol) == ' ') ;
|
||||
while (*(++ecol) != ' ') ;
|
||||
*ecol = '\0';
|
||||
bcol = ecol+1;
|
||||
while (*(--ecol) != ' ') ;
|
||||
|
||||
PRInt32 error;
|
||||
nsCAutoString day(ecol);
|
||||
curTime.tm_mday = day.ToInteger(&error, 10);
|
||||
|
||||
// YEAR
|
||||
if ((ecol = PL_strchr(bcol, ':')) == NULL) {
|
||||
nsCAutoString intStr(bcol);
|
||||
curTime.tm_year = intStr.ToInteger(&error, 10);
|
||||
} else {
|
||||
// TIME
|
||||
/* If the time is given as hh:mm, then the file is less than 1 year
|
||||
* old, but we might shift calandar year. This is avoided by checking
|
||||
* if the date parsed is future or not.
|
||||
*/
|
||||
*ecol = '\0';
|
||||
nsCAutoString intStr(++ecol);
|
||||
curTime.tm_min = intStr.ToInteger(&error, 10); // Right side of ':'
|
||||
|
||||
intStr = bcol;
|
||||
curTime.tm_hour = intStr.ToInteger(&error, 10); // Left side of ':'
|
||||
|
||||
PRExplodedTime nowETime;
|
||||
PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &nowETime);
|
||||
curTime.tm_year = nowETime.tm_year;
|
||||
|
||||
PRBool thisCalendarYear = PR_FALSE;
|
||||
if (nowETime.tm_month > curTime.tm_month) {
|
||||
thisCalendarYear = PR_TRUE;
|
||||
} else if (nowETime.tm_month == curTime.tm_month
|
||||
&& nowETime.tm_mday > curTime.tm_mday) {
|
||||
thisCalendarYear = PR_TRUE;
|
||||
} else if (nowETime.tm_month == curTime.tm_month
|
||||
&& nowETime.tm_mday == curTime.tm_mday
|
||||
&& nowETime.tm_hour > curTime.tm_hour) {
|
||||
thisCalendarYear = PR_TRUE;
|
||||
} else if (nowETime.tm_month == curTime.tm_month
|
||||
&& nowETime.tm_mday == curTime.tm_mday
|
||||
&& nowETime.tm_hour == curTime.tm_hour
|
||||
&& nowETime.tm_min >= curTime.tm_min) {
|
||||
thisCalendarYear = PR_TRUE;
|
||||
}
|
||||
|
||||
if (!thisCalendarYear) curTime.tm_year--;
|
||||
}
|
||||
|
||||
// set the out param
|
||||
outDate = curTime;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsFTPDirListingConv::ConvertDOSDate(char *aCStr, PRExplodedTime& outDate) {
|
||||
|
||||
PRExplodedTime curTime, nowTime;
|
||||
PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &nowTime);
|
||||
PRInt16 currCentury = nowTime.tm_year / 100;
|
||||
|
||||
InitPRExplodedTime(curTime);
|
||||
|
||||
curTime.tm_month = ((aCStr[0]-'0')*10 + (aCStr[1]-'0')) - 1;
|
||||
|
||||
curTime.tm_mday = (((aCStr[3]-'0')*10) + aCStr[4]-'0');
|
||||
curTime.tm_year = currCentury*100 + ((aCStr[6]-'0')*10) + aCStr[7]-'0';
|
||||
// year is only 2-digit, so we've converted. If its in the future,
|
||||
// it must have been last century
|
||||
if (curTime.tm_year > nowTime.tm_year) {
|
||||
curTime.tm_year -= 100;
|
||||
}
|
||||
|
||||
curTime.tm_hour = (((aCStr[10]-'0')*10) + aCStr[11]-'0');
|
||||
|
||||
if (aCStr[15] == 'P')
|
||||
curTime.tm_hour += 12;
|
||||
|
||||
curTime.tm_min = (((aCStr[13]-'0')*10) + aCStr[14]-'0');
|
||||
|
||||
outDate = curTime;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsFTPDirListingConv::ParseLSLine(char *aLine, indexEntry *aEntry) {
|
||||
|
||||
PRInt32 base=1;
|
||||
PRInt32 size_num=0;
|
||||
char save_char;
|
||||
char *ptr, *escName;
|
||||
|
||||
// insure that we have enough data to parse here
|
||||
// using 27 for a minimal LIST line
|
||||
if (PL_strlen(aLine) <= 27) {
|
||||
NS_WARNING("ls -l is incorrectly formatted");
|
||||
aEntry->mName.Adopt(nsEscape(aLine, url_Path));
|
||||
// initialize the time struct to 0
|
||||
InitPRExplodedTime(aEntry->mMDTM);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
for (ptr = &aLine[PL_strlen(aLine) - 1];
|
||||
(ptr > aLine+13) && (!nsCRT::IsAsciiSpace(*ptr) || !IsLSDate(ptr-12)); ptr--)
|
||||
; /* null body */
|
||||
save_char = *ptr;
|
||||
*ptr = '\0';
|
||||
if (ptr > aLine+13) {
|
||||
ConvertUNIXDate(ptr-12, aEntry->mMDTM);
|
||||
} else {
|
||||
// must be a dl listing
|
||||
// unterminate the line
|
||||
*ptr = save_char;
|
||||
// find the first whitespace and terminate
|
||||
for(ptr=aLine; *ptr != '\0'; ptr++)
|
||||
if (nsCRT::IsAsciiSpace(*ptr)) {
|
||||
*ptr = '\0';
|
||||
break;
|
||||
}
|
||||
escName = nsEscape(aLine, url_Path);
|
||||
aEntry->mName.Adopt(escName);
|
||||
|
||||
// initialize the time struct to 0 to be safe
|
||||
InitPRExplodedTime(aEntry->mMDTM);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
escName = nsEscape(ptr+1, url_Path);
|
||||
aEntry->mName.Adopt(escName);
|
||||
|
||||
// parse size
|
||||
if (ptr > aLine+15) {
|
||||
ptr -= 14;
|
||||
while (nsCRT::IsAsciiDigit(*ptr)) {
|
||||
size_num += ((PRInt32) (*ptr - '0')) * base;
|
||||
base *= 10;
|
||||
ptr--;
|
||||
}
|
||||
|
||||
aEntry->mContentLen = size_num;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsFTPDirListingConv::InitPRExplodedTime(PRExplodedTime& aTime) {
|
||||
aTime.tm_usec = 0;
|
||||
aTime.tm_sec = 0;
|
||||
aTime.tm_min = 0;
|
||||
aTime.tm_hour = 0;
|
||||
aTime.tm_mday = 0;
|
||||
aTime.tm_month= 0;
|
||||
aTime.tm_year = 0;
|
||||
aTime.tm_wday = 0;
|
||||
aTime.tm_yday = 0;
|
||||
aTime.tm_params.tp_gmt_offset = 0;
|
||||
aTime.tm_params.tp_dst_offset = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can this line possibly be a ls-l line?
|
||||
* Ideally, one should parse the line into tokens, etc. but
|
||||
* that's for later. At the moment, just test the line for
|
||||
* length and examine the first token. An absolutely minimal
|
||||
* line has the form
|
||||
* -rwxrwxrwx 0 Dec 31 23:59 F
|
||||
* which is 27 characters. If the line is at least 27 bytes
|
||||
* long and the first token matches the regular expression
|
||||
* [-dlbcps][r-][w-][sSx-][r-][w-][sSx-][r-][w-][tTx-]
|
||||
* then accept the line *provided* there is another token on
|
||||
* the line.
|
||||
|
||||
* As written, this function *assumes* leading whitespace has
|
||||
* been removed. That's what the rest of the code assumes. It
|
||||
* may not be a reasonable assumption.
|
||||
|
||||
* DigestBufferLines hints that the regular expression test should
|
||||
* be done case insensitively. That would relax this test so it is
|
||||
* *not* done. If definitive evidence exists of a server that does
|
||||
* this, then it can be changed.
|
||||
|
||||
* This function uses a lot of macros for clarity. They probably
|
||||
* should be improved.
|
||||
*/
|
||||
|
||||
PRBool
|
||||
nsFTPDirListingConv::ls_lCandidate(const char *lsLine) {
|
||||
|
||||
const char *cp;
|
||||
|
||||
if (PL_strlen(lsLine) < 27) return PR_FALSE;
|
||||
if (!IS_FTYPE(lsLine[0])) return PR_FALSE;
|
||||
// shorter tests first
|
||||
if (!IS_RPERM(lsLine[1])) return PR_FALSE;
|
||||
if (!IS_WPERM(lsLine[2])) return PR_FALSE;
|
||||
if (!IS_RPERM(lsLine[4])) return PR_FALSE;
|
||||
if (!IS_WPERM(lsLine[5])) return PR_FALSE;
|
||||
if (!IS_RPERM(lsLine[7])) return PR_FALSE;
|
||||
if (!IS_WPERM(lsLine[8])) return PR_FALSE;
|
||||
if (!IS_SPERM(lsLine[3])) return PR_FALSE;
|
||||
if (!IS_SPERM(lsLine[6])) return PR_FALSE;
|
||||
for (cp = &lsLine[10]; *cp; ++cp)
|
||||
if (!IS_LWS(*cp)) return PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
char *
|
||||
nsFTPDirListingConv::DigestBufferLines(char *aBuffer, nsCString &aString) {
|
||||
nsresult rv;
|
||||
char *line = aBuffer;
|
||||
char *eol;
|
||||
PRBool cr = PR_FALSE;
|
||||
|
@ -793,281 +323,53 @@ nsFTPDirListingConv::DigestBufferLines(char *aBuffer, nsCString &aString) {
|
|||
*eol = '\0';
|
||||
cr = PR_FALSE;
|
||||
}
|
||||
indexEntry *thisEntry = nsnull;
|
||||
NS_NEWXPCOM(thisEntry, indexEntry);
|
||||
if (!thisEntry) return nsnull;
|
||||
|
||||
// XXX we need to handle comments in the raw stream.
|
||||
list_state state;
|
||||
list_result result;
|
||||
|
||||
// special case windows servers who masquerade as unix servers
|
||||
if (NT == mServerType && !nsCRT::IsAsciiSpace(line[8]))
|
||||
mServerType = UNIX;
|
||||
int type = ParseFTPList(line, &state, &result );
|
||||
|
||||
// check for an eplf response
|
||||
if (line[0] == '+')
|
||||
mServerType = EPLF;
|
||||
|
||||
char *escName = nsnull;
|
||||
switch (mServerType) {
|
||||
|
||||
case UNIX:
|
||||
case PETER_LEWIS:
|
||||
case MACHTEN:
|
||||
// if it is other than a directory, file, or link -OR- if it is a
|
||||
// directory named . or .., skip over this line.
|
||||
if ((type != 'd' && type != 'f' && type != 'l') ||
|
||||
(result.fe_type == 'd' && result.fe_fname[0] == '.' &&
|
||||
(result.fe_fnlen == 1 || (result.fe_fnlen == 2 && result.fe_fname[1] == '.'))) )
|
||||
{
|
||||
// don't bother w/ these lines.
|
||||
if (!PL_strncmp(line, "total ", 6)
|
||||
|| !PL_strncmp(line, "ls: total", 9)
|
||||
|| (PL_strstr(line, "Permission denied") != NULL)
|
||||
|| (PL_strstr(line, "not available") != NULL)) {
|
||||
NS_DELETEXPCOM(thisEntry);
|
||||
if (cr)
|
||||
line = eol+2;
|
||||
else
|
||||
line = eol+1;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
PRInt32 len = PL_strlen(line);
|
||||
|
||||
// check first character of ls -l output
|
||||
// For example: "dr-x--x--x" is what we're starting with.
|
||||
// sanity check for dir permission bits
|
||||
if ((line[0] == 'D' || line[0] == 'd') && ls_lCandidate(line)) {
|
||||
/* it's a directory */
|
||||
thisEntry->mType = Dir;
|
||||
thisEntry->mSupressSize = PR_TRUE;
|
||||
} else if ((line[0] == 'L' || line[0] == 'l') && ls_lCandidate(line)) {
|
||||
/**
|
||||
* Dir Links are not displayed properly
|
||||
* we need a more robust implementation
|
||||
*/
|
||||
thisEntry->mType = Link;
|
||||
thisEntry->mSupressSize = PR_TRUE;
|
||||
|
||||
/* strip off " -> pathname" */
|
||||
PRInt32 i;
|
||||
for (i = len - 1; (i > 3) && (!nsCRT::IsAsciiSpace(line[i])
|
||||
|| (line[i-1] != '>')
|
||||
|| (line[i-2] != '-')
|
||||
|| (line[i-3] != ' ')); i--)
|
||||
; /* null body */
|
||||
if (i > 3) {
|
||||
line[i-3] = '\0';
|
||||
len = i - 3;
|
||||
}
|
||||
}
|
||||
|
||||
rv = ParseLSLine(line, thisEntry);
|
||||
if ( NS_FAILED(rv) || (thisEntry->mName.Equals("..")) || (thisEntry->mName.Equals(".")) ) {
|
||||
NS_DELETEXPCOM(thisEntry);
|
||||
if (cr)
|
||||
line = eol+2;
|
||||
else
|
||||
line = eol+1;
|
||||
continue;
|
||||
}
|
||||
|
||||
break; // END UNIX, PETER_LEWIS, MACHTEN
|
||||
}
|
||||
|
||||
case NCSA:
|
||||
case TCPC:
|
||||
{
|
||||
escName = nsEscape(line, url_Path);
|
||||
thisEntry->mName.Adopt(escName);
|
||||
|
||||
if (thisEntry->mName.Last() == '/') {
|
||||
thisEntry->mType = Dir;
|
||||
thisEntry->mName.Truncate(thisEntry->mName.Length()-1);
|
||||
}
|
||||
|
||||
break; // END NCSA, TCPC
|
||||
}
|
||||
|
||||
case CMS:
|
||||
{
|
||||
escName = nsEscape(line, url_Path);
|
||||
thisEntry->mName.Adopt(escName);
|
||||
break; // END CMS
|
||||
}
|
||||
case NT:
|
||||
{
|
||||
// don't bother w/ these lines.
|
||||
if (!PL_strncmp(line, "total ", 6)
|
||||
|| !PL_strncmp(line, "ls: total", 9)
|
||||
|| (PL_strstr(line, "Permission denied") != NULL)
|
||||
|| (PL_strstr(line, "not available") != NULL)) {
|
||||
NS_DELETEXPCOM(thisEntry);
|
||||
if (cr)
|
||||
line = eol+2;
|
||||
else
|
||||
line = eol+1;
|
||||
continue;
|
||||
}
|
||||
|
||||
char *date, *size_s, *name;
|
||||
|
||||
if (PL_strlen(line) > 37) {
|
||||
date = line;
|
||||
line[17] = '\0';
|
||||
size_s = &line[18];
|
||||
line[38] = '\0';
|
||||
name = &line[39];
|
||||
|
||||
if (PL_strstr(size_s, "<DIR>")) {
|
||||
thisEntry->mType = Dir;
|
||||
} else {
|
||||
nsCAutoString size(size_s);
|
||||
size.StripWhitespace();
|
||||
thisEntry->mContentLen = atol(size.get());
|
||||
}
|
||||
|
||||
ConvertDOSDate(date, thisEntry->mMDTM);
|
||||
|
||||
escName = nsEscape(name, url_Path);
|
||||
thisEntry->mName.Adopt(escName);
|
||||
} else {
|
||||
escName = nsEscape(line, url_Path);
|
||||
thisEntry->mName.Adopt(escName);
|
||||
}
|
||||
break; // END NT
|
||||
}
|
||||
case EPLF:
|
||||
{
|
||||
|
||||
int flagcwd = 0;
|
||||
int when = 0;
|
||||
int flagsize = 0;
|
||||
unsigned long size = 0;
|
||||
PRBool processing = PR_TRUE;
|
||||
while (*line && processing)
|
||||
switch (*line) {
|
||||
case '\t':
|
||||
{
|
||||
if (flagcwd) {
|
||||
thisEntry->mType = Dir;
|
||||
thisEntry->mContentLen = 0;
|
||||
} else {
|
||||
thisEntry->mType = File;
|
||||
thisEntry->mContentLen = size;
|
||||
}
|
||||
|
||||
escName = nsEscape(line+1, url_Path);
|
||||
thisEntry->mName.Adopt(escName);
|
||||
thisEntry->mSupressSize = !flagsize;
|
||||
|
||||
// Mutiply what the last modification date to get usecs.
|
||||
PRInt64 usecs = LL_Zero();
|
||||
PRInt64 seconds = LL_Zero();
|
||||
PRInt64 multiplier = LL_Zero();
|
||||
LL_I2L(seconds, when);
|
||||
LL_I2L(multiplier, PR_USEC_PER_SEC);
|
||||
LL_MUL(usecs, seconds, multiplier);
|
||||
PR_ExplodeTime(usecs, PR_LocalTimeParameters, &thisEntry->mMDTM);
|
||||
|
||||
processing = PR_FALSE;
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
flagsize = 1;
|
||||
size = 0;
|
||||
while (*++line && nsCRT::IsAsciiDigit(*line))
|
||||
size = size * 10 + (*line - '0');
|
||||
break;
|
||||
case 'm':
|
||||
while (*++line && nsCRT::IsAsciiDigit(*line))
|
||||
when = when * 10 + (*line - '0');
|
||||
break;
|
||||
case '/':
|
||||
flagcwd = 1;
|
||||
default:
|
||||
while (*line) if (*line++ == ',') break;
|
||||
}
|
||||
break; //END EPLF
|
||||
}
|
||||
|
||||
case OS_2:
|
||||
{
|
||||
if (!PL_strncmp(line, "total ", 6)
|
||||
|| (PL_strstr(line, "not authorized") != NULL)
|
||||
|| (PL_strstr(line, "Path not found") != NULL)
|
||||
|| (PL_strstr(line, "No Files") != NULL)) {
|
||||
NS_DELETEXPCOM(thisEntry);
|
||||
if (cr)
|
||||
line = eol+2;
|
||||
else
|
||||
line = eol+1;
|
||||
continue;
|
||||
}
|
||||
|
||||
char *name;
|
||||
nsCAutoString str;
|
||||
|
||||
if (PL_strstr(line, "DIR")) {
|
||||
thisEntry->mType = Dir;
|
||||
thisEntry->mSupressSize = PR_TRUE;
|
||||
}
|
||||
else
|
||||
thisEntry->mType = File;
|
||||
|
||||
PRInt32 error;
|
||||
line[18] = '\0';
|
||||
str = line;
|
||||
str.StripWhitespace();
|
||||
thisEntry->mContentLen = str.ToInteger(&error, 10);
|
||||
|
||||
InitPRExplodedTime(thisEntry->mMDTM);
|
||||
line[37] = '\0';
|
||||
str = &line[35];
|
||||
thisEntry->mMDTM.tm_month = str.ToInteger(&error, 10) - 1;
|
||||
|
||||
line[40] = '\0';
|
||||
str = &line[38];
|
||||
thisEntry->mMDTM.tm_mday = str.ToInteger(&error, 10);
|
||||
|
||||
line[43] = '\0';
|
||||
str = &line[41];
|
||||
thisEntry->mMDTM.tm_year = str.ToInteger(&error, 10);
|
||||
|
||||
line[48] = '\0';
|
||||
str = &line[46];
|
||||
thisEntry->mMDTM.tm_hour = str.ToInteger(&error, 10);
|
||||
|
||||
line[51] = '\0';
|
||||
str = &line[49];
|
||||
thisEntry->mMDTM.tm_min = str.ToInteger(&error, 10);
|
||||
|
||||
name = &line[53];
|
||||
escName = nsEscape(name, url_Path);
|
||||
thisEntry->mName.Adopt(escName);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
escName = nsEscape(line, url_Path);
|
||||
thisEntry->mName.Adopt(escName);
|
||||
break; // END default (catches GENERIC, DCTS)
|
||||
}
|
||||
|
||||
} // end switch (mServerType)
|
||||
|
||||
// blast the index entry into the indexFormat buffer as a 201: line.
|
||||
aString.Append("201: ");
|
||||
// FILENAME
|
||||
aString.Append(thisEntry->mName);
|
||||
if (thisEntry->mType == Dir)
|
||||
|
||||
aString.Append(nsDependentCString(result.fe_fname, result.fe_fnlen));
|
||||
|
||||
/* Bug 143770
|
||||
if (type == 'd')
|
||||
aString.Append('/');
|
||||
*/
|
||||
aString.Append(' ');
|
||||
|
||||
// CONTENT LENGTH
|
||||
if (!thisEntry->mSupressSize) {
|
||||
aString.AppendInt(thisEntry->mContentLen);
|
||||
} else {
|
||||
aString.Append('0');
|
||||
|
||||
if (type == 'f')
|
||||
{
|
||||
for (int i = 0; i < sizeof(result.fe_size); i++)
|
||||
{
|
||||
if (result.fe_size[i] != '\0')
|
||||
aString.Append((const char*)&result.fe_size[i], 1);
|
||||
}
|
||||
|
||||
aString.Append(' ');
|
||||
}
|
||||
else
|
||||
aString.Append("0 ");
|
||||
|
||||
|
||||
// MODIFIED DATE
|
||||
char buffer[256] = "";
|
||||
|
@ -1075,40 +377,27 @@ nsFTPDirListingConv::DigestBufferLines(char *aBuffer, nsCString &aString) {
|
|||
// the application/http-index-format specs
|
||||
// viewers of such a format can then reformat this into the
|
||||
// current locale (or anything else they choose)
|
||||
|
||||
// make sure we don't have a null time struct
|
||||
if ((thisEntry->mMDTM.tm_month + thisEntry->mMDTM.tm_mday +
|
||||
thisEntry->mMDTM.tm_year + thisEntry->mMDTM.tm_hour +
|
||||
thisEntry->mMDTM.tm_min) != nsnull) {
|
||||
PR_FormatTimeUSEnglish(buffer, sizeof(buffer),
|
||||
"%a, %d %b %Y %H:%M:%S", &thisEntry->mMDTM );
|
||||
}
|
||||
"%a, %d %b %Y %H:%M:%S", &result.fe_time );
|
||||
|
||||
char *escapedDate = nsEscape(buffer, url_Path);
|
||||
|
||||
aString.Append(escapedDate);
|
||||
nsMemory::Free(escapedDate);
|
||||
aString.Append(' ');
|
||||
|
||||
|
||||
// ENTRY TYPE
|
||||
switch (thisEntry->mType) {
|
||||
case Dir:
|
||||
if (type == 'd')
|
||||
aString.Append("DIRECTORY");
|
||||
break;
|
||||
case Link:
|
||||
else if (type == 'l')
|
||||
aString.Append("SYMBOLIC-LINK");
|
||||
break;
|
||||
default:
|
||||
else
|
||||
aString.Append("FILE");
|
||||
}
|
||||
|
||||
aString.Append(' ');
|
||||
|
||||
aString.Append(char(nsCRT::LF)); // complete this line
|
||||
// END 201:
|
||||
|
||||
NS_DELETEXPCOM(thisEntry);
|
||||
|
||||
if (cr)
|
||||
line = eol+2;
|
||||
else
|
||||
|
|
|
@ -53,62 +53,6 @@
|
|||
}
|
||||
static NS_DEFINE_CID(kFTPDirListingConverterCID, NS_FTPDIRLISTINGCONVERTER_CID);
|
||||
|
||||
// The nsFTPDirListingConv stream converter converts a stream of type "text/ftp-dir-SERVER_TYPE"
|
||||
// (where SERVER_TYPE is one of the following):
|
||||
//
|
||||
// SERVER TYPES:
|
||||
// generic
|
||||
// unix
|
||||
// dcts
|
||||
// ncsa
|
||||
// peter_lewis
|
||||
// machten
|
||||
// cms
|
||||
// tcpc
|
||||
// vms
|
||||
// nt
|
||||
// eplf
|
||||
//
|
||||
// nsFTPDirListingConv converts the raw ascii text directory generated via a FTP
|
||||
// LIST or NLST command, to the application/http-index-format MIME-type.
|
||||
// For more info see: http://www.area.com/~roeber/file_format.html
|
||||
|
||||
typedef enum _FTP_Server_Type {
|
||||
GENERIC,
|
||||
UNIX,
|
||||
DCTS,
|
||||
NCSA,
|
||||
PETER_LEWIS,
|
||||
MACHTEN,
|
||||
CMS,
|
||||
TCPC,
|
||||
VMS,
|
||||
NT,
|
||||
EPLF,
|
||||
OS_2,
|
||||
ERROR_TYPE
|
||||
} FTP_Server_Type;
|
||||
|
||||
typedef enum _FTPentryType {
|
||||
Dir,
|
||||
File,
|
||||
Link
|
||||
} FTPentryType;
|
||||
|
||||
|
||||
// indexEntry is the data structure used to maintain directory entry information.
|
||||
class indexEntry {
|
||||
public:
|
||||
indexEntry() { mContentLen = 0; mType = File; mSupressSize = PR_FALSE; };
|
||||
|
||||
nsCString mName; // the file or dir name
|
||||
FTPentryType mType;
|
||||
PRInt32 mContentLen; // length of the file
|
||||
nsCString mContentType; // type of the file
|
||||
PRExplodedTime mMDTM; // modified time
|
||||
PRBool mSupressSize; // supress the size info from display
|
||||
};
|
||||
|
||||
class nsFTPDirListingConv : public nsIStreamConverter {
|
||||
public:
|
||||
// nsISupports methods
|
||||
|
@ -128,53 +72,15 @@ public:
|
|||
virtual ~nsFTPDirListingConv();
|
||||
nsresult Init();
|
||||
|
||||
// For factory creation.
|
||||
static NS_METHOD
|
||||
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) {
|
||||
nsresult rv;
|
||||
if (aOuter)
|
||||
return NS_ERROR_NO_AGGREGATION;
|
||||
|
||||
nsFTPDirListingConv* _s = new nsFTPDirListingConv();
|
||||
if (_s == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(_s);
|
||||
rv = _s->Init();
|
||||
if (NS_FAILED(rv)) {
|
||||
delete _s;
|
||||
return rv;
|
||||
}
|
||||
rv = _s->QueryInterface(aIID, aResult);
|
||||
NS_RELEASE(_s);
|
||||
return rv;
|
||||
}
|
||||
|
||||
private:
|
||||
// Get the application/http-index-format headers
|
||||
nsresult GetHeaders(nsACString& str, nsIURI* uri);
|
||||
|
||||
// util parsing methods
|
||||
PRInt8 MonthNumber(const char *aCStr);
|
||||
PRBool IsLSDate(char *aCStr);
|
||||
|
||||
// date conversion/parsing methods
|
||||
PRBool ConvertUNIXDate(char *aCStr, PRExplodedTime& outDate);
|
||||
PRBool ConvertDOSDate(char *aCStr, PRExplodedTime& outDate);
|
||||
|
||||
// line parsing methods
|
||||
nsresult ParseLSLine(char *aLine, indexEntry *aEntry);
|
||||
nsresult ParseVMSLine(char *aLine, indexEntry *aEntry);
|
||||
|
||||
void InitPRExplodedTime(PRExplodedTime& aTime);
|
||||
PRBool ls_lCandidate(const char *aLine);
|
||||
char* DigestBufferLines(char *aBuffer, nsCString &aString);
|
||||
|
||||
// member data
|
||||
FTP_Server_Type mServerType; // what kind of server is the data coming from?
|
||||
nsCAutoString mBuffer; // buffered data.
|
||||
PRBool mSentHeading; // have we sent 100, 101, 200, and 300 lines yet?
|
||||
|
||||
|
||||
nsIStreamListener *mFinalListener; // this guy gets the converted data via his OnDataAvailable()
|
||||
nsIChannel *mPartChannel; // the channel for the given part we're processing.
|
||||
// one channel per part.
|
||||
|
|
Загрузка…
Ссылка в новой задаче