summaryrefslogtreecommitdiffstats
path: root/netwerk/streamconv
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/streamconv')
-rw-r--r--netwerk/streamconv/converters/ParseFTPList.cpp1888
-rw-r--r--netwerk/streamconv/converters/ParseFTPList.h104
-rw-r--r--netwerk/streamconv/converters/moz.build39
-rw-r--r--netwerk/streamconv/converters/mozTXTToHTMLConv.cpp1427
-rw-r--r--netwerk/streamconv/converters/mozTXTToHTMLConv.h294
-rw-r--r--netwerk/streamconv/converters/nsBinHexDecoder.cpp520
-rw-r--r--netwerk/streamconv/converters/nsBinHexDecoder.h126
-rw-r--r--netwerk/streamconv/converters/nsDirIndex.cpp122
-rw-r--r--netwerk/streamconv/converters/nsDirIndex.h30
-rw-r--r--netwerk/streamconv/converters/nsDirIndexParser.cpp427
-rw-r--r--netwerk/streamconv/converters/nsDirIndexParser.h67
-rw-r--r--netwerk/streamconv/converters/nsFTPDirListingConv.cpp345
-rw-r--r--netwerk/streamconv/converters/nsFTPDirListingConv.h52
-rw-r--r--netwerk/streamconv/converters/nsHTTPCompressConv.cpp659
-rw-r--r--netwerk/streamconv/converters/nsHTTPCompressConv.h135
-rw-r--r--netwerk/streamconv/converters/nsICompressConvStats.idl17
-rw-r--r--netwerk/streamconv/converters/nsIndexedToHTML.cpp895
-rw-r--r--netwerk/streamconv/converters/nsIndexedToHTML.h63
-rw-r--r--netwerk/streamconv/converters/nsMultiMixedConv.cpp1121
-rw-r--r--netwerk/streamconv/converters/nsMultiMixedConv.h176
-rw-r--r--netwerk/streamconv/converters/nsTXTToHTMLConv.cpp314
-rw-r--r--netwerk/streamconv/converters/nsTXTToHTMLConv.h89
-rw-r--r--netwerk/streamconv/converters/nsUnknownDecoder.cpp836
-rw-r--r--netwerk/streamconv/converters/nsUnknownDecoder.h159
-rw-r--r--netwerk/streamconv/converters/parse-ftp/3-guess.in30
-rw-r--r--netwerk/streamconv/converters/parse-ftp/3-guess.out28
-rw-r--r--netwerk/streamconv/converters/parse-ftp/C-VMold.in16
-rw-r--r--netwerk/streamconv/converters/parse-ftp/C-VMold.out12
-rw-r--r--netwerk/streamconv/converters/parse-ftp/C-zVM.in61
-rw-r--r--netwerk/streamconv/converters/parse-ftp/C-zVM.out19
-rw-r--r--netwerk/streamconv/converters/parse-ftp/D-WinNT.in60
-rw-r--r--netwerk/streamconv/converters/parse-ftp/D-WinNT.out47
-rw-r--r--netwerk/streamconv/converters/parse-ftp/E-EPLF.in189
-rw-r--r--netwerk/streamconv/converters/parse-ftp/E-EPLF.out174
-rw-r--r--netwerk/streamconv/converters/parse-ftp/O-guess.in19
-rw-r--r--netwerk/streamconv/converters/parse-ftp/O-guess.out13
-rw-r--r--netwerk/streamconv/converters/parse-ftp/R-dls.in23
-rw-r--r--netwerk/streamconv/converters/parse-ftp/R-dls.out22
-rw-r--r--netwerk/streamconv/converters/parse-ftp/README28
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-HellSoft.in25
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-HellSoft.out16
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-NetPresenz.in31
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-NetPresenz.out17
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-NetWare.in51
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-NetWare.out31
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-Novonyx.in92
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-Novonyx.out78
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-Surge.in66
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-Surge.out52
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-WarFTPd.in38
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-WarFTPd.out22
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-WebStar.in41
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-WebStar.out21
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-WinNT.in68
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-WinNT.out72
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-hethmon.in42
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-hethmon.out30
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-murksw.in29
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-murksw.out14
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-ncFTPd.in1411
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-ncFTPd.out1377
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-no_ug.in84
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-no_ug.out26
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-nogid.in82
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-nogid.out47
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-proftpd.in21
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-proftpd.out7
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-wu.in71
-rw-r--r--netwerk/streamconv/converters/parse-ftp/U-wu.out15
-rw-r--r--netwerk/streamconv/converters/parse-ftp/V-MultiNet.in34
-rw-r--r--netwerk/streamconv/converters/parse-ftp/V-MultiNet.out14
-rw-r--r--netwerk/streamconv/converters/parse-ftp/V-VMS-mix.in22
-rw-r--r--netwerk/streamconv/converters/parse-ftp/V-VMS-mix.out10
-rw-r--r--netwerk/streamconv/moz.build25
-rw-r--r--netwerk/streamconv/mozITXTToHTMLConv.idl88
-rw-r--r--netwerk/streamconv/nsIDirIndex.idl82
-rw-r--r--netwerk/streamconv/nsIDirIndexListener.idl79
-rw-r--r--netwerk/streamconv/nsIStreamConverter.idl100
-rw-r--r--netwerk/streamconv/nsIStreamConverterService.idl80
-rw-r--r--netwerk/streamconv/nsITXTToHTMLConv.idl25
-rw-r--r--netwerk/streamconv/nsStreamConverterService.cpp558
-rw-r--r--netwerk/streamconv/nsStreamConverterService.h46
-rw-r--r--netwerk/streamconv/test/Converters.cpp140
-rw-r--r--netwerk/streamconv/test/Converters.h52
-rw-r--r--netwerk/streamconv/test/TestStreamConv.cpp261
-rw-r--r--netwerk/streamconv/test/moz.build22
86 files changed, 16261 insertions, 0 deletions
diff --git a/netwerk/streamconv/converters/ParseFTPList.cpp b/netwerk/streamconv/converters/ParseFTPList.cpp
new file mode 100644
index 000000000..2ca16166c
--- /dev/null
+++ b/netwerk/streamconv/converters/ParseFTPList.cpp
@@ -0,0 +1,1888 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ParseFTPList.h"
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "plstr.h"
+#include "nsDebug.h"
+#include "prprf.h"
+#include "mozilla/IntegerPrintfMacros.h"
+#include "mozilla/Sprintf.h"
+
+/* ==================================================================== */
+
+static inline int ParsingFailed(struct list_state *state)
+{
+ if (state->parsed_one || state->lstyle) /* junk if we fail to parse */
+ return '?'; /* this time but had previously parsed successfully */
+ return '"'; /* its part of a comment or error message */
+}
+
+int ParseFTPList(const char *line, struct list_state *state,
+ struct list_result *result )
+{
+ unsigned int carry_buf_len; /* copy of state->carry_buf_len */
+ unsigned int pos;
+ const char *p;
+
+ if (!line || !state || !result)
+ return 0;
+
+ memset( result, 0, sizeof(*result) );
+ state->numlines++;
+
+ /* carry buffer is only valid from one line to the next */
+ carry_buf_len = state->carry_buf_len;
+ state->carry_buf_len = 0;
+
+ /* strip leading whitespace */
+ while (*line == ' ' || *line == '\t')
+ line++;
+
+ /* line is terminated at first '\0' or '\n' */
+ p = line;
+ while (*p && *p != '\n')
+ p++;
+ unsigned int linelen = p - line;
+
+ if (linelen > 0 && *p == '\n' && *(p-1) == '\r')
+ linelen--;
+
+ /* DON'T strip trailing whitespace. */
+
+ if (linelen > 0)
+ {
+ static const char *month_names = "JanFebMarAprMayJunJulAugSepOctNovDec";
+ const char *tokens[16]; /* 16 is more than enough */
+ unsigned int toklen[(sizeof(tokens)/sizeof(tokens[0]))];
+ unsigned int linelen_sans_wsp; // line length sans whitespace
+ unsigned int numtoks = 0;
+ unsigned int tokmarker = 0; /* extra info for lstyle handler */
+ unsigned int month_num = 0;
+ char tbuf[4];
+ int lstyle = 0;
+
+ if (carry_buf_len) /* VMS long filename carryover buffer */
+ {
+ tokens[0] = state->carry_buf;
+ toklen[0] = carry_buf_len;
+ numtoks++;
+ }
+
+ pos = 0;
+ while (pos < linelen && numtoks < (sizeof(tokens)/sizeof(tokens[0])) )
+ {
+ while (pos < linelen &&
+ (line[pos] == ' ' || line[pos] == '\t' || line[pos] == '\r'))
+ pos++;
+ if (pos < linelen)
+ {
+ tokens[numtoks] = &line[pos];
+ while (pos < linelen &&
+ (line[pos] != ' ' && line[pos] != '\t' && line[pos] != '\r'))
+ pos++;
+ if (tokens[numtoks] != &line[pos])
+ {
+ toklen[numtoks] = (&line[pos] - tokens[numtoks]);
+ numtoks++;
+ }
+ }
+ }
+
+ if (!numtoks)
+ return ParsingFailed(state);
+
+ linelen_sans_wsp = &(tokens[numtoks-1][toklen[numtoks-1]]) - tokens[0];
+ if (numtoks == (sizeof(tokens)/sizeof(tokens[0])) )
+ {
+ pos = linelen;
+ while (pos > 0 && (line[pos-1] == ' ' || line[pos-1] == '\t'))
+ pos--;
+ linelen_sans_wsp = pos;
+ }
+
+ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+#if defined(SUPPORT_EPLF)
+ /* EPLF handling must come somewhere before /bin/dls handling. */
+ if (!lstyle && (!state->lstyle || state->lstyle == 'E'))
+ {
+ if (*line == '+' && linelen > 4 && numtoks >= 2)
+ {
+ pos = 1;
+ while (pos < (linelen-1))
+ {
+ p = &line[pos++];
+ if (*p == '/')
+ result->fe_type = 'd'; /* its a dir */
+ else if (*p == 'r')
+ result->fe_type = 'f'; /* its a file */
+ else if (*p == 'm')
+ {
+ if (isdigit(line[pos]))
+ {
+ while (pos < linelen && isdigit(line[pos]))
+ pos++;
+ if (pos < linelen && line[pos] == ',')
+ {
+ PRTime t;
+ PRTime seconds;
+ PR_sscanf(p+1, "%llu", &seconds);
+ t = seconds * PR_USEC_PER_SEC;
+ PR_ExplodeTime(t, PR_LocalTimeParameters, &(result->fe_time) );
+ }
+ }
+ }
+ else if (*p == 's')
+ {
+ if (isdigit(line[pos]))
+ {
+ while (pos < linelen && isdigit(line[pos]))
+ pos++;
+ if (pos < linelen && line[pos] == ',' &&
+ ((&line[pos]) - (p+1)) < int(sizeof(result->fe_size)-1) )
+ {
+ memcpy( result->fe_size, p+1, (unsigned)(&line[pos] - (p+1)) );
+ result->fe_size[(&line[pos] - (p+1))] = '\0';
+ }
+ }
+ }
+ else if (isalpha(*p)) /* 'i'/'up' or unknown "fact" (property) */
+ {
+ while (pos < linelen && *++p != ',')
+ pos++;
+ }
+ else if (*p != '\t' || (p+1) != tokens[1])
+ {
+ break; /* its not EPLF after all */
+ }
+ else
+ {
+ state->parsed_one = 1;
+ state->lstyle = lstyle = 'E';
+
+ p = &(line[linelen_sans_wsp]);
+ result->fe_fname = tokens[1];
+ result->fe_fnlen = p - tokens[1];
+
+ if (!result->fe_type) /* access denied */
+ {
+ result->fe_type = 'f'; /* is assuming 'f'ile correct? */
+ return '?'; /* NO! junk it. */
+ }
+ return result->fe_type;
+ }
+ if (pos >= (linelen-1) || line[pos] != ',')
+ break;
+ pos++;
+ } /* while (pos < linelen) */
+ memset( result, 0, sizeof(*result) );
+ } /* if (*line == '+' && linelen > 4 && numtoks >= 2) */
+ } /* if (!lstyle && (!state->lstyle || state->lstyle == 'E')) */
+#endif /* SUPPORT_EPLF */
+
+ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+#if defined(SUPPORT_VMS)
+ if (!lstyle && (!state->lstyle || state->lstyle == 'V'))
+ { /* try VMS Multinet/UCX/CMS server */
+ /*
+ * Legal characters in a VMS file/dir spec are [A-Z0-9$.-_~].
+ * '$' cannot begin a filename and `-' cannot be used as the first
+ * or last character. '.' is only valid as a directory separator
+ * and <file>.<type> separator. A canonical filename spec might look
+ * like this: DISK$VOL:[DIR1.DIR2.DIR3]FILE.TYPE;123
+ * All VMS FTP servers LIST in uppercase.
+ *
+ * We need to be picky about this in order to support
+ * multi-line listings correctly.
+ */
+ if (!state->parsed_one &&
+ (numtoks == 1 || (numtoks == 2 && toklen[0] == 9 &&
+ memcmp(tokens[0], "Directory", 9)==0 )))
+ {
+ /* If no dirstyle has been detected yet, and this line is a
+ * VMS list's dirname, then turn on VMS dirstyle.
+ * eg "ACA:[ANONYMOUS]", "DISK$FTP:[ANONYMOUS]", "SYS$ANONFTP:"
+ */
+ p = tokens[0];
+ pos = toklen[0];
+ if (numtoks == 2)
+ {
+ p = tokens[1];
+ pos = toklen[1];
+ }
+ pos--;
+ if (pos >= 3)
+ {
+ while (pos > 0 && p[pos] != '[')
+ {
+ pos--;
+ if (p[pos] == '-' || p[pos] == '$')
+ {
+ if (pos == 0 || p[pos-1] == '[' || p[pos-1] == '.' ||
+ (p[pos] == '-' && (p[pos+1] == ']' || p[pos+1] == '.')))
+ break;
+ }
+ else if (p[pos] != '.' && p[pos] != '~' &&
+ !isdigit(p[pos]) && !isalpha(p[pos]))
+ break;
+ else if (isalpha(p[pos]) && p[pos] != toupper(p[pos]))
+ break;
+ }
+ if (pos > 0)
+ {
+ pos--;
+ if (p[pos] != ':' || p[pos+1] != '[')
+ pos = 0;
+ }
+ }
+ if (pos > 0 && p[pos] == ':')
+ {
+ while (pos > 0)
+ {
+ pos--;
+ if (p[pos] != '$' && p[pos] != '_' && p[pos] != '-' &&
+ p[pos] != '~' && !isdigit(p[pos]) && !isalpha(p[pos]))
+ break;
+ else if (isalpha(p[pos]) && p[pos] != toupper(p[pos]))
+ break;
+ }
+ if (pos == 0)
+ {
+ state->lstyle = 'V';
+ return '?'; /* its junk */
+ }
+ }
+ /* fallthrough */
+ }
+ else if ((tokens[0][toklen[0]-1]) != ';')
+ {
+ if (numtoks == 1 && (state->lstyle == 'V' && !carry_buf_len))
+ lstyle = 'V';
+ else if (numtoks < 4)
+ ;
+ else if (toklen[1] >= 10 && memcmp(tokens[1], "%RMS-E-PRV", 10) == 0)
+ lstyle = 'V';
+ else if ((&line[linelen] - tokens[1]) >= 22 &&
+ memcmp(tokens[1], "insufficient privilege", 22) == 0)
+ lstyle = 'V';
+ else if (numtoks != 4 && numtoks != 6)
+ ;
+ else if (numtoks == 6 && (
+ toklen[5] < 4 || *tokens[5] != '(' || /* perms */
+ (tokens[5][toklen[5]-1]) != ')' ))
+ ;
+ else if ( (toklen[2] == 10 || toklen[2] == 11) &&
+ (tokens[2][toklen[2]-5]) == '-' &&
+ (tokens[2][toklen[2]-9]) == '-' &&
+ (((toklen[3]==4 || toklen[3]==5 || toklen[3]==7 || toklen[3]==8) &&
+ (tokens[3][toklen[3]-3]) == ':' ) ||
+ ((toklen[3]==10 || toklen[3]==11 ) &&
+ (tokens[3][toklen[3]-3]) == '.' )
+ ) && /* time in [H]H:MM[:SS[.CC]] format */
+ isdigit(*tokens[1]) && /* size */
+ isdigit(*tokens[2]) && /* date */
+ isdigit(*tokens[3]) /* time */
+ )
+ {
+ lstyle = 'V';
+ }
+ if (lstyle == 'V')
+ {
+ /*
+ * MultiNet FTP:
+ * LOGIN.COM;2 1 4-NOV-1994 04:09 [ANONYMOUS] (RWE,RWE,,)
+ * PUB.DIR;1 1 27-JAN-1994 14:46 [ANONYMOUS] (RWE,RWE,RE,RWE)
+ * README.FTP;1 %RMS-E-PRV, insufficient privilege or file protection violation
+ * ROUSSOS.DIR;1 1 27-JAN-1994 14:48 [CS,ROUSSOS] (RWE,RWE,RE,R)
+ * S67-50903.JPG;1 328 22-SEP-1998 16:19 [ANONYMOUS] (RWED,RWED,,)
+ * UCX FTP:
+ * CII-MANUAL.TEX;1 213/216 29-JAN-1996 03:33:12 [ANONYMOU,ANONYMOUS] (RWED,RWED,,)
+ * CMU/VMS-IP FTP
+ * [VMSSERV.FILES]ALARM.DIR;1 1/3 5-MAR-1993 18:09
+ * TCPware FTP
+ * FOO.BAR;1 4 5-MAR-1993 18:09:01.12
+ * Long filename example:
+ * THIS-IS-A-LONG-VMS-FILENAME.AND-THIS-IS-A-LONG-VMS-FILETYPE\r\n
+ * 213[/nnn] 29-JAN-1996 03:33[:nn] [ANONYMOU,ANONYMOUS] (RWED,RWED,,)
+ */
+ tokmarker = 0;
+ p = tokens[0];
+ pos = 0;
+ if (*p == '[' && toklen[0] >= 4) /* CMU style */
+ {
+ if (p[1] != ']')
+ {
+ p++;
+ pos++;
+ }
+ while (lstyle && pos < toklen[0] && *p != ']')
+ {
+ if (*p != '$' && *p != '.' && *p != '_' && *p != '-' &&
+ *p != '~' && !isdigit(*p) && !isalpha(*p))
+ lstyle = 0;
+ pos++;
+ p++;
+ }
+ if (lstyle && pos < (toklen[0]-1))
+ {
+ /* ']' was found and there is at least one character after it */
+ NS_ASSERTION(*p == ']', "unexpected state");
+ pos++;
+ p++;
+ tokmarker = pos; /* length of leading "[DIR1.DIR2.etc]" */
+ } else {
+ /* not a CMU style listing */
+ lstyle = 0;
+ }
+ }
+ while (lstyle && pos < toklen[0] && *p != ';')
+ {
+ if (*p != '$' && *p != '.' && *p != '_' && *p != '-' &&
+ *p != '~' && !isdigit(*p) && !isalpha(*p))
+ lstyle = 0;
+ else if (isalpha(*p) && *p != toupper(*p))
+ lstyle = 0;
+ p++;
+ pos++;
+ }
+ if (lstyle && *p == ';')
+ {
+ if (pos == 0 || pos == (toklen[0]-1))
+ lstyle = 0;
+ for (pos++;lstyle && pos < toklen[0];pos++)
+ {
+ if (!isdigit(tokens[0][pos]))
+ lstyle = 0;
+ }
+ }
+ pos = (p - tokens[0]); /* => fnlength sans ";####" */
+ pos -= tokmarker; /* => fnlength sans "[DIR1.DIR2.etc]" */
+ p = &(tokens[0][tokmarker]); /* offset of basename */
+
+ if (!lstyle || pos == 0 || pos > 80) /* VMS filenames can't be longer than that */
+ {
+ lstyle = 0;
+ }
+ else if (numtoks == 1)
+ {
+ /* if VMS has been detected and there is only one token and that
+ * token was a VMS filename then this is a multiline VMS LIST entry.
+ */
+ if (pos >= (sizeof(state->carry_buf)-1))
+ pos = (sizeof(state->carry_buf)-1); /* shouldn't happen */
+ memcpy( state->carry_buf, p, pos );
+ state->carry_buf_len = pos;
+ return '?'; /* tell caller to treat as junk */
+ }
+ else if (isdigit(*tokens[1])) /* not no-privs message */
+ {
+ for (pos = 0; lstyle && pos < (toklen[1]); pos++)
+ {
+ if (!isdigit((tokens[1][pos])) && (tokens[1][pos]) != '/')
+ lstyle = 0;
+ }
+ if (lstyle && numtoks > 4) /* Multinet or UCX but not CMU */
+ {
+ for (pos = 1; lstyle && pos < (toklen[5]-1); pos++)
+ {
+ p = &(tokens[5][pos]);
+ if (*p!='R' && *p!='W' && *p!='E' && *p!='D' && *p!=',')
+ lstyle = 0;
+ }
+ }
+ }
+ } /* passed initial tests */
+ } /* else if ((tokens[0][toklen[0]-1]) != ';') */
+
+ if (lstyle == 'V')
+ {
+ state->parsed_one = 1;
+ state->lstyle = lstyle;
+
+ if (isdigit(*tokens[1])) /* not permission denied etc */
+ {
+ /* strip leading directory name */
+ if (*tokens[0] == '[') /* CMU server */
+ {
+ pos = toklen[0]-1;
+ p = tokens[0]+1;
+ while (*p != ']')
+ {
+ p++;
+ pos--;
+ }
+ toklen[0] = --pos;
+ tokens[0] = ++p;
+ }
+ pos = 0;
+ while (pos < toklen[0] && (tokens[0][pos]) != ';')
+ pos++;
+
+ result->fe_cinfs = 1;
+ result->fe_type = 'f';
+ result->fe_fname = tokens[0];
+ result->fe_fnlen = pos;
+
+ if (pos > 4)
+ {
+ p = &(tokens[0][pos-4]);
+ if (p[0] == '.' && p[1] == 'D' && p[2] == 'I' && p[3] == 'R')
+ {
+ result->fe_fnlen -= 4;
+ result->fe_type = 'd';
+ }
+ }
+
+ if (result->fe_type != 'd')
+ {
+ /* #### or used/allocated form. If used/allocated form, then
+ * 'used' is the size in bytes if and only if 'used'<=allocated.
+ * If 'used' is size in bytes then it can be > 2^32
+ * If 'used' is not size in bytes then it is size in blocks.
+ */
+ pos = 0;
+ while (pos < toklen[1] && (tokens[1][pos]) != '/')
+ pos++;
+
+/*
+ * I've never seen size come back in bytes, its always in blocks, and
+ * the following test fails. So, always perform the "size in blocks".
+ * I'm leaving the "size in bytes" code if'd out in case we ever need
+ * to re-instate it.
+*/
+#if 0
+ if (pos < toklen[1] && ( (pos<<1) > (toklen[1]-1) ||
+ (strtoul(tokens[1], (char **)0, 10) >
+ strtoul(tokens[1]+pos+1, (char **)0, 10)) ))
+ { /* size is in bytes */
+ if (pos > (sizeof(result->fe_size)-1))
+ pos = sizeof(result->fe_size)-1;
+ memcpy( result->fe_size, tokens[1], pos );
+ result->fe_size[pos] = '\0';
+ }
+ else /* size is in blocks */
+#endif
+ {
+ /* size requires multiplication by blocksize.
+ *
+ * We could assume blocksize is 512 (like Lynx does) and
+ * shift by 9, but that might not be right. Even if it
+ * were, doing that wouldn't reflect what the file's
+ * real size was. The sanest thing to do is not use the
+ * LISTing's filesize, so we won't (like ftpmirror).
+ *
+ * ulltoa(((unsigned long long)fsz)<<9, result->fe_size, 10);
+ *
+ * A block is always 512 bytes on OpenVMS, compute size.
+ * So its rounded up to the next block, so what, its better
+ * than not showing the size at all.
+ * A block is always 512 bytes on OpenVMS, compute size.
+ * So its rounded up to the next block, so what, its better
+ * than not showing the size at all.
+ */
+ uint64_t fsz = uint64_t(strtoul(tokens[1], (char **)0, 10) * 512);
+ SprintfLiteral(result->fe_size, "%" PRId64, fsz);
+ }
+
+ } /* if (result->fe_type != 'd') */
+
+ p = tokens[2] + 2;
+ if (*p == '-')
+ p++;
+ tbuf[0] = p[0];
+ tbuf[1] = tolower(p[1]);
+ tbuf[2] = tolower(p[2]);
+ month_num = 0;
+ for (pos = 0; pos < (12*3); pos+=3)
+ {
+ if (tbuf[0] == month_names[pos+0] &&
+ tbuf[1] == month_names[pos+1] &&
+ tbuf[2] == month_names[pos+2])
+ break;
+ month_num++;
+ }
+ if (month_num >= 12)
+ month_num = 0;
+ result->fe_time.tm_month = month_num;
+ result->fe_time.tm_mday = atoi(tokens[2]);
+ result->fe_time.tm_year = atoi(p+4); // NSPR wants year as XXXX
+
+ p = tokens[3] + 2;
+ if (*p == ':')
+ p++;
+ if (p[2] == ':')
+ result->fe_time.tm_sec = atoi(p+3);
+ result->fe_time.tm_hour = atoi(tokens[3]);
+ result->fe_time.tm_min = atoi(p);
+
+ return result->fe_type;
+
+ } /* if (isdigit(*tokens[1])) */
+
+ return '?'; /* junk */
+
+ } /* if (lstyle == 'V') */
+ } /* if (!lstyle && (!state->lstyle || state->lstyle == 'V')) */
+#endif
+
+ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+#if defined(SUPPORT_CMS)
+ /* Virtual Machine/Conversational Monitor System (IBM Mainframe) */
+ if (!lstyle && (!state->lstyle || state->lstyle == 'C')) /* VM/CMS */
+ {
+ /* LISTing according to mirror.pl
+ * Filename FileType Fm Format Lrecl Records Blocks Date Time
+ * LASTING GLOBALV A1 V 41 21 1 9/16/91 15:10:32
+ * J43401 NETLOG A0 V 77 1 1 9/12/91 12:36:04
+ * PROFILE EXEC A1 V 17 3 1 9/12/91 12:39:07
+ * DIRUNIX SCRIPT A1 V 77 1216 17 1/04/93 20:30:47
+ * MAIL PROFILE A2 F 80 1 1 10/14/92 16:12:27
+ * BADY2K TEXT A0 V 1 1 1 1/03/102 10:11:12
+ * AUTHORS A1 DIR - - - 9/20/99 10:31:11
+ *
+ * LISTing from vm.marist.edu and vm.sc.edu
+ * 220-FTPSERVE IBM VM Level 420 at VM.MARIST.EDU, 04:58:12 EDT WEDNESDAY 2002-07-10
+ * AUTHORS DIR - - - 1999-09-20 10:31:11 -
+ * HARRINGTON DIR - - - 1997-02-12 15:33:28 -
+ * PICS DIR - - - 2000-10-12 15:43:23 -
+ * SYSFILE DIR - - - 2000-07-20 17:48:01 -
+ * WELCNVT EXEC V 72 9 1 1999-09-20 17:16:18 -
+ * WELCOME EREADME F 80 21 1 1999-12-27 16:19:00 -
+ * WELCOME README V 82 21 1 1999-12-27 16:19:04 -
+ * README ANONYMOU V 71 26 1 1997-04-02 12:33:20 TCP291
+ * README ANONYOLD V 71 15 1 1995-08-25 16:04:27 TCP291
+ */
+ if (numtoks >= 7 && (toklen[0]+toklen[1]) <= 16)
+ {
+ for (pos = 1; !lstyle && (pos+5) < numtoks; pos++)
+ {
+ p = tokens[pos];
+ if ((toklen[pos] == 1 && (*p == 'F' || *p == 'V')) ||
+ (toklen[pos] == 3 && *p == 'D' && p[1] == 'I' && p[2] == 'R'))
+ {
+ if (toklen[pos+5] == 8 && (tokens[pos+5][2]) == ':' &&
+ (tokens[pos+5][5]) == ':' )
+ {
+ p = tokens[pos+4];
+ if ((toklen[pos+4] == 10 && p[4] == '-' && p[7] == '-') ||
+ (toklen[pos+4] >= 7 && toklen[pos+4] <= 9 &&
+ p[((p[1]!='/')?(2):(1))] == '/' &&
+ p[((p[1]!='/')?(5):(4))] == '/'))
+ /* Y2K bugs possible ("7/06/102" or "13/02/101") */
+ {
+ if ( (*tokens[pos+1] == '-' &&
+ *tokens[pos+2] == '-' &&
+ *tokens[pos+3] == '-') ||
+ (isdigit(*tokens[pos+1]) &&
+ isdigit(*tokens[pos+2]) &&
+ isdigit(*tokens[pos+3])) )
+ {
+ lstyle = 'C';
+ tokmarker = pos;
+ }
+ }
+ }
+ }
+ } /* for (pos = 1; !lstyle && (pos+5) < numtoks; pos++) */
+ } /* if (numtoks >= 7) */
+
+ /* extra checking if first pass */
+ if (lstyle && !state->lstyle)
+ {
+ for (pos = 0, p = tokens[0]; lstyle && pos < toklen[0]; pos++, p++)
+ {
+ if (isalpha(*p) && toupper(*p) != *p)
+ lstyle = 0;
+ }
+ for (pos = tokmarker+1; pos <= tokmarker+3; pos++)
+ {
+ if (!(toklen[pos] == 1 && *tokens[pos] == '-'))
+ {
+ for (p = tokens[pos]; lstyle && p<(tokens[pos]+toklen[pos]); p++)
+ {
+ if (!isdigit(*p))
+ lstyle = 0;
+ }
+ }
+ }
+ for (pos = 0, p = tokens[tokmarker+4];
+ lstyle && pos < toklen[tokmarker+4]; pos++, p++)
+ {
+ if (*p == '/')
+ {
+ /* There may be Y2K bugs in the date. Don't simplify to
+ * pos != (len-3) && pos != (len-6) like time is done.
+ */
+ if ((tokens[tokmarker+4][1]) == '/')
+ {
+ if (pos != 1 && pos != 4)
+ lstyle = 0;
+ }
+ else if (pos != 2 && pos != 5)
+ lstyle = 0;
+ }
+ else if (*p != '-' && !isdigit(*p))
+ lstyle = 0;
+ else if (*p == '-' && pos != 4 && pos != 7)
+ lstyle = 0;
+ }
+ for (pos = 0, p = tokens[tokmarker+5];
+ lstyle && pos < toklen[tokmarker+5]; pos++, p++)
+ {
+ if (*p != ':' && !isdigit(*p))
+ lstyle = 0;
+ else if (*p == ':' && pos != (toklen[tokmarker+5]-3)
+ && pos != (toklen[tokmarker+5]-6))
+ lstyle = 0;
+ }
+ } /* initial if() */
+
+ if (lstyle == 'C')
+ {
+ state->parsed_one = 1;
+ state->lstyle = lstyle;
+
+ p = tokens[tokmarker+4];
+ if (toklen[tokmarker+4] == 10) /* newstyle: YYYY-MM-DD format */
+ {
+ result->fe_time.tm_year = atoi(p+0) - 1900;
+ result->fe_time.tm_month = atoi(p+5) - 1;
+ result->fe_time.tm_mday = atoi(p+8);
+ }
+ else /* oldstyle: [M]M/DD/YY format */
+ {
+ pos = toklen[tokmarker+4];
+ result->fe_time.tm_month = atoi(p) - 1;
+ result->fe_time.tm_mday = atoi((p+pos)-5);
+ result->fe_time.tm_year = atoi((p+pos)-2);
+ if (result->fe_time.tm_year < 70)
+ result->fe_time.tm_year += 100;
+ }
+
+ p = tokens[tokmarker+5];
+ pos = toklen[tokmarker+5];
+ result->fe_time.tm_hour = atoi(p);
+ result->fe_time.tm_min = atoi((p+pos)-5);
+ result->fe_time.tm_sec = atoi((p+pos)-2);
+
+ result->fe_cinfs = 1;
+ result->fe_fname = tokens[0];
+ result->fe_fnlen = toklen[0];
+ result->fe_type = 'f';
+
+ p = tokens[tokmarker];
+ if (toklen[tokmarker] == 3 && *p=='D' && p[1]=='I' && p[2]=='R')
+ result->fe_type = 'd';
+
+ if ((/*newstyle*/ toklen[tokmarker+4] == 10 && tokmarker > 1) ||
+ (/*oldstyle*/ toklen[tokmarker+4] != 10 && tokmarker > 2))
+ { /* have a filetype column */
+ char *dot;
+ p = &(tokens[0][toklen[0]]);
+ memcpy( &dot, &p, sizeof(dot) ); /* NASTY! */
+ *dot++ = '.';
+ p = tokens[1];
+ for (pos = 0; pos < toklen[1]; pos++)
+ *dot++ = *p++;
+ result->fe_fnlen += 1 + toklen[1];
+ }
+
+ /* oldstyle LISTING:
+ * files/dirs not on the 'A' minidisk are not RETRievable/CHDIRable
+ if (toklen[tokmarker+4] != 10 && *tokens[tokmarker-1] != 'A')
+ return '?';
+ */
+
+ /* VM/CMS LISTings have no usable filesize field.
+ * Have to use the 'SIZE' command for that.
+ */
+ return result->fe_type;
+
+ } /* if (lstyle == 'C' && (!state->lstyle || state->lstyle == lstyle)) */
+ } /* VM/CMS */
+#endif
+
+ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+#if defined(SUPPORT_DOS) /* WinNT DOS dirstyle */
+ if (!lstyle && (!state->lstyle || state->lstyle == 'W'))
+ {
+ /*
+ * "10-23-00 01:27PM <DIR> veronist"
+ * "06-15-00 07:37AM <DIR> zoe"
+ * "07-14-00 01:35PM 2094926 canprankdesk.tif"
+ * "07-21-00 01:19PM 95077 Jon Kauffman Enjoys the Good Life.jpg"
+ * "07-21-00 01:19PM 52275 Name Plate.jpg"
+ * "07-14-00 01:38PM 2250540 Valentineoffprank-HiRes.jpg"
+ */
+ // Microsoft FTP server with FtpDirBrowseShowLongDate set returns year
+ // in 4-digit format:
+ // "10-10-2014 10:10AM <DIR> FTP"
+ // Windows CE FTP server returns time in 24-hour format:
+ // "05-03-13 22:01 <DIR> APPS"
+ if ((numtoks >= 4) && (toklen[0] == 8 || toklen[0] == 10) &&
+ (toklen[1] == 5 || toklen[1] == 7) &&
+ (*tokens[2] == '<' || isdigit(*tokens[2])) )
+ {
+ p = tokens[0];
+ if ( isdigit(p[0]) && isdigit(p[1]) && p[2]=='-' &&
+ isdigit(p[3]) && isdigit(p[4]) && p[5]=='-' &&
+ isdigit(p[6]) && isdigit(p[7]) )
+ {
+ p = tokens[1];
+ if ( isdigit(p[0]) && isdigit(p[1]) && p[2]==':' &&
+ isdigit(p[3]) && isdigit(p[4]) &&
+ (toklen[1] == 5 || (toklen[1] == 7 &&
+ (p[5]=='A' || p[5]=='P') && p[6]=='M')))
+ {
+ lstyle = 'W';
+ if (!state->lstyle)
+ {
+ p = tokens[2];
+ /* <DIR> or <JUNCTION> */
+ if (*p != '<' || p[toklen[2]-1] != '>')
+ {
+ for (pos = 1; (lstyle && pos < toklen[2]); pos++)
+ {
+ if (!isdigit(*++p))
+ lstyle = 0;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (lstyle == 'W')
+ {
+ state->parsed_one = 1;
+ state->lstyle = lstyle;
+
+ p = &(line[linelen]); /* line end */
+ result->fe_cinfs = 1;
+ result->fe_fname = tokens[3];
+ result->fe_fnlen = p - tokens[3];
+ result->fe_type = 'd';
+
+ if (*tokens[2] != '<') /* not <DIR> or <JUNCTION> */
+ {
+ // try to handle correctly spaces at the beginning of the filename
+ // filesize (token[2]) must end at offset 38
+ if (tokens[2] + toklen[2] - line == 38) {
+ result->fe_fname = &(line[39]);
+ result->fe_fnlen = p - result->fe_fname;
+ }
+ result->fe_type = 'f';
+ pos = toklen[2];
+ while (pos > (sizeof(result->fe_size)-1))
+ pos = (sizeof(result->fe_size)-1);
+ memcpy( result->fe_size, tokens[2], pos );
+ result->fe_size[pos] = '\0';
+ }
+ else {
+ // try to handle correctly spaces at the beginning of the filename
+ // token[2] must begin at offset 24, the length is 5 or 10
+ // token[3] must begin at offset 39 or higher
+ if (tokens[2] - line == 24 && (toklen[2] == 5 || toklen[2] == 10) &&
+ tokens[3] - line >= 39) {
+ result->fe_fname = &(line[39]);
+ result->fe_fnlen = p - result->fe_fname;
+ }
+
+ if ((tokens[2][1]) != 'D') /* not <DIR> */
+ {
+ result->fe_type = '?'; /* unknown until junc for sure */
+ if (result->fe_fnlen > 4)
+ {
+ p = result->fe_fname;
+ for (pos = result->fe_fnlen - 4; pos > 0; pos--)
+ {
+ if (p[0] == ' ' && p[3] == ' ' && p[2] == '>' &&
+ (p[1] == '=' || p[1] == '-'))
+ {
+ result->fe_type = 'l';
+ result->fe_fnlen = p - result->fe_fname;
+ result->fe_lname = p + 4;
+ result->fe_lnlen = &(line[linelen])
+ - result->fe_lname;
+ break;
+ }
+ p++;
+ }
+ }
+ }
+ }
+
+ result->fe_time.tm_month = atoi(tokens[0]+0);
+ if (result->fe_time.tm_month != 0)
+ {
+ result->fe_time.tm_month--;
+ result->fe_time.tm_mday = atoi(tokens[0]+3);
+ result->fe_time.tm_year = atoi(tokens[0]+6);
+ /* if year has only two digits then assume that
+ 00-79 is 2000-2079
+ 80-99 is 1980-1999 */
+ if (result->fe_time.tm_year < 80)
+ result->fe_time.tm_year += 2000;
+ else if (result->fe_time.tm_year < 100)
+ result->fe_time.tm_year += 1900;
+ }
+
+ result->fe_time.tm_hour = atoi(tokens[1]+0);
+ result->fe_time.tm_min = atoi(tokens[1]+3);
+ if (toklen[1] == 7)
+ {
+ if ((tokens[1][5]) == 'P' && result->fe_time.tm_hour < 12)
+ result->fe_time.tm_hour += 12;
+ else if ((tokens[1][5]) == 'A' && result->fe_time.tm_hour == 12)
+ result->fe_time.tm_hour = 0;
+ }
+
+ /* the caller should do this (if dropping "." and ".." is desired)
+ if (result->fe_type == 'd' && result->fe_fname[0] == '.' &&
+ (result->fe_fnlen == 1 || (result->fe_fnlen == 2 &&
+ result->fe_fname[1] == '.')))
+ return '?';
+ */
+
+ return result->fe_type;
+ } /* if (lstyle == 'W' && (!state->lstyle || state->lstyle == lstyle)) */
+ } /* if (!lstyle && (!state->lstyle || state->lstyle == 'W')) */
+#endif
+
+ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+#if defined(SUPPORT_OS2)
+ if (!lstyle && (!state->lstyle || state->lstyle == 'O')) /* OS/2 test */
+ {
+ /* 220 server IBM TCP/IP for OS/2 - FTP Server ver 23:04:36 on Jan 15 1997 ready.
+ * fixed position, space padded columns. I have only a vague idea
+ * of what the contents between col 18 and 34 might be: All I can infer
+ * is that there may be attribute flags in there and there may be
+ * a " DIR" in there.
+ *
+ * 1 2 3 4 5 6
+ *0123456789012345678901234567890123456789012345678901234567890123456789
+ *----- size -------|??????????????? MM-DD-YY| HH:MM| nnnnnnnnn....
+ * 0 DIR 04-11-95 16:26 .
+ * 0 DIR 04-11-95 16:26 ..
+ * 0 DIR 04-11-95 16:26 ADDRESS
+ * 612 RHSA 07-28-95 16:45 air_tra1.bag
+ * 195 A 08-09-95 10:23 Alfa1.bag
+ * 0 RHS DIR 04-11-95 16:26 ATTACH
+ * 372 A 08-09-95 10:26 Aussie_1.bag
+ * 310992 06-28-94 09:56 INSTALL.EXE
+ * 1 2 3 4
+ * 01234567890123456789012345678901234567890123456789
+ * dirlist from the mirror.pl project, col positions from Mozilla.
+ */
+ p = &(line[toklen[0]]);
+ /* \s(\d\d-\d\d-\d\d)\s+(\d\d:\d\d)\s */
+ if (numtoks >= 4 && toklen[0] <= 18 && isdigit(*tokens[0]) &&
+ (linelen - toklen[0]) >= (53-18) &&
+ p[18-18] == ' ' && p[34-18] == ' ' &&
+ p[37-18] == '-' && p[40-18] == '-' && p[43-18] == ' ' &&
+ p[45-18] == ' ' && p[48-18] == ':' && p[51-18] == ' ' &&
+ isdigit(p[35-18]) && isdigit(p[36-18]) &&
+ isdigit(p[38-18]) && isdigit(p[39-18]) &&
+ isdigit(p[41-18]) && isdigit(p[42-18]) &&
+ isdigit(p[46-18]) && isdigit(p[47-18]) &&
+ isdigit(p[49-18]) && isdigit(p[50-18])
+ )
+ {
+ lstyle = 'O'; /* OS/2 */
+ if (!state->lstyle)
+ {
+ for (pos = 1; lstyle && pos < toklen[0]; pos++)
+ {
+ if (!isdigit(tokens[0][pos]))
+ lstyle = 0;
+ }
+ }
+ }
+
+ if (lstyle == 'O')
+ {
+ state->parsed_one = 1;
+ state->lstyle = lstyle;
+
+ p = &(line[toklen[0]]);
+
+ result->fe_cinfs = 1;
+ result->fe_fname = &p[53-18];
+ result->fe_fnlen = (&(line[linelen_sans_wsp]))
+ - (result->fe_fname);
+ result->fe_type = 'f';
+
+ /* I don't have a real listing to determine exact pos, so scan. */
+ for (pos = (18-18); pos < ((35-18)-4); pos++)
+ {
+ if (p[pos+0] == ' ' && p[pos+1] == 'D' &&
+ p[pos+2] == 'I' && p[pos+3] == 'R')
+ {
+ result->fe_type = 'd';
+ break;
+ }
+ }
+
+ if (result->fe_type != 'd')
+ {
+ pos = toklen[0];
+ if (pos > (sizeof(result->fe_size)-1))
+ pos = (sizeof(result->fe_size)-1);
+ memcpy( result->fe_size, tokens[0], pos );
+ result->fe_size[pos] = '\0';
+ }
+
+ result->fe_time.tm_month = atoi(&p[35-18]) - 1;
+ result->fe_time.tm_mday = atoi(&p[38-18]);
+ result->fe_time.tm_year = atoi(&p[41-18]);
+ if (result->fe_time.tm_year < 80)
+ result->fe_time.tm_year += 100;
+ result->fe_time.tm_hour = atoi(&p[46-18]);
+ result->fe_time.tm_min = atoi(&p[49-18]);
+
+ /* the caller should do this (if dropping "." and ".." is desired)
+ if (result->fe_type == 'd' && result->fe_fname[0] == '.' &&
+ (result->fe_fnlen == 1 || (result->fe_fnlen == 2 &&
+ result->fe_fname[1] == '.')))
+ return '?';
+ */
+
+ return result->fe_type;
+ } /* if (lstyle == 'O') */
+
+ } /* if (!lstyle && (!state->lstyle || state->lstyle == 'O')) */
+#endif
+
+ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+#if defined(SUPPORT_LSL)
+ if (!lstyle && (!state->lstyle || state->lstyle == 'U')) /* /bin/ls & co. */
+ {
+ /* UNIX-style listing, without inum and without blocks
+ * "-rw-r--r-- 1 root other 531 Jan 29 03:26 README"
+ * "dr-xr-xr-x 2 root other 512 Apr 8 1994 etc"
+ * "dr-xr-xr-x 2 root 512 Apr 8 1994 etc"
+ * "lrwxrwxrwx 1 root other 7 Jan 25 00:17 bin -> usr/bin"
+ * Also produced by Microsoft's FTP servers for Windows:
+ * "---------- 1 owner group 1803128 Jul 10 10:18 ls-lR.Z"
+ * "d--------- 1 owner group 0 May 9 19:45 Softlib"
+ * Also WFTPD for MSDOS:
+ * "-rwxrwxrwx 1 noone nogroup 322 Aug 19 1996 message.ftp"
+ * Hellsoft for NetWare:
+ * "d[RWCEMFA] supervisor 512 Jan 16 18:53 login"
+ * "-[RWCEMFA] rhesus 214059 Oct 20 15:27 cx.exe"
+ * Newer Hellsoft for NetWare: (netlab2.usu.edu)
+ * - [RWCEAFMS] NFAUUser 192 Apr 27 15:21 HEADER.html
+ * d [RWCEAFMS] jrd 512 Jul 11 03:01 allupdates
+ * Also NetPresenz for the Mac:
+ * "-------r-- 326 1391972 1392298 Nov 22 1995 MegaPhone.sit"
+ * "drwxrwxr-x folder 2 May 10 1996 network"
+ * Protected directory:
+ * "drwx-wx-wt 2 root wheel 512 Jul 1 02:15 incoming"
+ * uid/gid instead of username/groupname:
+ * "drwxr-xr-x 2 0 0 512 May 28 22:17 etc"
+ */
+
+ bool is_old_Hellsoft = false;
+
+ if (numtoks >= 6)
+ {
+ /* there are two perm formats (Hellsoft/NetWare and *IX strmode(3)).
+ * Scan for size column only if the perm format is one or the other.
+ */
+ if (toklen[0] == 1 || (tokens[0][1]) == '[')
+ {
+ if (*tokens[0] == 'd' || *tokens[0] == '-')
+ {
+ pos = toklen[0]-1;
+ p = tokens[0] + 1;
+ if (pos == 0)
+ {
+ p = tokens[1];
+ pos = toklen[1];
+ }
+ if ((pos == 9 || pos == 10) &&
+ (*p == '[' && p[pos-1] == ']') &&
+ (p[1] == 'R' || p[1] == '-') &&
+ (p[2] == 'W' || p[2] == '-') &&
+ (p[3] == 'C' || p[3] == '-') &&
+ (p[4] == 'E' || p[4] == '-'))
+ {
+ /* rest is FMA[S] or AFM[S] */
+ lstyle = 'U'; /* very likely one of the NetWare servers */
+ if (toklen[0] == 10)
+ is_old_Hellsoft = true;
+ }
+ }
+ }
+ else if ((toklen[0] == 10 || toklen[0] == 11)
+ && strchr("-bcdlpsw?DFam", *tokens[0]))
+ {
+ p = &(tokens[0][1]);
+ if ((p[0] == 'r' || p[0] == '-') &&
+ (p[1] == 'w' || p[1] == '-') &&
+ (p[3] == 'r' || p[3] == '-') &&
+ (p[4] == 'w' || p[4] == '-') &&
+ (p[6] == 'r' || p[6] == '-') &&
+ (p[7] == 'w' || p[7] == '-'))
+ /* 'x'/p[9] can be S|s|x|-|T|t or implementation specific */
+ {
+ lstyle = 'U'; /* very likely /bin/ls */
+ }
+ }
+ }
+ if (lstyle == 'U') /* first token checks out */
+ {
+ lstyle = 0;
+ for (pos = (numtoks-5); !lstyle && pos > 1; pos--)
+ {
+ /* scan for: (\d+)\s+([A-Z][a-z][a-z])\s+
+ * (\d\d\d\d|\d\:\d\d|\d\d\:\d\d|\d\:\d\d\:\d\d|\d\d\:\d\d\:\d\d)
+ * \s+(.+)$
+ */
+ if (isdigit(*tokens[pos]) /* size */
+ /* (\w\w\w) */
+ && toklen[pos+1] == 3 && isalpha(*tokens[pos+1]) &&
+ isalpha(tokens[pos+1][1]) && isalpha(tokens[pos+1][2])
+ /* (\d|\d\d) */
+ && isdigit(*tokens[pos+2]) &&
+ (toklen[pos+2] == 1 ||
+ (toklen[pos+2] == 2 && isdigit(tokens[pos+2][1])))
+ && toklen[pos+3] >= 4 && isdigit(*tokens[pos+3])
+ /* (\d\:\d\d\:\d\d|\d\d\:\d\d\:\d\d) */
+ && (toklen[pos+3] <= 5 || (
+ (toklen[pos+3] == 7 || toklen[pos+3] == 8) &&
+ (tokens[pos+3][toklen[pos+3]-3]) == ':'))
+ && isdigit(tokens[pos+3][toklen[pos+3]-2])
+ && isdigit(tokens[pos+3][toklen[pos+3]-1])
+ && (
+ /* (\d\d\d\d) */
+ ((toklen[pos+3] == 4 || toklen[pos+3] == 5) &&
+ isdigit(tokens[pos+3][1]) &&
+ isdigit(tokens[pos+3][2]) )
+ /* (\d\:\d\d|\d\:\d\d\:\d\d) */
+ || ((toklen[pos+3] == 4 || toklen[pos+3] == 7) &&
+ (tokens[pos+3][1]) == ':' &&
+ isdigit(tokens[pos+3][2]) && isdigit(tokens[pos+3][3]))
+ /* (\d\d\:\d\d|\d\d\:\d\d\:\d\d) */
+ || ((toklen[pos+3] == 5 || toklen[pos+3] == 8) &&
+ isdigit(tokens[pos+3][1]) && (tokens[pos+3][2]) == ':' &&
+ isdigit(tokens[pos+3][3]) && isdigit(tokens[pos+3][4]))
+ )
+ )
+ {
+ lstyle = 'U'; /* assume /bin/ls or variant format */
+ tokmarker = pos;
+
+ /* check that size is numeric */
+ p = tokens[tokmarker];
+ unsigned int i;
+ for (i = 0; i < toklen[tokmarker]; i++)
+ {
+ if (!isdigit(*p++))
+ {
+ lstyle = 0;
+ break;
+ }
+ }
+ if (lstyle)
+ {
+ month_num = 0;
+ p = tokens[tokmarker+1];
+ for (i = 0; i < (12*3); i+=3)
+ {
+ if (p[0] == month_names[i+0] &&
+ p[1] == month_names[i+1] &&
+ p[2] == month_names[i+2])
+ break;
+ month_num++;
+ }
+ if (month_num >= 12)
+ lstyle = 0;
+ }
+ } /* relative position test */
+ } /* for (pos = (numtoks-5); !lstyle && pos > 1; pos--) */
+ } /* if (lstyle == 'U') */
+
+ if (lstyle == 'U')
+ {
+ state->parsed_one = 1;
+ state->lstyle = lstyle;
+
+ result->fe_cinfs = 0;
+ result->fe_type = '?';
+ if (*tokens[0] == 'd' || *tokens[0] == 'l')
+ result->fe_type = *tokens[0];
+ else if (*tokens[0] == 'D')
+ result->fe_type = 'd';
+ else if (*tokens[0] == '-' || *tokens[0] == 'F')
+ result->fe_type = 'f'; /* (hopefully a regular file) */
+
+ if (result->fe_type != 'd')
+ {
+ pos = toklen[tokmarker];
+ if (pos > (sizeof(result->fe_size)-1))
+ pos = (sizeof(result->fe_size)-1);
+ memcpy( result->fe_size, tokens[tokmarker], pos );
+ result->fe_size[pos] = '\0';
+ }
+
+ result->fe_time.tm_month = month_num;
+ result->fe_time.tm_mday = atoi(tokens[tokmarker+2]);
+ if (result->fe_time.tm_mday == 0)
+ result->fe_time.tm_mday++;
+
+ p = tokens[tokmarker+3];
+ pos = (unsigned int)atoi(p);
+ if (p[1] == ':') /* one digit hour */
+ p--;
+ if (p[2] != ':') /* year */
+ {
+ result->fe_time.tm_year = pos;
+ }
+ else
+ {
+ result->fe_time.tm_hour = pos;
+ result->fe_time.tm_min = atoi(p+3);
+ if (p[5] == ':')
+ result->fe_time.tm_sec = atoi(p+6);
+
+ if (!state->now_time)
+ {
+ state->now_time = PR_Now();
+ PR_ExplodeTime((state->now_time), PR_LocalTimeParameters, &(state->now_tm) );
+ }
+
+ result->fe_time.tm_year = state->now_tm.tm_year;
+ if ( (( state->now_tm.tm_month << 5) + state->now_tm.tm_mday) <
+ ((result->fe_time.tm_month << 5) + result->fe_time.tm_mday) )
+ result->fe_time.tm_year--;
+
+ } /* time/year */
+
+ // The length of the whole date string should be 12. On AIX the length
+ // is only 11 when the year is present in the date string and there is
+ // 1 padding space at the end of the string. In both cases the filename
+ // starts at offset 13 from the start of the date string.
+ // Don't care about leading spaces when the date string has different
+ // format or when old Hellsoft output was detected.
+ {
+ const char *date_start = tokens[tokmarker+1];
+ const char *date_end = tokens[tokmarker+3] + toklen[tokmarker+3];
+ if (!is_old_Hellsoft && ((date_end - date_start) == 12 ||
+ ((date_end - date_start) == 11 && date_end[1] == ' ')))
+ result->fe_fname = date_start + 13;
+ else
+ result->fe_fname = tokens[tokmarker+4];
+ }
+
+ result->fe_fnlen = (&(line[linelen]))
+ - (result->fe_fname);
+
+ if (result->fe_type == 'l' && result->fe_fnlen > 4)
+ {
+ /* First try to use result->fe_size to find " -> " sequence.
+ This can give proper result for cases like "aaa -> bbb -> ccc". */
+ uint32_t fe_size = atoi(result->fe_size);
+
+ if (result->fe_fnlen > (fe_size + 4) &&
+ PL_strncmp(result->fe_fname + result->fe_fnlen - fe_size - 4 , " -> ", 4) == 0)
+ {
+ result->fe_lname = result->fe_fname + (result->fe_fnlen - fe_size);
+ result->fe_lnlen = (&(line[linelen])) - (result->fe_lname);
+ result->fe_fnlen -= fe_size + 4;
+ }
+ else
+ {
+ /* Search for sequence " -> " from the end for case when there are
+ more occurrences. F.e. if ftpd returns "a -> b -> c" assume
+ "a -> b" as a name. Powerusers can remove unnecessary parts
+ manually but there is no way to follow the link when some
+ essential part is missing. */
+ p = result->fe_fname + (result->fe_fnlen - 5);
+ for (pos = (result->fe_fnlen - 5); pos > 0; pos--)
+ {
+ if (PL_strncmp(p, " -> ", 4) == 0)
+ {
+ result->fe_lname = p + 4;
+ result->fe_lnlen = (&(line[linelen]))
+ - (result->fe_lname);
+ result->fe_fnlen = pos;
+ break;
+ }
+ p--;
+ }
+ }
+ }
+
+#if defined(SUPPORT_LSLF) /* some (very rare) servers return ls -lF */
+ if (result->fe_fnlen > 1)
+ {
+ p = result->fe_fname[result->fe_fnlen-1];
+ pos = result->fe_type;
+ if (pos == 'd') {
+ if (*p == '/') result->fe_fnlen--; /* directory */
+ } else if (pos == 'l') {
+ if (*p == '@') result->fe_fnlen--; /* symlink */
+ } else if (pos == 'f') {
+ if (*p == '*') result->fe_fnlen--; /* executable */
+ } else if (*p == '=' || *p == '%' || *p == '|') {
+ result->fe_fnlen--; /* socket, whiteout, fifo */
+ }
+ }
+#endif
+
+ /* the caller should do this (if dropping "." and ".." is desired)
+ if (result->fe_type == 'd' && result->fe_fname[0] == '.' &&
+ (result->fe_fnlen == 1 || (result->fe_fnlen == 2 &&
+ result->fe_fname[1] == '.')))
+ return '?';
+ */
+
+ return result->fe_type;
+
+ } /* if (lstyle == 'U') */
+
+ } /* if (!lstyle && (!state->lstyle || state->lstyle == 'U')) */
+#endif
+
+ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+#if defined(SUPPORT_W16) /* 16bit Windows */
+ if (!lstyle && (!state->lstyle || state->lstyle == 'w'))
+ { /* old SuperTCP suite FTP server for Win3.1 */
+ /* old NetManage Chameleon TCP/IP suite FTP server for Win3.1 */
+ /*
+ * SuperTCP dirlist from the mirror.pl project
+ * mon/day/year separator may be '/' or '-'.
+ * . <DIR> 11-16-94 17:16
+ * .. <DIR> 11-16-94 17:16
+ * INSTALL <DIR> 11-16-94 17:17
+ * CMT <DIR> 11-21-94 10:17
+ * DESIGN1.DOC 11264 05-11-95 14:20
+ * README.TXT 1045 05-10-95 11:01
+ * WPKIT1.EXE 960338 06-21-95 17:01
+ * CMT.CSV 0 07-06-95 14:56
+ *
+ * Chameleon dirlist guessed from lynx
+ * . <DIR> Nov 16 1994 17:16
+ * .. <DIR> Nov 16 1994 17:16
+ * INSTALL <DIR> Nov 16 1994 17:17
+ * CMT <DIR> Nov 21 1994 10:17
+ * DESIGN1.DOC 11264 May 11 1995 14:20 A
+ * README.TXT 1045 May 10 1995 11:01
+ * WPKIT1.EXE 960338 Jun 21 1995 17:01 R
+ * CMT.CSV 0 Jul 06 1995 14:56 RHA
+ */
+ if (numtoks >= 4 && toklen[0] < 13 &&
+ ((toklen[1] == 5 && *tokens[1] == '<') || isdigit(*tokens[1])) )
+ {
+ if (numtoks == 4
+ && (toklen[2] == 8 || toklen[2] == 9)
+ && (((tokens[2][2]) == '/' && (tokens[2][5]) == '/') ||
+ ((tokens[2][2]) == '-' && (tokens[2][5]) == '-'))
+ && (toklen[3] == 4 || toklen[3] == 5)
+ && (tokens[3][toklen[3]-3]) == ':'
+ && isdigit(tokens[2][0]) && isdigit(tokens[2][1])
+ && isdigit(tokens[2][3]) && isdigit(tokens[2][4])
+ && isdigit(tokens[2][6]) && isdigit(tokens[2][7])
+ && (toklen[2] < 9 || isdigit(tokens[2][8]))
+ && isdigit(tokens[3][toklen[3]-1]) && isdigit(tokens[3][toklen[3]-2])
+ && isdigit(tokens[3][toklen[3]-4]) && isdigit(*tokens[3])
+ )
+ {
+ lstyle = 'w';
+ }
+ else if ((numtoks == 6 || numtoks == 7)
+ && toklen[2] == 3 && toklen[3] == 2
+ && toklen[4] == 4 && toklen[5] == 5
+ && (tokens[5][2]) == ':'
+ && isalpha(tokens[2][0]) && isalpha(tokens[2][1])
+ && isalpha(tokens[2][2])
+ && isdigit(tokens[3][0]) && isdigit(tokens[3][1])
+ && isdigit(tokens[4][0]) && isdigit(tokens[4][1])
+ && isdigit(tokens[4][2]) && isdigit(tokens[4][3])
+ && isdigit(tokens[5][0]) && isdigit(tokens[5][1])
+ && isdigit(tokens[5][3]) && isdigit(tokens[5][4])
+ /* could also check that (&(tokens[5][5]) - tokens[2]) == 17 */
+ )
+ {
+ lstyle = 'w';
+ }
+ if (lstyle && state->lstyle != lstyle) /* first time */
+ {
+ p = tokens[1];
+ if (toklen[1] != 5 || p[0] != '<' || p[1] != 'D' ||
+ p[2] != 'I' || p[3] != 'R' || p[4] != '>')
+ {
+ for (pos = 0; lstyle && pos < toklen[1]; pos++)
+ {
+ if (!isdigit(*p++))
+ lstyle = 0;
+ }
+ } /* not <DIR> */
+ } /* if (first time) */
+ } /* if (numtoks == ...) */
+
+ if (lstyle == 'w')
+ {
+ state->parsed_one = 1;
+ state->lstyle = lstyle;
+
+ result->fe_cinfs = 1;
+ result->fe_fname = tokens[0];
+ result->fe_fnlen = toklen[0];
+ result->fe_type = 'd';
+
+ p = tokens[1];
+ if (isdigit(*p))
+ {
+ result->fe_type = 'f';
+ pos = toklen[1];
+ if (pos > (sizeof(result->fe_size)-1))
+ pos = sizeof(result->fe_size)-1;
+ memcpy( result->fe_size, p, pos );
+ result->fe_size[pos] = '\0';
+ }
+
+ p = tokens[2];
+ if (toklen[2] == 3) /* Chameleon */
+ {
+ tbuf[0] = toupper(p[0]);
+ tbuf[1] = tolower(p[1]);
+ tbuf[2] = tolower(p[2]);
+ for (pos = 0; pos < (12*3); pos+=3)
+ {
+ if (tbuf[0] == month_names[pos+0] &&
+ tbuf[1] == month_names[pos+1] &&
+ tbuf[2] == month_names[pos+2])
+ {
+ result->fe_time.tm_month = pos/3;
+ result->fe_time.tm_mday = atoi(tokens[3]);
+ result->fe_time.tm_year = atoi(tokens[4]) - 1900;
+ break;
+ }
+ }
+ pos = 5; /* Chameleon toknum of date field */
+ }
+ else
+ {
+ result->fe_time.tm_month = atoi(p+0)-1;
+ result->fe_time.tm_mday = atoi(p+3);
+ result->fe_time.tm_year = atoi(p+6);
+ if (result->fe_time.tm_year < 80) /* SuperTCP */
+ result->fe_time.tm_year += 100;
+
+ pos = 3; /* SuperTCP toknum of date field */
+ }
+
+ result->fe_time.tm_hour = atoi(tokens[pos]);
+ result->fe_time.tm_min = atoi(&(tokens[pos][toklen[pos]-2]));
+
+ /* the caller should do this (if dropping "." and ".." is desired)
+ if (result->fe_type == 'd' && result->fe_fname[0] == '.' &&
+ (result->fe_fnlen == 1 || (result->fe_fnlen == 2 &&
+ result->fe_fname[1] == '.')))
+ return '?';
+ */
+
+ return result->fe_type;
+ } /* (lstyle == 'w') */
+
+ } /* if (!lstyle && (!state->lstyle || state->lstyle == 'w')) */
+#endif
+
+ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+#if defined(SUPPORT_DLS) /* dls -dtR */
+ if (!lstyle &&
+ (state->lstyle == 'D' || (!state->lstyle && state->numlines == 1)))
+ /* /bin/dls lines have to be immediately recognizable (first line) */
+ {
+ /* I haven't seen an FTP server that delivers a /bin/dls listing,
+ * but can infer the format from the lynx and mirror.pl projects.
+ * Both formats are supported.
+ *
+ * Lynx says:
+ * README 763 Information about this server\0
+ * bin/ - \0
+ * etc/ = \0
+ * ls-lR 0 \0
+ * ls-lR.Z 3 \0
+ * pub/ = Public area\0
+ * usr/ - \0
+ * morgan 14 -> ../real/morgan\0
+ * TIMIT.mostlikely.Z\0
+ * 79215 \0
+ *
+ * mirror.pl says:
+ * filename: ^(\S*)\s+
+ * size: (\-|\=|\d+)\s+
+ * month/day: ((\w\w\w\s+\d+|\d+\s+\w\w\w)\s+
+ * time/year: (\d+:\d+|\d\d\d\d))\s+
+ * rest: (.+)
+ *
+ * README 763 Jul 11 21:05 Information about this server
+ * bin/ - Apr 28 1994
+ * etc/ = 11 Jul 21:04
+ * ls-lR 0 6 Aug 17:14
+ * ls-lR.Z 3 05 Sep 1994
+ * pub/ = Jul 11 21:04 Public area
+ * usr/ - Sep 7 09:39
+ * morgan 14 Apr 18 09:39 -> ../real/morgan
+ * TIMIT.mostlikely.Z
+ * 79215 Jul 11 21:04
+ */
+ if (!state->lstyle && line[linelen-1] == ':' &&
+ linelen >= 2 && toklen[numtoks-1] != 1)
+ {
+ /* code in mirror.pl suggests that a listing may be preceded
+ * by a PWD line in the form "/some/dir/names/here:"
+ * but does not necessarily begin with '/'. *sigh*
+ */
+ pos = 0;
+ p = line;
+ while (pos < (linelen-1))
+ {
+ /* illegal (or extremely unusual) chars in a dirspec */
+ if (*p == '<' || *p == '|' || *p == '>' ||
+ *p == '?' || *p == '*' || *p == '\\')
+ break;
+ if (*p == '/' && pos < (linelen-2) && p[1] == '/')
+ break;
+ pos++;
+ p++;
+ }
+ if (pos == (linelen-1))
+ {
+ state->lstyle = 'D';
+ return '?';
+ }
+ }
+
+ if (!lstyle && numtoks >= 2)
+ {
+ pos = 22; /* pos of (\d+|-|=) if this is not part of a multiline */
+ if (state->lstyle && carry_buf_len) /* first is from previous line */
+ pos = toklen[1]-1; /* and is 'as-is' (may contain whitespace) */
+
+ if (linelen > pos)
+ {
+ p = &line[pos];
+ if ((*p == '-' || *p == '=' || isdigit(*p)) &&
+ ((linelen == (pos+1)) ||
+ (linelen >= (pos+3) && p[1] == ' ' && p[2] == ' ')) )
+ {
+ tokmarker = 1;
+ if (!carry_buf_len)
+ {
+ pos = 1;
+ while (pos < numtoks && (tokens[pos]+toklen[pos]) < (&line[23]))
+ pos++;
+ tokmarker = 0;
+ if ((tokens[pos]+toklen[pos]) == (&line[23]))
+ tokmarker = pos;
+ }
+ if (tokmarker)
+ {
+ lstyle = 'D';
+ if (*tokens[tokmarker] == '-' || *tokens[tokmarker] == '=')
+ {
+ if (toklen[tokmarker] != 1 ||
+ (tokens[tokmarker-1][toklen[tokmarker-1]-1]) != '/')
+ lstyle = 0;
+ }
+ else
+ {
+ for (pos = 0; lstyle && pos < toklen[tokmarker]; pos++)
+ {
+ if (!isdigit(tokens[tokmarker][pos]))
+ lstyle = 0;
+ }
+ }
+ if (lstyle && !state->lstyle) /* first time */
+ {
+ /* scan for illegal (or incredibly unusual) chars in fname */
+ for (p = tokens[0]; lstyle &&
+ p < &(tokens[tokmarker-1][toklen[tokmarker-1]]); p++)
+ {
+ if (*p == '<' || *p == '|' || *p == '>' ||
+ *p == '?' || *p == '*' || *p == '/' || *p == '\\')
+ lstyle = 0;
+ }
+ }
+
+ } /* size token found */
+ } /* expected chars behind expected size token */
+ } /* if (linelen > pos) */
+ } /* if (!lstyle && numtoks >= 2) */
+
+ if (!lstyle && state->lstyle == 'D' && !carry_buf_len)
+ {
+ /* the filename of a multi-line entry can be identified
+ * correctly only if dls format had been previously established.
+ * This should always be true because there should be entries
+ * for '.' and/or '..' and/or CWD that precede the rest of the
+ * listing.
+ */
+ pos = linelen;
+ if (pos > (sizeof(state->carry_buf)-1))
+ pos = sizeof(state->carry_buf)-1;
+ memcpy( state->carry_buf, line, pos );
+ state->carry_buf_len = pos;
+ return '?';
+ }
+
+ if (lstyle == 'D')
+ {
+ state->parsed_one = 1;
+ state->lstyle = lstyle;
+
+ p = &(tokens[tokmarker-1][toklen[tokmarker-1]]);
+ result->fe_fname = tokens[0];
+ result->fe_fnlen = p - tokens[0];
+ result->fe_type = 'f';
+
+ if (result->fe_fname[result->fe_fnlen-1] == '/')
+ {
+ if (result->fe_lnlen == 1)
+ result->fe_type = '?';
+ else
+ {
+ result->fe_fnlen--;
+ result->fe_type = 'd';
+ }
+ }
+ else if (isdigit(*tokens[tokmarker]))
+ {
+ pos = toklen[tokmarker];
+ if (pos > (sizeof(result->fe_size)-1))
+ pos = sizeof(result->fe_size)-1;
+ memcpy( result->fe_size, tokens[tokmarker], pos );
+ result->fe_size[pos] = '\0';
+ }
+
+ if ((tokmarker+3) < numtoks &&
+ (&(tokens[numtoks-1][toklen[numtoks-1]]) -
+ tokens[tokmarker+1]) >= (1+1+3+1+4) )
+ {
+ pos = (tokmarker+3);
+ p = tokens[pos];
+ pos = toklen[pos];
+
+ if ((pos == 4 || pos == 5)
+ && isdigit(*p) && isdigit(p[pos-1]) && isdigit(p[pos-2])
+ && ((pos == 5 && p[2] == ':') ||
+ (pos == 4 && (isdigit(p[1]) || p[1] == ':')))
+ )
+ {
+ month_num = tokmarker+1; /* assumed position of month field */
+ pos = tokmarker+2; /* assumed position of mday field */
+ if (isdigit(*tokens[month_num])) /* positions are reversed */
+ {
+ month_num++;
+ pos--;
+ }
+ p = tokens[month_num];
+ if (isdigit(*tokens[pos])
+ && (toklen[pos] == 1 ||
+ (toklen[pos] == 2 && isdigit(tokens[pos][1])))
+ && toklen[month_num] == 3
+ && isalpha(*p) && isalpha(p[1]) && isalpha(p[2]) )
+ {
+ pos = atoi(tokens[pos]);
+ if (pos > 0 && pos <= 31)
+ {
+ result->fe_time.tm_mday = pos;
+ month_num = 1;
+ for (pos = 0; pos < (12*3); pos+=3)
+ {
+ if (p[0] == month_names[pos+0] &&
+ p[1] == month_names[pos+1] &&
+ p[2] == month_names[pos+2])
+ break;
+ month_num++;
+ }
+ if (month_num > 12)
+ result->fe_time.tm_mday = 0;
+ else
+ result->fe_time.tm_month = month_num - 1;
+ }
+ }
+ if (result->fe_time.tm_mday)
+ {
+ tokmarker += 3; /* skip mday/mon/yrtime (to find " -> ") */
+ p = tokens[tokmarker];
+
+ pos = atoi(p);
+ if (pos > 24)
+ result->fe_time.tm_year = pos-1900;
+ else
+ {
+ if (p[1] == ':')
+ p--;
+ result->fe_time.tm_hour = pos;
+ result->fe_time.tm_min = atoi(p+3);
+ if (!state->now_time)
+ {
+ state->now_time = PR_Now();
+ PR_ExplodeTime((state->now_time), PR_LocalTimeParameters, &(state->now_tm) );
+ }
+ result->fe_time.tm_year = state->now_tm.tm_year;
+ if ( (( state->now_tm.tm_month << 4) + state->now_tm.tm_mday) <
+ ((result->fe_time.tm_month << 4) + result->fe_time.tm_mday) )
+ result->fe_time.tm_year--;
+ } /* got year or time */
+ } /* got month/mday */
+ } /* may have year or time */
+ } /* enough remaining to possibly have date/time */
+
+ if (numtoks > (tokmarker+2))
+ {
+ pos = tokmarker+1;
+ p = tokens[pos];
+ if (toklen[pos] == 2 && *p == '-' && p[1] == '>')
+ {
+ p = &(tokens[numtoks-1][toklen[numtoks-1]]);
+ result->fe_type = 'l';
+ result->fe_lname = tokens[pos+1];
+ result->fe_lnlen = p - result->fe_lname;
+ if (result->fe_lnlen > 1 &&
+ result->fe_lname[result->fe_lnlen-1] == '/')
+ result->fe_lnlen--;
+ }
+ } /* if (numtoks > (tokmarker+2)) */
+
+ /* the caller should do this (if dropping "." and ".." is desired)
+ if (result->fe_type == 'd' && result->fe_fname[0] == '.' &&
+ (result->fe_fnlen == 1 || (result->fe_fnlen == 2 &&
+ result->fe_fname[1] == '.')))
+ return '?';
+ */
+
+ return result->fe_type;
+
+ } /* if (lstyle == 'D') */
+ } /* if (!lstyle && (!state->lstyle || state->lstyle == 'D')) */
+#endif
+
+ /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+
+ } /* if (linelen > 0) */
+
+ return ParsingFailed(state);
+}
+
+/* ==================================================================== */
+/* standalone testing */
+/* ==================================================================== */
+#if 0
+
+#include <stdio.h>
+
+static int do_it(FILE *outfile,
+ char *line, size_t linelen, struct list_state *state,
+ char **cmnt_buf, unsigned int *cmnt_buf_sz,
+ char **list_buf, unsigned int *list_buf_sz )
+{
+ struct list_result result;
+ char *p;
+ int rc;
+
+ rc = ParseFTPList( line, state, &result );
+
+ if (!outfile)
+ {
+ outfile = stdout;
+ if (rc == '?')
+ fprintf(outfile, "junk: %.*s\n", (int)linelen, line );
+ else if (rc == '"')
+ fprintf(outfile, "cmnt: %.*s\n", (int)linelen, line );
+ else
+ fprintf(outfile,
+ "list: %02u-%02u-%02u %02u:%02u%cM %20s %.*s%s%.*s\n",
+ (result.fe_time.tm_mday ? (result.fe_time.tm_month + 1) : 0),
+ result.fe_time.tm_mday,
+ (result.fe_time.tm_mday ? (result.fe_time.tm_year % 100) : 0),
+ result.fe_time.tm_hour -
+ ((result.fe_time.tm_hour > 12)?(12):(0)),
+ result.fe_time.tm_min,
+ ((result.fe_time.tm_hour >= 12) ? 'P' : 'A'),
+ (rc == 'd' ? "<DIR> " :
+ (rc == 'l' ? "<JUNCTION> " : result.fe_size)),
+ (int)result.fe_fnlen, result.fe_fname,
+ ((rc == 'l' && result.fe_lnlen) ? " -> " : ""),
+ (int)((rc == 'l' && result.fe_lnlen) ? result.fe_lnlen : 0),
+ ((rc == 'l' && result.fe_lnlen) ? result.fe_lname : "") );
+ }
+ else if (rc != '?') /* NOT junk */
+ {
+ char **bufp = list_buf;
+ unsigned int *bufz = list_buf_sz;
+
+ if (rc == '"') /* comment - make it a 'result' */
+ {
+ memset( &result, 0, sizeof(result));
+ result.fe_fname = line;
+ result.fe_fnlen = linelen;
+ result.fe_type = 'f';
+ if (line[linelen-1] == '/')
+ {
+ result.fe_type = 'd';
+ result.fe_fnlen--;
+ }
+ bufp = cmnt_buf;
+ bufz = cmnt_buf_sz;
+ rc = result.fe_type;
+ }
+
+ linelen = 80 + result.fe_fnlen + result.fe_lnlen;
+ p = (char *)realloc( *bufp, *bufz + linelen );
+ if (!p)
+ return -1;
+ sprintf( &p[*bufz],
+ "%02u-%02u-%04u %02u:%02u:%02u %20s %.*s%s%.*s\n",
+ (result.fe_time.tm_mday ? (result.fe_time.tm_month + 1) : 0),
+ result.fe_time.tm_mday,
+ (result.fe_time.tm_mday ? (result.fe_time.tm_year + 1900) : 0),
+ result.fe_time.tm_hour,
+ result.fe_time.tm_min,
+ result.fe_time.tm_sec,
+ (rc == 'd' ? "<DIR> " :
+ (rc == 'l' ? "<JUNCTION> " : result.fe_size)),
+ (int)result.fe_fnlen, result.fe_fname,
+ ((rc == 'l' && result.fe_lnlen) ? " -> " : ""),
+ (int)((rc == 'l' && result.fe_lnlen) ? result.fe_lnlen : 0),
+ ((rc == 'l' && result.fe_lnlen) ? result.fe_lname : "") );
+ linelen = strlen(&p[*bufz]);
+ *bufp = p;
+ *bufz = *bufz + linelen;
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ FILE *infile = (FILE *)0;
+ FILE *outfile = (FILE *)0;
+ int need_close_in = 0;
+ int need_close_out = 0;
+
+ if (argc > 1)
+ {
+ infile = stdin;
+ if (strcmp(argv[1], "-") == 0)
+ need_close_in = 0;
+ else if ((infile = fopen(argv[1], "r")) != ((FILE *)0))
+ need_close_in = 1;
+ else
+ fprintf(stderr, "Unable to open input file '%s'\n", argv[1]);
+ }
+ if (infile && argc > 2)
+ {
+ outfile = stdout;
+ if (strcmp(argv[2], "-") == 0)
+ need_close_out = 0;
+ else if ((outfile = fopen(argv[2], "w")) != ((FILE *)0))
+ need_close_out = 1;
+ else
+ {
+ fprintf(stderr, "Unable to open output file '%s'\n", argv[2]);
+ fclose(infile);
+ infile = (FILE *)0;
+ }
+ }
+
+ if (!infile)
+ {
+ char *appname = &(argv[0][strlen(argv[0])]);
+ while (appname > argv[0])
+ {
+ appname--;
+ if (*appname == '/' || *appname == '\\' || *appname == ':')
+ {
+ appname++;
+ break;
+ }
+ }
+ fprintf(stderr,
+ "Usage: %s <inputfilename> [<outputfilename>]\n"
+ "\nIf an outout file is specified the results will be"
+ "\nbe post-processed, and only the file entries will appear"
+ "\n(or all comments if there are no file entries)."
+ "\nNot specifying an output file causes %s to run in \"debug\""
+ "\nmode, ie results are printed as lines are parsed."
+ "\nIf a filename is a single dash ('-'), stdin/stdout is used."
+ "\n", appname, appname );
+ }
+ else
+ {
+ char *cmnt_buf = (char *)0;
+ unsigned int cmnt_buf_sz = 0;
+ char *list_buf = (char *)0;
+ unsigned int list_buf_sz = 0;
+
+ struct list_state state;
+ char line[512];
+
+ memset( &state, 0, sizeof(state) );
+ while (fgets(line, sizeof(line), infile))
+ {
+ size_t linelen = strlen(line);
+ if (linelen < (sizeof(line)-1))
+ {
+ if (linelen > 0 && line[linelen-1] == '\n')
+ linelen--;
+ if (do_it( outfile, line, linelen, &state,
+ &cmnt_buf, &cmnt_buf_sz, &list_buf, &list_buf_sz) != 0)
+ {
+ fprintf(stderr, "Insufficient memory. Listing may be incomplete.\n");
+ break;
+ }
+ }
+ else
+ {
+ /* no '\n' found. drop this and everything up to the next '\n' */
+ fprintf(stderr, "drop: %.*s", (int)linelen, line );
+ while (linelen == sizeof(line))
+ {
+ if (!fgets(line, sizeof(line), infile))
+ break;
+ linelen = 0;
+ while (linelen < sizeof(line) && line[linelen] != '\n')
+ linelen++;
+ fprintf(stderr, "%.*s", (int)linelen, line );
+ }
+ fprintf(stderr, "\n");
+ }
+ }
+ if (outfile)
+ {
+ if (list_buf)
+ fwrite( list_buf, 1, list_buf_sz, outfile );
+ else if (cmnt_buf)
+ fwrite( cmnt_buf, 1, cmnt_buf_sz, outfile );
+ }
+ if (list_buf)
+ free(list_buf);
+ if (cmnt_buf)
+ free(cmnt_buf);
+
+ if (need_close_in)
+ fclose(infile);
+ if (outfile && need_close_out)
+ fclose(outfile);
+ }
+
+ return 0;
+}
+#endif
diff --git a/netwerk/streamconv/converters/ParseFTPList.h b/netwerk/streamconv/converters/ParseFTPList.h
new file mode 100644
index 000000000..f4a632a87
--- /dev/null
+++ b/netwerk/streamconv/converters/ParseFTPList.h
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef ParseRTPList_h___
+#define ParseRTPList_h___
+
+#include <stdint.h>
+#include <string.h>
+#include "prtime.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 consistently: 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
+{
+ list_state() {
+ memset(this, 0, sizeof(*this));
+ }
+
+ PRTime now_time; /* needed for year determination */
+ PRExplodedTime now_tm; /* needed for year determination */
+ int32_t lstyle; /* LISTing style */
+ int32_t parsed_one; /* returned anything yet? */
+ char carry_buf[84]; /* for VMS multiline */
+ uint32_t carry_buf_len; /* length of name in carry_buf */
+ uint32_t numlines; /* number of lines seen */
+};
+
+struct list_result
+{
+ int32_t fe_type; /* 'd'(dir) or 'l'(link) or 'f'(file) */
+ const char * fe_fname; /* pointer to filename */
+ uint32_t fe_fnlen; /* length of filename */
+ const char * fe_lname; /* pointer to symlink name */
+ uint32_t fe_lnlen; /* length of symlink name */
+ char fe_size[40]; /* size of file in bytes (<= (2^128 - 1)) */
+ PRExplodedTime fe_time; /* last-modified time */
+ int32_t 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 );
+
+#endif /* !ParseRTPList_h___ */
diff --git a/netwerk/streamconv/converters/moz.build b/netwerk/streamconv/converters/moz.build
new file mode 100644
index 000000000..d190843c6
--- /dev/null
+++ b/netwerk/streamconv/converters/moz.build
@@ -0,0 +1,39 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+XPIDL_SOURCES += [
+ 'nsICompressConvStats.idl'
+]
+
+XPIDL_MODULE = 'necko_http'
+
+UNIFIED_SOURCES += [
+ 'mozTXTToHTMLConv.cpp',
+ 'nsDirIndex.cpp',
+ 'nsDirIndexParser.cpp',
+ 'nsHTTPCompressConv.cpp',
+ 'nsIndexedToHTML.cpp',
+ 'nsMultiMixedConv.cpp',
+ 'nsTXTToHTMLConv.cpp',
+ 'nsUnknownDecoder.cpp',
+]
+
+if 'ftp' in CONFIG['NECKO_PROTOCOLS']:
+ UNIFIED_SOURCES += [
+ 'nsFTPDirListingConv.cpp',
+ 'ParseFTPList.cpp',
+ ]
+
+if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'cocoa':
+ UNIFIED_SOURCES += [
+ 'nsBinHexDecoder.cpp',
+ ]
+
+FINAL_LIBRARY = 'xul'
+
+LOCAL_INCLUDES += [
+ '/netwerk/base',
+]
diff --git a/netwerk/streamconv/converters/mozTXTToHTMLConv.cpp b/netwerk/streamconv/converters/mozTXTToHTMLConv.cpp
new file mode 100644
index 000000000..db23cca35
--- /dev/null
+++ b/netwerk/streamconv/converters/mozTXTToHTMLConv.cpp
@@ -0,0 +1,1427 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozTXTToHTMLConv.h"
+#include "nsNetUtil.h"
+#include "nsUnicharUtils.h"
+#include "nsCRT.h"
+#include "nsIExternalProtocolHandler.h"
+#include "nsIIOService.h"
+#include "nsIURI.h"
+
+#include <algorithm>
+
+#ifdef DEBUG_BenB_Perf
+#include "prtime.h"
+#include "prinrval.h"
+#endif
+
+const double growthRate = 1.2;
+
+// Bug 183111, editor now replaces multiple spaces with leading
+// 0xA0's and a single ending space, so need to treat 0xA0's as spaces.
+// 0xA0 is the Latin1/Unicode character for "non-breaking space (nbsp)"
+// Also recognize the Japanese ideographic space 0x3000 as a space.
+static inline bool IsSpace(const char16_t aChar)
+{
+ return (nsCRT::IsAsciiSpace(aChar) || aChar == 0xA0 || aChar == 0x3000);
+}
+
+// Escape Char will take ch, escape it and append the result to
+// aStringToAppendTo
+void
+mozTXTToHTMLConv::EscapeChar(const char16_t ch, nsString& aStringToAppendTo,
+ bool inAttribute)
+{
+ switch (ch)
+ {
+ case '<':
+ aStringToAppendTo.AppendLiteral("&lt;");
+ break;
+ case '>':
+ aStringToAppendTo.AppendLiteral("&gt;");
+ break;
+ case '&':
+ aStringToAppendTo.AppendLiteral("&amp;");
+ break;
+ case '"':
+ if (inAttribute)
+ {
+ aStringToAppendTo.AppendLiteral("&quot;");
+ break;
+ }
+ // else fall through
+ MOZ_FALLTHROUGH;
+ default:
+ aStringToAppendTo += ch;
+ }
+
+ return;
+}
+
+// EscapeStr takes the passed in string and
+// escapes it IN PLACE.
+void
+mozTXTToHTMLConv::EscapeStr(nsString& aInString, bool inAttribute)
+{
+ // the replace substring routines
+ // don't seem to work if you have a character
+ // in the in string that is also in the replacement
+ // string! =(
+ //aInString.ReplaceSubstring("&", "&amp;");
+ //aInString.ReplaceSubstring("<", "&lt;");
+ //aInString.ReplaceSubstring(">", "&gt;");
+ for (uint32_t i = 0; i < aInString.Length();)
+ {
+ switch (aInString[i])
+ {
+ case '<':
+ aInString.Cut(i, 1);
+ aInString.Insert(NS_LITERAL_STRING("&lt;"), i);
+ i += 4; // skip past the integers we just added
+ break;
+ case '>':
+ aInString.Cut(i, 1);
+ aInString.Insert(NS_LITERAL_STRING("&gt;"), i);
+ i += 4; // skip past the integers we just added
+ break;
+ case '&':
+ aInString.Cut(i, 1);
+ aInString.Insert(NS_LITERAL_STRING("&amp;"), i);
+ i += 5; // skip past the integers we just added
+ break;
+ case '"':
+ if (inAttribute)
+ {
+ aInString.Cut(i, 1);
+ aInString.Insert(NS_LITERAL_STRING("&quot;"), i);
+ i += 6;
+ break;
+ }
+ // else fall through
+ MOZ_FALLTHROUGH;
+ default:
+ i++;
+ }
+ }
+}
+
+void
+mozTXTToHTMLConv::UnescapeStr(const char16_t * aInString, int32_t aStartPos, int32_t aLength, nsString& aOutString)
+{
+ const char16_t * subString = nullptr;
+ for (uint32_t i = aStartPos; int32_t(i) - aStartPos < aLength;)
+ {
+ int32_t remainingChars = i - aStartPos;
+ if (aInString[i] == '&')
+ {
+ subString = &aInString[i];
+ if (!nsCRT::strncmp(subString, u"&lt;", std::min(4, aLength - remainingChars)))
+ {
+ aOutString.Append(char16_t('<'));
+ i += 4;
+ }
+ else if (!nsCRT::strncmp(subString, u"&gt;", std::min(4, aLength - remainingChars)))
+ {
+ aOutString.Append(char16_t('>'));
+ i += 4;
+ }
+ else if (!nsCRT::strncmp(subString, u"&amp;", std::min(5, aLength - remainingChars)))
+ {
+ aOutString.Append(char16_t('&'));
+ i += 5;
+ }
+ else if (!nsCRT::strncmp(subString, u"&quot;", std::min(6, aLength - remainingChars)))
+ {
+ aOutString.Append(char16_t('"'));
+ i += 6;
+ }
+ else
+ {
+ aOutString += aInString[i];
+ i++;
+ }
+ }
+ else
+ {
+ aOutString += aInString[i];
+ i++;
+ }
+ }
+}
+
+void
+mozTXTToHTMLConv::CompleteAbbreviatedURL(const char16_t * aInString, int32_t aInLength,
+ const uint32_t pos, nsString& aOutString)
+{
+ NS_ASSERTION(int32_t(pos) < aInLength, "bad args to CompleteAbbreviatedURL, see bug #190851");
+ if (int32_t(pos) >= aInLength)
+ return;
+
+ if (aInString[pos] == '@')
+ {
+ // only pre-pend a mailto url if the string contains a .domain in it..
+ //i.e. we want to linkify johndoe@foo.com but not "let's meet @8pm"
+ nsDependentString inString(aInString, aInLength);
+ if (inString.FindChar('.', pos) != kNotFound) // if we have a '.' after the @ sign....
+ {
+ aOutString.AssignLiteral("mailto:");
+ aOutString += aInString;
+ }
+ }
+ else if (aInString[pos] == '.')
+ {
+ if (ItMatchesDelimited(aInString, aInLength,
+ u"www.", 4, LT_IGNORE, LT_IGNORE))
+ {
+ aOutString.AssignLiteral("http://");
+ aOutString += aInString;
+ }
+ else if (ItMatchesDelimited(aInString,aInLength, u"ftp.", 4, LT_IGNORE, LT_IGNORE))
+ {
+ aOutString.AssignLiteral("ftp://");
+ aOutString += aInString;
+ }
+ }
+}
+
+bool
+mozTXTToHTMLConv::FindURLStart(const char16_t * aInString, int32_t aInLength,
+ const uint32_t pos, const modetype check,
+ uint32_t& start)
+{
+ switch(check)
+ { // no breaks, because end of blocks is never reached
+ case RFC1738:
+ {
+ if (!nsCRT::strncmp(&aInString[std::max(int32_t(pos - 4), 0)], u"<URL:", 5))
+ {
+ start = pos + 1;
+ return true;
+ }
+ else
+ return false;
+ }
+ case RFC2396E:
+ {
+ nsString temp(aInString, aInLength);
+ int32_t i = pos <= 0 ? kNotFound : temp.RFindCharInSet(u"<>\"", pos - 1);
+ if (i != kNotFound && (temp[uint32_t(i)] == '<' ||
+ temp[uint32_t(i)] == '"'))
+ {
+ start = uint32_t(++i);
+ return start < pos;
+ }
+ else
+ return false;
+ }
+ case freetext:
+ {
+ int32_t i = pos - 1;
+ for (; i >= 0 && (
+ nsCRT::IsAsciiAlpha(aInString[uint32_t(i)]) ||
+ nsCRT::IsAsciiDigit(aInString[uint32_t(i)]) ||
+ aInString[uint32_t(i)] == '+' ||
+ aInString[uint32_t(i)] == '-' ||
+ aInString[uint32_t(i)] == '.'
+ ); i--)
+ ;
+ if (++i >= 0 && uint32_t(i) < pos && nsCRT::IsAsciiAlpha(aInString[uint32_t(i)]))
+ {
+ start = uint32_t(i);
+ return true;
+ }
+ else
+ return false;
+ }
+ case abbreviated:
+ {
+ int32_t i = pos - 1;
+ // This disallows non-ascii-characters for email.
+ // Currently correct, but revisit later after standards changed.
+ bool isEmail = aInString[pos] == (char16_t)'@';
+ // These chars mark the start of the URL
+ for (; i >= 0
+ && aInString[uint32_t(i)] != '>' && aInString[uint32_t(i)] != '<'
+ && aInString[uint32_t(i)] != '"' && aInString[uint32_t(i)] != '\''
+ && aInString[uint32_t(i)] != '`' && aInString[uint32_t(i)] != ','
+ && aInString[uint32_t(i)] != '{' && aInString[uint32_t(i)] != '['
+ && aInString[uint32_t(i)] != '(' && aInString[uint32_t(i)] != '|'
+ && aInString[uint32_t(i)] != '\\'
+ && !IsSpace(aInString[uint32_t(i)])
+ && (!isEmail || nsCRT::IsAscii(aInString[uint32_t(i)]))
+ ; i--)
+ ;
+ if
+ (
+ ++i >= 0 && uint32_t(i) < pos
+ &&
+ (
+ nsCRT::IsAsciiAlpha(aInString[uint32_t(i)]) ||
+ nsCRT::IsAsciiDigit(aInString[uint32_t(i)])
+ )
+ )
+ {
+ start = uint32_t(i);
+ return true;
+ }
+ else
+ return false;
+ }
+ default:
+ return false;
+ } //switch
+}
+
+bool
+mozTXTToHTMLConv::FindURLEnd(const char16_t * aInString, int32_t aInStringLength, const uint32_t pos,
+ const modetype check, const uint32_t start, uint32_t& end)
+{
+ switch(check)
+ { // no breaks, because end of blocks is never reached
+ case RFC1738:
+ case RFC2396E:
+ {
+ nsString temp(aInString, aInStringLength);
+
+ int32_t i = temp.FindCharInSet(u"<>\"", pos + 1);
+ if (i != kNotFound && temp[uint32_t(i--)] ==
+ (check == RFC1738 || temp[start - 1] == '<' ? '>' : '"'))
+ {
+ end = uint32_t(i);
+ return end > pos;
+ }
+ return false;
+ }
+ case freetext:
+ case abbreviated:
+ {
+ uint32_t i = pos + 1;
+ bool isEmail = aInString[pos] == (char16_t)'@';
+ bool seenOpeningParenthesis = false; // there is a '(' earlier in the URL
+ bool seenOpeningSquareBracket = false; // there is a '[' earlier in the URL
+ for (; int32_t(i) < aInStringLength; i++)
+ {
+ // These chars mark the end of the URL
+ if (aInString[i] == '>' || aInString[i] == '<' ||
+ aInString[i] == '"' || aInString[i] == '`' ||
+ aInString[i] == '}' || aInString[i] == '{' ||
+ (aInString[i] == ')' && !seenOpeningParenthesis) ||
+ (aInString[i] == ']' && !seenOpeningSquareBracket) ||
+ // Allow IPv6 adresses like http://[1080::8:800:200C:417A]/foo.
+ (aInString[i] == '[' && i > 2 &&
+ (aInString[i - 1] != '/' || aInString[i - 2] != '/')) ||
+ IsSpace(aInString[i]))
+ break;
+ // Disallow non-ascii-characters for email.
+ // Currently correct, but revisit later after standards changed.
+ if (isEmail && (
+ aInString[i] == '(' || aInString[i] == '\'' ||
+ !nsCRT::IsAscii(aInString[i])))
+ break;
+ if (aInString[i] == '(')
+ seenOpeningParenthesis = true;
+ if (aInString[i] == '[')
+ seenOpeningSquareBracket = true;
+ }
+ // These chars are allowed in the middle of the URL, but not at end.
+ // Technically they are, but are used in normal text after the URL.
+ while (--i > pos && (
+ aInString[i] == '.' || aInString[i] == ',' || aInString[i] == ';' ||
+ aInString[i] == '!' || aInString[i] == '?' || aInString[i] == '-' ||
+ aInString[i] == ':' || aInString[i] == '\''
+ ))
+ ;
+ if (i > pos)
+ {
+ end = i;
+ return true;
+ }
+ return false;
+ }
+ default:
+ return false;
+ } //switch
+}
+
+void
+mozTXTToHTMLConv::CalculateURLBoundaries(const char16_t * aInString, int32_t aInStringLength,
+ const uint32_t pos, const uint32_t whathasbeendone,
+ const modetype check, const uint32_t start, const uint32_t end,
+ nsString& txtURL, nsString& desc,
+ int32_t& replaceBefore, int32_t& replaceAfter)
+{
+ uint32_t descstart = start;
+ switch(check)
+ {
+ case RFC1738:
+ {
+ descstart = start - 5;
+ desc.Append(&aInString[descstart], end - descstart + 2); // include "<URL:" and ">"
+ replaceAfter = end - pos + 1;
+ } break;
+ case RFC2396E:
+ {
+ descstart = start - 1;
+ desc.Append(&aInString[descstart], end - descstart + 2); // include brackets
+ replaceAfter = end - pos + 1;
+ } break;
+ case freetext:
+ case abbreviated:
+ {
+ descstart = start;
+ desc.Append(&aInString[descstart], end - start + 1); // don't include brackets
+ replaceAfter = end - pos;
+ } break;
+ default: break;
+ } //switch
+
+ EscapeStr(desc, false);
+
+ txtURL.Append(&aInString[start], end - start + 1);
+ txtURL.StripWhitespace();
+
+ // FIX ME
+ nsAutoString temp2;
+ ScanTXT(&aInString[descstart], pos - descstart, ~kURLs /*prevents loop*/ & whathasbeendone, temp2);
+ replaceBefore = temp2.Length();
+ return;
+}
+
+bool mozTXTToHTMLConv::ShouldLinkify(const nsCString& aURL)
+{
+ if (!mIOService)
+ return false;
+
+ nsAutoCString scheme;
+ nsresult rv = mIOService->ExtractScheme(aURL, scheme);
+ if(NS_FAILED(rv))
+ return false;
+
+ // Get the handler for this scheme.
+ nsCOMPtr<nsIProtocolHandler> handler;
+ rv = mIOService->GetProtocolHandler(scheme.get(), getter_AddRefs(handler));
+ if(NS_FAILED(rv))
+ return false;
+
+ // Is it an external protocol handler? If not, linkify it.
+ nsCOMPtr<nsIExternalProtocolHandler> externalHandler = do_QueryInterface(handler);
+ if (!externalHandler)
+ return true; // handler is built-in, linkify it!
+
+ // If external app exists for the scheme then linkify it.
+ bool exists;
+ rv = externalHandler->ExternalAppExistsForScheme(scheme, &exists);
+ return(NS_SUCCEEDED(rv) && exists);
+}
+
+bool
+mozTXTToHTMLConv::CheckURLAndCreateHTML(
+ const nsString& txtURL, const nsString& desc, const modetype mode,
+ nsString& outputHTML)
+{
+ // Create *uri from txtURL
+ nsCOMPtr<nsIURI> uri;
+ nsresult rv;
+ // Lazily initialize mIOService
+ if (!mIOService)
+ {
+ mIOService = do_GetIOService();
+
+ if (!mIOService)
+ return false;
+ }
+
+ // See if the url should be linkified.
+ NS_ConvertUTF16toUTF8 utf8URL(txtURL);
+ if (!ShouldLinkify(utf8URL))
+ return false;
+
+ // it would be faster if we could just check to see if there is a protocol
+ // handler for the url and return instead of actually trying to create a url...
+ rv = mIOService->NewURI(utf8URL, nullptr, nullptr, getter_AddRefs(uri));
+
+ // Real work
+ if (NS_SUCCEEDED(rv) && uri)
+ {
+ outputHTML.AssignLiteral("<a class=\"moz-txt-link-");
+ switch(mode)
+ {
+ case RFC1738:
+ outputHTML.AppendLiteral("rfc1738");
+ break;
+ case RFC2396E:
+ outputHTML.AppendLiteral("rfc2396E");
+ break;
+ case freetext:
+ outputHTML.AppendLiteral("freetext");
+ break;
+ case abbreviated:
+ outputHTML.AppendLiteral("abbreviated");
+ break;
+ default: break;
+ }
+ nsAutoString escapedURL(txtURL);
+ EscapeStr(escapedURL, true);
+
+ outputHTML.AppendLiteral("\" href=\"");
+ outputHTML += escapedURL;
+ outputHTML.AppendLiteral("\">");
+ outputHTML += desc;
+ outputHTML.AppendLiteral("</a>");
+ return true;
+ }
+ else
+ return false;
+}
+
+NS_IMETHODIMP mozTXTToHTMLConv::FindURLInPlaintext(const char16_t * aInString, int32_t aInLength, int32_t aPos, int32_t * aStartPos, int32_t * aEndPos)
+{
+ // call FindURL on the passed in string
+ nsAutoString outputHTML; // we'll ignore the generated output HTML
+
+ *aStartPos = -1;
+ *aEndPos = -1;
+
+ FindURL(aInString, aInLength, aPos, kURLs, outputHTML, *aStartPos, *aEndPos);
+
+ return NS_OK;
+}
+
+bool
+mozTXTToHTMLConv::FindURL(const char16_t * aInString, int32_t aInLength, const uint32_t pos,
+ const uint32_t whathasbeendone,
+ nsString& outputHTML, int32_t& replaceBefore, int32_t& replaceAfter)
+{
+ enum statetype {unchecked, invalid, startok, endok, success};
+ static const modetype ranking[] = {RFC1738, RFC2396E, freetext, abbreviated};
+
+ statetype state[mozTXTToHTMLConv_lastMode + 1]; // 0(=unknown)..lastMode
+ /* I don't like this abuse of enums as index for the array,
+ but I don't know a better method */
+
+ // Define, which modes to check
+ /* all modes but abbreviated are checked for text[pos] == ':',
+ only abbreviated for '.', RFC2396E and abbreviated for '@' */
+ for (modetype iState = unknown; iState <= mozTXTToHTMLConv_lastMode;
+ iState = modetype(iState + 1))
+ state[iState] = aInString[pos] == ':' ? unchecked : invalid;
+ switch (aInString[pos])
+ {
+ case '@':
+ state[RFC2396E] = unchecked;
+ MOZ_FALLTHROUGH;
+ case '.':
+ state[abbreviated] = unchecked;
+ break;
+ case ':':
+ state[abbreviated] = invalid;
+ break;
+ default:
+ break;
+ }
+
+ // Test, first successful mode wins, sequence defined by |ranking|
+ int32_t iCheck = 0; // the currently tested modetype
+ modetype check = ranking[iCheck];
+ for (; iCheck < mozTXTToHTMLConv_numberOfModes && state[check] != success;
+ iCheck++)
+ /* check state from last run.
+ If this is the first, check this one, which isn't = success yet */
+ {
+ check = ranking[iCheck];
+
+ uint32_t start, end;
+
+ if (state[check] == unchecked)
+ if (FindURLStart(aInString, aInLength, pos, check, start))
+ state[check] = startok;
+
+ if (state[check] == startok)
+ if (FindURLEnd(aInString, aInLength, pos, check, start, end))
+ state[check] = endok;
+
+ if (state[check] == endok)
+ {
+ nsAutoString txtURL, desc;
+ int32_t resultReplaceBefore, resultReplaceAfter;
+
+ CalculateURLBoundaries(aInString, aInLength, pos, whathasbeendone, check, start, end,
+ txtURL, desc,
+ resultReplaceBefore, resultReplaceAfter);
+
+ if (aInString[pos] != ':')
+ {
+ nsAutoString temp = txtURL;
+ txtURL.SetLength(0);
+ CompleteAbbreviatedURL(temp.get(),temp.Length(), pos - start, txtURL);
+ }
+
+ if (!txtURL.IsEmpty() && CheckURLAndCreateHTML(txtURL, desc, check,
+ outputHTML))
+ {
+ replaceBefore = resultReplaceBefore;
+ replaceAfter = resultReplaceAfter;
+ state[check] = success;
+ }
+ } // if
+ } // for
+ return state[check] == success;
+}
+
+bool
+mozTXTToHTMLConv::ItMatchesDelimited(const char16_t * aInString,
+ int32_t aInLength, const char16_t* rep, int32_t aRepLen,
+ LIMTYPE before, LIMTYPE after)
+{
+
+ // this little method gets called a LOT. I found we were spending a
+ // lot of time just calculating the length of the variable "rep"
+ // over and over again every time we called it. So we're now passing
+ // an integer in here.
+ int32_t textLen = aInLength;
+
+ if
+ (
+ ((before == LT_IGNORE && (after == LT_IGNORE || after == LT_DELIMITER))
+ && textLen < aRepLen) ||
+ ((before != LT_IGNORE || (after != LT_IGNORE && after != LT_DELIMITER))
+ && textLen < aRepLen + 1) ||
+ (before != LT_IGNORE && after != LT_IGNORE && after != LT_DELIMITER
+ && textLen < aRepLen + 2)
+ )
+ return false;
+
+ char16_t text0 = aInString[0];
+ char16_t textAfterPos = aInString[aRepLen + (before == LT_IGNORE ? 0 : 1)];
+
+ if
+ (
+ (before == LT_ALPHA
+ && !nsCRT::IsAsciiAlpha(text0)) ||
+ (before == LT_DIGIT
+ && !nsCRT::IsAsciiDigit(text0)) ||
+ (before == LT_DELIMITER
+ &&
+ (
+ nsCRT::IsAsciiAlpha(text0) ||
+ nsCRT::IsAsciiDigit(text0) ||
+ text0 == *rep
+ )) ||
+ (after == LT_ALPHA
+ && !nsCRT::IsAsciiAlpha(textAfterPos)) ||
+ (after == LT_DIGIT
+ && !nsCRT::IsAsciiDigit(textAfterPos)) ||
+ (after == LT_DELIMITER
+ &&
+ (
+ nsCRT::IsAsciiAlpha(textAfterPos) ||
+ nsCRT::IsAsciiDigit(textAfterPos) ||
+ textAfterPos == *rep
+ )) ||
+ !Substring(Substring(aInString, aInString+aInLength),
+ (before == LT_IGNORE ? 0 : 1),
+ aRepLen).Equals(Substring(rep, rep+aRepLen),
+ nsCaseInsensitiveStringComparator())
+ )
+ return false;
+
+ return true;
+}
+
+uint32_t
+mozTXTToHTMLConv::NumberOfMatches(const char16_t * aInString, int32_t aInStringLength,
+ const char16_t* rep, int32_t aRepLen, LIMTYPE before, LIMTYPE after)
+{
+ uint32_t result = 0;
+
+ for (int32_t i = 0; i < aInStringLength; i++)
+ {
+ const char16_t * indexIntoString = &aInString[i];
+ if (ItMatchesDelimited(indexIntoString, aInStringLength - i, rep, aRepLen, before, after))
+ result++;
+ }
+ return result;
+}
+
+
+// NOTE: the converted html for the phrase is appended to aOutString
+// tagHTML and attributeHTML are plain ASCII (literal strings, in fact)
+bool
+mozTXTToHTMLConv::StructPhraseHit(const char16_t * aInString, int32_t aInStringLength, bool col0,
+ const char16_t* tagTXT, int32_t aTagTXTLen,
+ const char* tagHTML, const char* attributeHTML,
+ nsString& aOutString, uint32_t& openTags)
+{
+ /* We're searching for the following pattern:
+ LT_DELIMITER - "*" - ALPHA -
+ [ some text (maybe more "*"-pairs) - ALPHA ] "*" - LT_DELIMITER.
+ <strong> is only inserted, if existence of a pair could be verified
+ We use the first opening/closing tag, if we can choose */
+
+ const char16_t * newOffset = aInString;
+ int32_t newLength = aInStringLength;
+ if (!col0) // skip the first element?
+ {
+ newOffset = &aInString[1];
+ newLength = aInStringLength - 1;
+ }
+
+ // opening tag
+ if
+ (
+ ItMatchesDelimited(aInString, aInStringLength, tagTXT, aTagTXTLen,
+ (col0 ? LT_IGNORE : LT_DELIMITER), LT_ALPHA) // is opening tag
+ && NumberOfMatches(newOffset, newLength, tagTXT, aTagTXTLen,
+ LT_ALPHA, LT_DELIMITER) // remaining closing tags
+ > openTags
+ )
+ {
+ openTags++;
+ aOutString.Append('<');
+ aOutString.AppendASCII(tagHTML);
+ aOutString.Append(char16_t(' '));
+ aOutString.AppendASCII(attributeHTML);
+ aOutString.AppendLiteral("><span class=\"moz-txt-tag\">");
+ aOutString.Append(tagTXT);
+ aOutString.AppendLiteral("</span>");
+ return true;
+ }
+
+ // closing tag
+ else if (openTags > 0
+ && ItMatchesDelimited(aInString, aInStringLength, tagTXT, aTagTXTLen, LT_ALPHA, LT_DELIMITER))
+ {
+ openTags--;
+ aOutString.AppendLiteral("<span class=\"moz-txt-tag\">");
+ aOutString.Append(tagTXT);
+ aOutString.AppendLiteral("</span></");
+ aOutString.AppendASCII(tagHTML);
+ aOutString.Append(char16_t('>'));
+ return true;
+ }
+
+ return false;
+}
+
+
+bool
+mozTXTToHTMLConv::SmilyHit(const char16_t * aInString, int32_t aLength, bool col0,
+ const char* tagTXT, const char* imageName,
+ nsString& outputHTML, int32_t& glyphTextLen)
+{
+ if ( !aInString || !tagTXT || !imageName )
+ return false;
+
+ int32_t tagLen = strlen(tagTXT);
+
+ uint32_t delim = (col0 ? 0 : 1) + tagLen;
+
+ if
+ (
+ (col0 || IsSpace(aInString[0]))
+ &&
+ (
+ aLength <= int32_t(delim) ||
+ IsSpace(aInString[delim]) ||
+ (aLength > int32_t(delim + 1)
+ &&
+ (
+ aInString[delim] == '.' ||
+ aInString[delim] == ',' ||
+ aInString[delim] == ';' ||
+ aInString[delim] == '8' ||
+ aInString[delim] == '>' ||
+ aInString[delim] == '!' ||
+ aInString[delim] == '?'
+ )
+ && IsSpace(aInString[delim + 1]))
+ )
+ && ItMatchesDelimited(aInString, aLength, NS_ConvertASCIItoUTF16(tagTXT).get(), tagLen,
+ col0 ? LT_IGNORE : LT_DELIMITER, LT_IGNORE)
+ // Note: tests at different pos for LT_IGNORE and LT_DELIMITER
+ )
+ {
+ if (!col0)
+ {
+ outputHTML.Truncate();
+ outputHTML.Append(char16_t(' '));
+ }
+
+ outputHTML.AppendLiteral("<span class=\""); // <span class="
+ AppendASCIItoUTF16(imageName, outputHTML); // e.g. smiley-frown
+ outputHTML.AppendLiteral("\" title=\""); // " title="
+ AppendASCIItoUTF16(tagTXT, outputHTML); // smiley tooltip
+ outputHTML.AppendLiteral("\"><span>"); // "><span>
+ AppendASCIItoUTF16(tagTXT, outputHTML); // original text
+ outputHTML.AppendLiteral("</span></span>"); // </span></span>
+ glyphTextLen = (col0 ? 0 : 1) + tagLen;
+ return true;
+ }
+
+ return false;
+}
+
+// the glyph is appended to aOutputString instead of the original string...
+bool
+mozTXTToHTMLConv::GlyphHit(const char16_t * aInString, int32_t aInLength, bool col0,
+ nsString& aOutputString, int32_t& glyphTextLen)
+{
+ char16_t text0 = aInString[0];
+ char16_t text1 = aInString[1];
+ char16_t firstChar = (col0 ? text0 : text1);
+
+ // temporary variable used to store the glyph html text
+ nsAutoString outputHTML;
+ bool bTestSmilie;
+ bool bArg = false;
+ int i;
+
+ // refactor some of this mess to avoid code duplication and speed execution a bit
+ // there are two cases that need to be tried one after another. To avoid a lot of
+ // duplicate code, rolling into a loop
+
+ i = 0;
+ while ( i < 2 )
+ {
+ bTestSmilie = false;
+ if ( !i && (firstChar == ':' || firstChar == ';' || firstChar == '=' || firstChar == '>' || firstChar == '8' || firstChar == 'O'))
+ {
+ // first test passed
+
+ bTestSmilie = true;
+ bArg = col0;
+ }
+ if ( i && col0 && ( text1 == ':' || text1 == ';' || text1 == '=' || text1 == '>' || text1 == '8' || text1 == 'O' ) )
+ {
+ // second test passed
+
+ bTestSmilie = true;
+ bArg = false;
+ }
+ if ( bTestSmilie && (
+ SmilyHit(aInString, aInLength, bArg,
+ ":-)",
+ "moz-smiley-s1", // smile
+ outputHTML, glyphTextLen) ||
+
+ SmilyHit(aInString, aInLength, bArg,
+ ":)",
+ "moz-smiley-s1", // smile
+ outputHTML, glyphTextLen) ||
+
+ SmilyHit(aInString, aInLength, bArg,
+ ":-D",
+ "moz-smiley-s5", // laughing
+ outputHTML, glyphTextLen) ||
+
+ SmilyHit(aInString, aInLength, bArg,
+ ":-(",
+ "moz-smiley-s2", // frown
+ outputHTML, glyphTextLen) ||
+
+ SmilyHit(aInString, aInLength, bArg,
+ ":(",
+ "moz-smiley-s2", // frown
+ outputHTML, glyphTextLen) ||
+
+ SmilyHit(aInString, aInLength, bArg,
+ ":-[",
+ "moz-smiley-s6", // embarassed
+ outputHTML, glyphTextLen) ||
+
+ SmilyHit(aInString, aInLength, bArg,
+ ";-)",
+ "moz-smiley-s3", // wink
+ outputHTML, glyphTextLen) ||
+
+ SmilyHit(aInString, aInLength, col0,
+ ";)",
+ "moz-smiley-s3", // wink
+ outputHTML, glyphTextLen) ||
+
+ SmilyHit(aInString, aInLength, bArg,
+ ":-\\",
+ "moz-smiley-s7", // undecided
+ outputHTML, glyphTextLen) ||
+
+ SmilyHit(aInString, aInLength, bArg,
+ ":-P",
+ "moz-smiley-s4", // tongue
+ outputHTML, glyphTextLen) ||
+
+ SmilyHit(aInString, aInLength, bArg,
+ ";-P",
+ "moz-smiley-s4", // tongue
+ outputHTML, glyphTextLen) ||
+
+ SmilyHit(aInString, aInLength, bArg,
+ "=-O",
+ "moz-smiley-s8", // surprise
+ outputHTML, glyphTextLen) ||
+
+ SmilyHit(aInString, aInLength, bArg,
+ ":-*",
+ "moz-smiley-s9", // kiss
+ outputHTML, glyphTextLen) ||
+
+ SmilyHit(aInString, aInLength, bArg,
+ ">:o",
+ "moz-smiley-s10", // yell
+ outputHTML, glyphTextLen) ||
+
+ SmilyHit(aInString, aInLength, bArg,
+ ">:-o",
+ "moz-smiley-s10", // yell
+ outputHTML, glyphTextLen) ||
+
+ SmilyHit(aInString, aInLength, bArg,
+ "8-)",
+ "moz-smiley-s11", // cool
+ outputHTML, glyphTextLen) ||
+
+ SmilyHit(aInString, aInLength, bArg,
+ ":-$",
+ "moz-smiley-s12", // money
+ outputHTML, glyphTextLen) ||
+
+ SmilyHit(aInString, aInLength, bArg,
+ ":-!",
+ "moz-smiley-s13", // foot
+ outputHTML, glyphTextLen) ||
+
+ SmilyHit(aInString, aInLength, bArg,
+ "O:-)",
+ "moz-smiley-s14", // innocent
+ outputHTML, glyphTextLen) ||
+
+ SmilyHit(aInString, aInLength, bArg,
+ ":'(",
+ "moz-smiley-s15", // cry
+ outputHTML, glyphTextLen) ||
+
+ SmilyHit(aInString, aInLength, bArg,
+ ":-X",
+ "moz-smiley-s16", // sealed
+ outputHTML, glyphTextLen)
+ )
+ )
+ {
+ aOutputString.Append(outputHTML);
+ return true;
+ }
+ i++;
+ }
+ if (text0 == '\f')
+ {
+ aOutputString.AppendLiteral("<span class='moz-txt-formfeed'></span>");
+ glyphTextLen = 1;
+ return true;
+ }
+ if (text0 == '+' || text1 == '+')
+ {
+ if (ItMatchesDelimited(aInString, aInLength,
+ u" +/-", 4,
+ LT_IGNORE, LT_IGNORE))
+ {
+ aOutputString.AppendLiteral(" &plusmn;");
+ glyphTextLen = 4;
+ return true;
+ }
+ if (col0 && ItMatchesDelimited(aInString, aInLength,
+ u"+/-", 3,
+ LT_IGNORE, LT_IGNORE))
+ {
+ aOutputString.AppendLiteral("&plusmn;");
+ glyphTextLen = 3;
+ return true;
+ }
+ }
+
+ // x^2 => x<sup>2</sup>, also handle powers x^-2, x^0.5
+ // implement regular expression /[\dA-Za-z\)\]}]\^-?\d+(\.\d+)*[^\dA-Za-z]/
+ if
+ (
+ text1 == '^'
+ &&
+ (
+ nsCRT::IsAsciiDigit(text0) || nsCRT::IsAsciiAlpha(text0) ||
+ text0 == ')' || text0 == ']' || text0 == '}'
+ )
+ &&
+ (
+ (2 < aInLength && nsCRT::IsAsciiDigit(aInString[2])) ||
+ (3 < aInLength && aInString[2] == '-' && nsCRT::IsAsciiDigit(aInString[3]))
+ )
+ )
+ {
+ // Find first non-digit
+ int32_t delimPos = 3; // skip "^" and first digit (or '-')
+ for (; delimPos < aInLength
+ &&
+ (
+ nsCRT::IsAsciiDigit(aInString[delimPos]) ||
+ (aInString[delimPos] == '.' && delimPos + 1 < aInLength &&
+ nsCRT::IsAsciiDigit(aInString[delimPos + 1]))
+ );
+ delimPos++)
+ ;
+
+ if (delimPos < aInLength && nsCRT::IsAsciiAlpha(aInString[delimPos]))
+ {
+ return false;
+ }
+
+ outputHTML.Truncate();
+ outputHTML += text0;
+ outputHTML.AppendLiteral(
+ "<sup class=\"moz-txt-sup\">"
+ "<span style=\"display:inline-block;width:0;height:0;overflow:hidden\">"
+ "^</span>");
+
+ aOutputString.Append(outputHTML);
+ aOutputString.Append(&aInString[2], delimPos - 2);
+ aOutputString.AppendLiteral("</sup>");
+
+ glyphTextLen = delimPos /* - 1 + 1 */ ;
+ return true;
+ }
+ /*
+ The following strings are not substituted:
+ |TXT |HTML |Reason
+ +------+---------+----------
+ -> &larr; Bug #454
+ => &lArr; dito
+ <- &rarr; dito
+ <= &rArr; dito
+ (tm) &trade; dito
+ 1/4 &frac14; is triggered by 1/4 Part 1, 2/4 Part 2, ...
+ 3/4 &frac34; dito
+ 1/2 &frac12; similar
+ */
+ return false;
+}
+
+/***************************************************************************
+ Library-internal Interface
+****************************************************************************/
+
+mozTXTToHTMLConv::mozTXTToHTMLConv()
+{
+}
+
+mozTXTToHTMLConv::~mozTXTToHTMLConv()
+{
+}
+
+NS_IMPL_ISUPPORTS(mozTXTToHTMLConv,
+ mozITXTToHTMLConv,
+ nsIStreamConverter,
+ nsIStreamListener,
+ nsIRequestObserver)
+
+int32_t
+mozTXTToHTMLConv::CiteLevelTXT(const char16_t *line,
+ uint32_t& logLineStart)
+{
+ int32_t result = 0;
+ int32_t lineLength = NS_strlen(line);
+
+ bool moreCites = true;
+ while (moreCites)
+ {
+ /* E.g. the following lines count as quote:
+
+ > text
+ //#ifdef QUOTE_RECOGNITION_AGGRESSIVE
+ >text
+ //#ifdef QUOTE_RECOGNITION_AGGRESSIVE
+ > text
+ ] text
+ USER> text
+ USER] text
+ //#endif
+
+ logLineStart is the position of "t" in this example
+ */
+ uint32_t i = logLineStart;
+
+#ifdef QUOTE_RECOGNITION_AGGRESSIVE
+ for (; int32_t(i) < lineLength && IsSpace(line[i]); i++)
+ ;
+ for (; int32_t(i) < lineLength && nsCRT::IsAsciiAlpha(line[i])
+ && nsCRT::IsUpper(line[i]) ; i++)
+ ;
+ if (int32_t(i) < lineLength && (line[i] == '>' || line[i] == ']'))
+#else
+ if (int32_t(i) < lineLength && line[i] == '>')
+#endif
+ {
+ i++;
+ if (int32_t(i) < lineLength && line[i] == ' ')
+ i++;
+ // sendmail/mbox
+ // Placed here for performance increase
+ const char16_t * indexString = &line[logLineStart];
+ // here, |logLineStart < lineLength| is always true
+ uint32_t minlength = std::min(uint32_t(6), NS_strlen(indexString));
+ if (Substring(indexString,
+ indexString+minlength).Equals(Substring(NS_LITERAL_STRING(">From "), 0, minlength),
+ nsCaseInsensitiveStringComparator()))
+ //XXX RFC2646
+ moreCites = false;
+ else
+ {
+ result++;
+ logLineStart = i;
+ }
+ }
+ else
+ moreCites = false;
+ }
+
+ return result;
+}
+
+void
+mozTXTToHTMLConv::ScanTXT(const char16_t * aInString, int32_t aInStringLength, uint32_t whattodo, nsString& aOutString)
+{
+ bool doURLs = 0 != (whattodo & kURLs);
+ bool doGlyphSubstitution = 0 != (whattodo & kGlyphSubstitution);
+ bool doStructPhrase = 0 != (whattodo & kStructPhrase);
+
+ uint32_t structPhrase_strong = 0; // Number of currently open tags
+ uint32_t structPhrase_underline = 0;
+ uint32_t structPhrase_italic = 0;
+ uint32_t structPhrase_code = 0;
+
+ nsAutoString outputHTML; // moved here for performance increase
+
+ for(uint32_t i = 0; int32_t(i) < aInStringLength;)
+ {
+ if (doGlyphSubstitution)
+ {
+ int32_t glyphTextLen;
+ if (GlyphHit(&aInString[i], aInStringLength - i, i == 0, aOutString, glyphTextLen))
+ {
+ i += glyphTextLen;
+ continue;
+ }
+ }
+
+ if (doStructPhrase)
+ {
+ const char16_t * newOffset = aInString;
+ int32_t newLength = aInStringLength;
+ if (i > 0 ) // skip the first element?
+ {
+ newOffset = &aInString[i-1];
+ newLength = aInStringLength - i + 1;
+ }
+
+ switch (aInString[i]) // Performance increase
+ {
+ case '*':
+ if (StructPhraseHit(newOffset, newLength, i == 0,
+ u"*", 1,
+ "b", "class=\"moz-txt-star\"",
+ aOutString, structPhrase_strong))
+ {
+ i++;
+ continue;
+ }
+ break;
+ case '/':
+ if (StructPhraseHit(newOffset, newLength, i == 0,
+ u"/", 1,
+ "i", "class=\"moz-txt-slash\"",
+ aOutString, structPhrase_italic))
+ {
+ i++;
+ continue;
+ }
+ break;
+ case '_':
+ if (StructPhraseHit(newOffset, newLength, i == 0,
+ u"_", 1,
+ "span" /* <u> is deprecated */,
+ "class=\"moz-txt-underscore\"",
+ aOutString, structPhrase_underline))
+ {
+ i++;
+ continue;
+ }
+ break;
+ case '|':
+ if (StructPhraseHit(newOffset, newLength, i == 0,
+ u"|", 1,
+ "code", "class=\"moz-txt-verticalline\"",
+ aOutString, structPhrase_code))
+ {
+ i++;
+ continue;
+ }
+ break;
+ }
+ }
+
+ if (doURLs)
+ {
+ switch (aInString[i])
+ {
+ case ':':
+ case '@':
+ case '.':
+ if ( (i == 0 || ((i > 0) && aInString[i - 1] != ' ')) && aInString[i +1] != ' ') // Performance increase
+ {
+ int32_t replaceBefore;
+ int32_t replaceAfter;
+ if (FindURL(aInString, aInStringLength, i, whattodo,
+ outputHTML, replaceBefore, replaceAfter)
+ && structPhrase_strong + structPhrase_italic +
+ structPhrase_underline + structPhrase_code == 0
+ /* workaround for bug #19445 */ )
+ {
+ aOutString.Cut(aOutString.Length() - replaceBefore, replaceBefore);
+ aOutString += outputHTML;
+ i += replaceAfter + 1;
+ continue;
+ }
+ }
+ break;
+ } //switch
+ }
+
+ switch (aInString[i])
+ {
+ // Special symbols
+ case '<':
+ case '>':
+ case '&':
+ EscapeChar(aInString[i], aOutString, false);
+ i++;
+ break;
+ // Normal characters
+ default:
+ aOutString += aInString[i];
+ i++;
+ break;
+ }
+ }
+}
+
+void
+mozTXTToHTMLConv::ScanHTML(nsString& aInString, uint32_t whattodo, nsString &aOutString)
+{
+ // some common variables we were recalculating
+ // every time inside the for loop...
+ int32_t lengthOfInString = aInString.Length();
+ const char16_t * uniBuffer = aInString.get();
+
+#ifdef DEBUG_BenB_Perf
+ PRTime parsing_start = PR_IntervalNow();
+#endif
+
+ // Look for simple entities not included in a tags and scan them.
+ // Skip all tags ("<[...]>") and content in an a link tag ("<a [...]</a>"),
+ // comment tag ("<!--[...]-->"), style tag, script tag or head tag.
+ // Unescape the rest (text between tags) and pass it to ScanTXT.
+ nsAutoCString canFollow(" \f\n\r\t>");
+ for (int32_t i = 0; i < lengthOfInString;)
+ {
+ if (aInString[i] == '<') // html tag
+ {
+ int32_t start = i;
+ if (i + 2 < lengthOfInString &&
+ nsCRT::ToLower(aInString[i + 1]) == 'a' &&
+ canFollow.FindChar(aInString[i + 2]) != kNotFound)
+ // if a tag, skip until </a>.
+ // Make sure there's a white-space character after, not to match "abbr".
+ {
+ i = aInString.Find("</a>", true, i);
+ if (i == kNotFound)
+ i = lengthOfInString;
+ else
+ i += 4;
+ }
+ else if (Substring(aInString, i + 1, 3).LowerCaseEqualsASCII("!--"))
+ // if out-commended code, skip until -->
+ {
+ i = aInString.Find("-->", false, i);
+ if (i == kNotFound)
+ i = lengthOfInString;
+ else
+ i += 3;
+ }
+ else if (i + 6 < lengthOfInString &&
+ Substring(aInString, i + 1, 5).LowerCaseEqualsASCII("style") &&
+ canFollow.FindChar(aInString[i + 6]) != kNotFound)
+ // if style tag, skip until </style>
+ {
+ i = aInString.Find("</style>", true, i);
+ if (i == kNotFound)
+ i = lengthOfInString;
+ else
+ i += 8;
+ }
+ else if (i + 7 < lengthOfInString &&
+ Substring(aInString, i + 1, 6).LowerCaseEqualsASCII("script") &&
+ canFollow.FindChar(aInString[i + 7]) != kNotFound)
+ // if script tag, skip until </script>
+ {
+ i = aInString.Find("</script>", true, i);
+ if (i == kNotFound)
+ i = lengthOfInString;
+ else
+ i += 9;
+ }
+ else if (i + 5 < lengthOfInString &&
+ Substring(aInString, i + 1, 4).LowerCaseEqualsASCII("head") &&
+ canFollow.FindChar(aInString[i + 5]) != kNotFound)
+ // if head tag, skip until </head>
+ // Make sure not to match <header>.
+ {
+ i = aInString.Find("</head>", true, i);
+ if (i == kNotFound)
+ i = lengthOfInString;
+ else
+ i += 7;
+ }
+ else // just skip tag (attributes etc.)
+ {
+ i = aInString.FindChar('>', i);
+ if (i == kNotFound)
+ i = lengthOfInString;
+ else
+ i++;
+ }
+ aOutString.Append(&uniBuffer[start], i - start);
+ }
+ else
+ {
+ uint32_t start = uint32_t(i);
+ i = aInString.FindChar('<', i);
+ if (i == kNotFound)
+ i = lengthOfInString;
+
+ nsString tempString;
+ tempString.SetCapacity(uint32_t((uint32_t(i) - start) * growthRate));
+ UnescapeStr(uniBuffer, start, uint32_t(i) - start, tempString);
+ ScanTXT(tempString.get(), tempString.Length(), whattodo, aOutString);
+ }
+ }
+
+#ifdef DEBUG_BenB_Perf
+ printf("ScanHTML time: %d ms\n", PR_IntervalToMilliseconds(PR_IntervalNow() - parsing_start));
+#endif
+}
+
+/****************************************************************************
+ XPCOM Interface
+*****************************************************************************/
+
+NS_IMETHODIMP
+mozTXTToHTMLConv::Convert(nsIInputStream *aFromStream,
+ const char *aFromType,
+ const char *aToType,
+ nsISupports *aCtxt, nsIInputStream **_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+mozTXTToHTMLConv::AsyncConvertData(const char *aFromType,
+ const char *aToType,
+ nsIStreamListener *aListener, nsISupports *aCtxt) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+mozTXTToHTMLConv::OnDataAvailable(nsIRequest* request, nsISupports *ctxt,
+ nsIInputStream *inStr, uint64_t sourceOffset,
+ uint32_t count)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+mozTXTToHTMLConv::OnStartRequest(nsIRequest* request, nsISupports *ctxt)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+mozTXTToHTMLConv::OnStopRequest(nsIRequest* request, nsISupports *ctxt,
+ nsresult aStatus)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+mozTXTToHTMLConv::CiteLevelTXT(const char16_t *line, uint32_t *logLineStart,
+ uint32_t *_retval)
+{
+ if (!logLineStart || !_retval || !line)
+ return NS_ERROR_NULL_POINTER;
+ *_retval = CiteLevelTXT(line, *logLineStart);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+mozTXTToHTMLConv::ScanTXT(const char16_t *text, uint32_t whattodo,
+ char16_t **_retval)
+{
+ NS_ENSURE_ARG(text);
+
+ // FIX ME!!!
+ nsString outString;
+ int32_t inLength = NS_strlen(text);
+ // by setting a large capacity up front, we save time
+ // when appending characters to the output string because we don't
+ // need to reallocate and re-copy the characters already in the out String.
+ NS_ASSERTION(inLength, "ScanTXT passed 0 length string");
+ if (inLength == 0) {
+ *_retval = NS_strdup(text);
+ return NS_OK;
+ }
+
+ outString.SetCapacity(uint32_t(inLength * growthRate));
+ ScanTXT(text, inLength, whattodo, outString);
+
+ *_retval = ToNewUnicode(outString);
+ return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+NS_IMETHODIMP
+mozTXTToHTMLConv::ScanHTML(const char16_t *text, uint32_t whattodo,
+ char16_t **_retval)
+{
+ NS_ENSURE_ARG(text);
+
+ // FIX ME!!!
+ nsString outString;
+ nsString inString (text); // look at this nasty extra copy of the entire input buffer!
+ outString.SetCapacity(uint32_t(inString.Length() * growthRate));
+
+ ScanHTML(inString, whattodo, outString);
+ *_retval = ToNewUnicode(outString);
+ return *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+}
+
+nsresult
+MOZ_NewTXTToHTMLConv(mozTXTToHTMLConv** aConv)
+{
+ NS_PRECONDITION(aConv != nullptr, "null ptr");
+ if (!aConv)
+ return NS_ERROR_NULL_POINTER;
+
+ *aConv = new mozTXTToHTMLConv();
+ if (!*aConv)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(*aConv);
+ // return (*aConv)->Init();
+ return NS_OK;
+}
diff --git a/netwerk/streamconv/converters/mozTXTToHTMLConv.h b/netwerk/streamconv/converters/mozTXTToHTMLConv.h
new file mode 100644
index 000000000..731cc0737
--- /dev/null
+++ b/netwerk/streamconv/converters/mozTXTToHTMLConv.h
@@ -0,0 +1,294 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ Description: Currently only functions to enhance plain text with HTML tags. See mozITXTToHTMLConv. Stream conversion is defunct.
+*/
+
+#ifndef _mozTXTToHTMLConv_h__
+#define _mozTXTToHTMLConv_h__
+
+#include "mozITXTToHTMLConv.h"
+#include "nsString.h"
+#include "nsCOMPtr.h"
+
+class nsIIOService;
+
+class mozTXTToHTMLConv : public mozITXTToHTMLConv
+{
+
+ virtual ~mozTXTToHTMLConv();
+
+//////////////////////////////////////////////////////////
+public:
+//////////////////////////////////////////////////////////
+
+ mozTXTToHTMLConv();
+ NS_DECL_ISUPPORTS
+
+ NS_DECL_MOZITXTTOHTMLCONV
+ NS_DECL_NSIREQUESTOBSERVER
+ NS_DECL_NSISTREAMLISTENER
+ NS_DECL_NSISTREAMCONVERTER
+
+/**
+ see mozITXTToHTMLConv::ScanTXT
+ */
+ void ScanTXT(const char16_t * aInString, int32_t aInStringLength, uint32_t whattodo, nsString& aOutString);
+
+/**
+ see mozITXTToHTMLConv::ScanHTML. We will modify aInString potentially...
+ */
+ void ScanHTML(nsString& aInString, uint32_t whattodo, nsString &aOutString);
+
+/**
+ see mozITXTToHTMLConv::CiteLevelTXT
+ */
+ int32_t CiteLevelTXT(const char16_t * line,uint32_t& logLineStart);
+
+
+//////////////////////////////////////////////////////////
+protected:
+//////////////////////////////////////////////////////////
+ nsCOMPtr<nsIIOService> mIOService; // for performance reasons, cache the netwerk service...
+/**
+ Completes<ul>
+ <li>Case 1: mailto: "mozilla@bucksch.org" -> "mailto:mozilla@bucksch.org"
+ <li>Case 2: http: "www.mozilla.org" -> "http://www.mozilla.org"
+ <li>Case 3: ftp: "ftp.mozilla.org" -> "ftp://www.mozilla.org"
+ </ul>
+ It does no check, if the resulting URL is valid.
+ @param text (in): abbreviated URL
+ @param pos (in): position of "@" (case 1) or first "." (case 2 and 3)
+ @return Completed URL at success and empty string at failure
+ */
+ void CompleteAbbreviatedURL(const char16_t * aInString, int32_t aInLength,
+ const uint32_t pos, nsString& aOutString);
+
+
+//////////////////////////////////////////////////////////
+private:
+//////////////////////////////////////////////////////////
+
+ enum LIMTYPE
+ {
+ LT_IGNORE, // limitation not checked
+ LT_DELIMITER, // not alphanumeric and not rep[0]. End of text is also ok.
+ LT_ALPHA, // alpha char
+ LT_DIGIT
+ };
+
+/**
+ @param text (in): the string to search through.<p>
+ If before = IGNORE,<br>
+ rep is compared starting at 1. char of text (text[0]),<br>
+ else starting at 2. char of text (text[1]).
+ Chars after "after"-delimiter are ignored.
+ @param rep (in): the string to look for
+ @param aRepLen (in): the number of bytes in the string to look for
+ @param before (in): limitation before rep
+ @param after (in): limitation after rep
+ @return true, if rep is found and limitation spec is met or rep is empty
+*/
+ bool ItMatchesDelimited(const char16_t * aInString, int32_t aInLength,
+ const char16_t * rep, int32_t aRepLen, LIMTYPE before, LIMTYPE after);
+
+/**
+ @param see ItMatchesDelimited
+ @return Number of ItMatchesDelimited in text
+*/
+ uint32_t NumberOfMatches(const char16_t * aInString, int32_t aInStringLength,
+ const char16_t* rep, int32_t aRepLen, LIMTYPE before, LIMTYPE after);
+
+/**
+ Currently only changes "<", ">" and "&". All others stay as they are.<p>
+ "Char" in function name to avoid side effects with nsString(ch)
+ constructors.
+ @param ch (in)
+ @param aStringToAppendto (out) - the string to append the escaped
+ string to.
+ @param inAttribute (in) - will escape quotes, too (which is
+ only needed for attribute values)
+*/
+ void EscapeChar(const char16_t ch, nsString& aStringToAppendto,
+ bool inAttribute);
+
+/**
+ See EscapeChar. Escapes the string in place.
+*/
+ void EscapeStr(nsString& aInString, bool inAttribute);
+
+/**
+ Currently only reverts "<", ">" and "&". All others stay as they are.<p>
+ @param aInString (in) HTML string
+ @param aStartPos (in) start index into the buffer
+ @param aLength (in) length of the buffer
+ @param aOutString (out) unescaped buffer
+*/
+ void UnescapeStr(const char16_t * aInString, int32_t aStartPos,
+ int32_t aLength, nsString& aOutString);
+
+/**
+ <em>Note</em>: I use different strategies to pass context between the
+ functions (full text and pos vs. cutted text and col0, glphyTextLen vs.
+ replaceBefore/-After). It makes some sense, but is hard to understand
+ (maintain) :-(.
+*/
+
+/**
+ <p><em>Note:</em> replaceBefore + replaceAfter + 1 (for char at pos) chars
+ in text should be replaced by outputHTML.</p>
+ <p><em>Note:</em> This function should be able to process a URL on multiple
+ lines, but currently, ScanForURLs is called for every line, so it can't.</p>
+ @param text (in): includes possibly a URL
+ @param pos (in): position in text, where either ":", "." or "@" are found
+ @param whathasbeendone (in): What the calling ScanTXT did/has to do with the
+ (not-linkified) text, i.e. usually the "whattodo" parameter.
+ (Needed to calculate replaceBefore.) NOT what will be done with
+ the content of the link.
+ @param outputHTML (out): URL with HTML-a tag
+ @param replaceBefore (out): Number of chars of URL before pos
+ @param replaceAfter (out): Number of chars of URL after pos
+ @return URL found
+*/
+ bool FindURL(const char16_t * aInString, int32_t aInLength, const uint32_t pos,
+ const uint32_t whathasbeendone,
+ nsString& outputHTML, int32_t& replaceBefore, int32_t& replaceAfter);
+
+ enum modetype {
+ unknown,
+ RFC1738, /* Check, if RFC1738, APPENDIX compliant,
+ like "<URL:http://www.mozilla.org>". */
+ RFC2396E, /* RFC2396, APPENDIX E allows anglebrackets (like
+ "<http://www.mozilla.org>") (without "URL:") or
+ quotation marks(like ""http://www.mozilla.org"").
+ Also allow email addresses without scheme,
+ e.g. "<mozilla@bucksch.org>" */
+ freetext, /* assume heading scheme
+ with "[a-zA-Z][a-zA-Z0-9+\-\.]*:" like "news:"
+ (see RFC2396, Section 3.1).
+ Certain characters (see code) or any whitespace
+ (including linebreaks) end the URL.
+ Other certain (punctation) characters (see code)
+ at the end are stripped off. */
+ abbreviated /* Similar to freetext, but without scheme, e.g.
+ "www.mozilla.org", "ftp.mozilla.org" and
+ "mozilla@bucksch.org". */
+ /* RFC1738 and RFC2396E type URLs may use multiple lines,
+ whitespace is stripped. Special characters like ")" stay intact.*/
+ };
+
+/**
+ * @param text (in), pos (in): see FindURL
+ * @param check (in): Start must be conform with this mode
+ * @param start (out): Position in text, where URL (including brackets or
+ * similar) starts
+ * @return |check|-conform start has been found
+ */
+ bool FindURLStart(const char16_t * aInString, int32_t aInLength, const uint32_t pos,
+ const modetype check, uint32_t& start);
+
+/**
+ * @param text (in), pos (in): see FindURL
+ * @param check (in): End must be conform with this mode
+ * @param start (in): see FindURLStart
+ * @param end (out): Similar to |start| param of FindURLStart
+ * @return |check|-conform end has been found
+ */
+ bool FindURLEnd(const char16_t * aInString, int32_t aInStringLength, const uint32_t pos,
+ const modetype check, const uint32_t start, uint32_t& end);
+
+/**
+ * @param text (in), pos (in), whathasbeendone (in): see FindURL
+ * @param check (in): Current mode
+ * @param start (in), end (in): see FindURLEnd
+ * @param txtURL (out): Guessed (raw) URL.
+ * Without whitespace, but not completed.
+ * @param desc (out): Link as shown to the user, but already escaped.
+ * Should be placed between the <a> and </a> tags.
+ * @param replaceBefore(out), replaceAfter (out): see FindURL
+ */
+ void CalculateURLBoundaries(const char16_t * aInString, int32_t aInStringLength,
+ const uint32_t pos, const uint32_t whathasbeendone,
+ const modetype check, const uint32_t start, const uint32_t end,
+ nsString& txtURL, nsString& desc,
+ int32_t& replaceBefore, int32_t& replaceAfter);
+
+/**
+ * @param txtURL (in), desc (in): see CalculateURLBoundaries
+ * @param outputHTML (out): see FindURL
+ * @return A valid URL could be found (and creation of HTML successful)
+ */
+ bool CheckURLAndCreateHTML(
+ const nsString& txtURL, const nsString& desc, const modetype mode,
+ nsString& outputHTML);
+
+/**
+ @param text (in): line of text possibly with tagTXT.<p>
+ if col0 is true,
+ starting with tagTXT<br>
+ else
+ starting one char before tagTXT
+ @param col0 (in): tagTXT is on the beginning of the line (or paragraph).
+ open must be 0 then.
+ @param tagTXT (in): Tag in plaintext to search for, e.g. "*"
+ @param aTagTxtLen (in): length of tagTXT.
+ @param tagHTML (in): HTML-Tag to replace tagTXT with,
+ without "<" and ">", e.g. "strong"
+ @param attributeHTML (in): HTML-attribute to add to opening tagHTML,
+ e.g. "class=txt_star"
+ @param aOutString: string to APPEND the converted html into
+ @param open (in/out): Number of currently open tags of type tagHTML
+ @return Conversion succeeded
+*/
+ bool StructPhraseHit(const char16_t * aInString, int32_t aInStringLength, bool col0,
+ const char16_t* tagTXT,
+ int32_t aTagTxtLen,
+ const char* tagHTML, const char* attributeHTML,
+ nsString& aOutputString, uint32_t& openTags);
+
+/**
+ @param text (in), col0 (in): see GlyphHit
+ @param tagTXT (in): Smily, see also StructPhraseHit
+ @param imageName (in): the basename of the file that contains the image for this smilie
+ @param outputHTML (out): new string containing the html for the smily
+ @param glyphTextLen (out): see GlyphHit
+*/
+ bool
+ SmilyHit(const char16_t * aInString, int32_t aLength, bool col0,
+ const char* tagTXT, const char* imageName,
+ nsString& outputHTML, int32_t& glyphTextLen);
+
+/**
+ Checks, if we can replace some chars at the start of line with prettier HTML
+ code.<p>
+ If success is reported, replace the first glyphTextLen chars with outputHTML
+
+ @param text (in): line of text possibly with Glyph.<p>
+ If col0 is true,
+ starting with Glyph <br><!-- (br not part of text) -->
+ else
+ starting one char before Glyph
+ @param col0 (in): text starts at the beginning of the line (or paragraph)
+ @param aOutString (out): APPENDS html for the glyph to this string
+ @param glyphTextLen (out): Length of original text to replace
+ @return see StructPhraseHit
+*/
+ bool GlyphHit(const char16_t * aInString, int32_t aInLength, bool col0,
+ nsString& aOutString, int32_t& glyphTextLen);
+
+/**
+ Check if a given url should be linkified.
+ @param aURL (in): url to be checked on.
+*/
+ bool ShouldLinkify(const nsCString& aURL);
+};
+
+// It's said, that Win32 and Mac don't like static const members
+const int32_t mozTXTToHTMLConv_lastMode = 4;
+ // Needed (only) by mozTXTToHTMLConv::FindURL
+const int32_t mozTXTToHTMLConv_numberOfModes = 4; // dito; unknown not counted
+
+#endif
diff --git a/netwerk/streamconv/converters/nsBinHexDecoder.cpp b/netwerk/streamconv/converters/nsBinHexDecoder.cpp
new file mode 100644
index 000000000..416fd743b
--- /dev/null
+++ b/netwerk/streamconv/converters/nsBinHexDecoder.cpp
@@ -0,0 +1,520 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIOService.h"
+#include "nsBinHexDecoder.h"
+#include "nsIServiceManager.h"
+#include "nsIStreamConverterService.h"
+#include "nsCRT.h"
+#include "nsIPipe.h"
+#include "nsMimeTypes.h"
+#include "netCore.h"
+#include "nsXPIDLString.h"
+#include "prnetdb.h"
+#include "nsIURI.h"
+#include "nsIURL.h"
+
+#include "nsIMIMEService.h"
+#include "nsMimeTypes.h"
+#include <algorithm>
+
+namespace mozilla {
+namespace net {
+
+nsBinHexDecoder::nsBinHexDecoder() :
+ mState(0), mCRC(0), mFileCRC(0), mOctetin(26),
+ mDonePos(3), mInCRC(0), mCount(0), mMarker(0), mPosInbuff(0),
+ mPosOutputBuff(0)
+{
+ mDataBuffer = nullptr;
+ mOutgoingBuffer = nullptr;
+ mPosInDataBuffer = 0;
+ mRlebuf = 0;
+
+ mOctetBuf.val = 0;
+ mHeader.type = 0;
+ mHeader.creator = 0;
+ mHeader.flags = 0;
+ mHeader.dlen = 0;
+ mHeader.rlen = 0;
+}
+
+nsBinHexDecoder::~nsBinHexDecoder()
+{
+ if (mDataBuffer)
+ free(mDataBuffer);
+ if (mOutgoingBuffer)
+ free(mOutgoingBuffer);
+}
+
+NS_IMPL_ADDREF(nsBinHexDecoder)
+NS_IMPL_RELEASE(nsBinHexDecoder)
+
+NS_INTERFACE_MAP_BEGIN(nsBinHexDecoder)
+ NS_INTERFACE_MAP_ENTRY(nsIStreamConverter)
+ NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
+ NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
+ NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+
+// The binhex 4.0 decoder table....
+
+static const signed char binhex_decode[256] =
+{
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1,
+ 13, 14, 15, 16, 17, 18, 19, -1, 20, 21, -1, -1, -1, -1, -1, -1,
+ 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, -1,
+ 37, 38, 39, 40, 41, 42, 43, -1, 44, 45, 46, 47, -1, -1, -1, -1,
+ 48, 49, 50, 51, 52, 53, 54, -1, 55, 56, 57, 58, 59, 60, -1, -1,
+ 61, 62, 63, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+};
+
+#define BHEXVAL(c) (binhex_decode[(unsigned char) c])
+
+//////////////////////////////////////////////////////
+// nsIStreamConverter methods...
+//////////////////////////////////////////////////////
+
+NS_IMETHODIMP
+nsBinHexDecoder::Convert(nsIInputStream *aFromStream,
+ const char *aFromType,
+ const char *aToType,
+ nsISupports *aCtxt,
+ nsIInputStream **aResultStream)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsBinHexDecoder::AsyncConvertData(const char *aFromType,
+ const char *aToType,
+ nsIStreamListener *aListener,
+ nsISupports *aCtxt)
+{
+ NS_ASSERTION(aListener && aFromType && aToType,
+ "null pointer passed into bin hex converter");
+
+ // hook up our final listener. this guy gets the various On*() calls we want to throw
+ // at him.
+ //
+ mNextListener = aListener;
+ return (aListener) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+//////////////////////////////////////////////////////
+// nsIStreamListener methods...
+//////////////////////////////////////////////////////
+NS_IMETHODIMP
+nsBinHexDecoder::OnDataAvailable(nsIRequest* request,
+ nsISupports *aCtxt,
+ nsIInputStream *aStream,
+ uint64_t aSourceOffset,
+ uint32_t aCount)
+{
+ nsresult rv = NS_OK;
+
+ if (mOutputStream && mDataBuffer && aCount > 0)
+ {
+ uint32_t numBytesRead = 0;
+ while (aCount > 0) // while we still have bytes to copy...
+ {
+ aStream->Read(mDataBuffer, std::min(aCount, nsIOService::gDefaultSegmentSize - 1), &numBytesRead);
+ if (aCount >= numBytesRead)
+ aCount -= numBytesRead; // subtract off the number of bytes we just read
+ else
+ aCount = 0;
+
+ // Process this new chunk of bin hex data...
+ ProcessNextChunk(request, aCtxt, numBytesRead);
+ }
+ }
+
+ return rv;
+}
+
+nsresult nsBinHexDecoder::ProcessNextState(nsIRequest * aRequest, nsISupports * aContext)
+{
+ nsresult status = NS_OK;
+ uint16_t tmpcrc, cval;
+ unsigned char ctmp, c = mRlebuf;
+
+ /* do CRC */
+ ctmp = mInCRC ? c : 0;
+ cval = mCRC & 0xf000;
+ tmpcrc = ((uint16_t) (mCRC << 4) | (ctmp >> 4)) ^ (cval | (cval >> 7) | (cval >> 12));
+ cval = tmpcrc & 0xf000;
+ mCRC = ((uint16_t) (tmpcrc << 4) | (ctmp & 0x0f)) ^ (cval | (cval >> 7) | (cval >> 12));
+
+ /* handle state */
+ switch (mState)
+ {
+ case BINHEX_STATE_START:
+ mState = BINHEX_STATE_FNAME;
+ mCount = 0;
+
+ // c & 63 returns the length of mName. So if we need the length, that's how
+ // you can figure it out....
+ mName.SetLength(c & 63);
+ if (mName.Length() != (c & 63)) {
+ /* XXX ProcessNextState/ProcessNextChunk aren't rv checked */
+ mState = BINHEX_STATE_DONE;
+ }
+ break;
+
+ case BINHEX_STATE_FNAME:
+ if (mCount < mName.Length()) {
+ mName.BeginWriting()[mCount] = c;
+ }
+
+ if (++mCount > mName.Length())
+ {
+ // okay we've figured out the file name....set the content type on the channel
+ // based on the file name AND issue our delayed on start request....
+
+ DetectContentType(aRequest, mName);
+ // now propagate the on start request
+ mNextListener->OnStartRequest(aRequest, aContext);
+
+ mState = BINHEX_STATE_HEADER;
+ mCount = 0;
+ }
+ break;
+
+ case BINHEX_STATE_HEADER:
+ ((char *) &mHeader)[mCount] = c;
+ if (++mCount == 18)
+ {
+ if (sizeof(binhex_header) != 18) /* fix an alignment problem in some OSes */
+ {
+ char *p = (char *)&mHeader;
+ p += 19;
+ for (c = 0; c < 8; c++)
+ {
+ *p = *(p-2);
+ --p;
+ }
+ }
+
+ mState = BINHEX_STATE_HCRC;
+ mInCRC = 1;
+ mCount = 0;
+ }
+ break;
+
+ case BINHEX_STATE_DFORK:
+ case BINHEX_STATE_RFORK:
+ mOutgoingBuffer[mPosOutputBuff++] = c;
+ if (--mCount == 0)
+ {
+ /* only output data fork in the non-mac system. */
+ if (mState == BINHEX_STATE_DFORK)
+ {
+ uint32_t numBytesWritten = 0;
+ mOutputStream->Write(mOutgoingBuffer, mPosOutputBuff, &numBytesWritten);
+ if (int32_t(numBytesWritten) != mPosOutputBuff)
+ status = NS_ERROR_FAILURE;
+
+ // now propagate the data we just wrote
+ mNextListener->OnDataAvailable(aRequest, aContext, mInputStream, 0, numBytesWritten);
+ }
+ else
+ status = NS_OK; /* do nothing for resource fork. */
+
+ mPosOutputBuff = 0;
+
+ if (status != NS_OK)
+ mState = BINHEX_STATE_DONE;
+ else
+ ++mState;
+
+ mInCRC = 1;
+ }
+ else if (mPosOutputBuff >= (int32_t) nsIOService::gDefaultSegmentSize)
+ {
+ if (mState == BINHEX_STATE_DFORK)
+ {
+ uint32_t numBytesWritten = 0;
+ mOutputStream->Write(mOutgoingBuffer, mPosOutputBuff, &numBytesWritten);
+ if (int32_t(numBytesWritten) != mPosOutputBuff)
+ status = NS_ERROR_FAILURE;
+
+ mNextListener->OnDataAvailable(aRequest, aContext, mInputStream, 0, numBytesWritten);
+ mPosOutputBuff = 0;
+ }
+ }
+ break;
+
+ case BINHEX_STATE_HCRC:
+ case BINHEX_STATE_DCRC:
+ case BINHEX_STATE_RCRC:
+ if (!mCount++)
+ mFileCRC = (unsigned short) c << 8;
+ else
+ {
+ if ((mFileCRC | c) != mCRC)
+ {
+ mState = BINHEX_STATE_DONE;
+ break;
+ }
+
+ /* passed the CRC check!!!*/
+ mCRC = 0;
+ if (++mState == BINHEX_STATE_FINISH)
+ {
+ // when we reach the finished state...fire an on stop request on the event listener...
+ mNextListener->OnStopRequest(aRequest, aContext, NS_OK);
+ mNextListener = nullptr;
+
+ /* now We are done with everything. */
+ ++mState;
+ break;
+ }
+
+ if (mState == BINHEX_STATE_DFORK)
+ mCount = PR_ntohl(mHeader.dlen);
+ else
+ {
+ // we aren't processing the resurce Fork. uncomment this line if we make this converter
+ // smart enough to do this in the future.
+ // mCount = PR_ntohl(mHeader.rlen); /* it should in host byte order */
+ mCount = 0;
+ }
+
+ if (mCount) {
+ mInCRC = 0;
+ } else {
+ /* nothing inside, so skip to the next state. */
+ ++mState;
+ }
+ }
+ break;
+ }
+
+ return NS_OK;
+}
+
+nsresult nsBinHexDecoder::ProcessNextChunk(nsIRequest * aRequest, nsISupports * aContext, uint32_t numBytesInBuffer)
+{
+ bool foundStart;
+ int16_t octetpos, c = 0;
+ uint32_t val;
+ mPosInDataBuffer = 0; // use member variable.
+
+ NS_ENSURE_TRUE(numBytesInBuffer > 0, NS_ERROR_FAILURE);
+
+ // if it is the first time, seek to the right start place.
+ if (mState == BINHEX_STATE_START)
+ {
+ foundStart = false;
+ // go through the line, until we get a ':'
+ while (mPosInDataBuffer < numBytesInBuffer)
+ {
+ c = mDataBuffer[mPosInDataBuffer++];
+ while (c == nsCRT::CR || c == nsCRT::LF)
+ {
+ if (mPosInDataBuffer >= numBytesInBuffer)
+ break;
+
+ c = mDataBuffer[mPosInDataBuffer++];
+ if (c == ':')
+ {
+ foundStart = true;
+ break;
+ }
+ }
+ if (foundStart) break; /* we got the start point. */
+ }
+
+ if (mPosInDataBuffer >= numBytesInBuffer)
+ return NS_OK; /* we meet buff end before we get the start point, wait till next fills. */
+
+ if (c != ':')
+ return NS_ERROR_FAILURE; /* can't find the start character. */
+ }
+
+ while (mState != BINHEX_STATE_DONE)
+ {
+ /* fill in octetbuf */
+ do
+ {
+ if (mPosInDataBuffer >= numBytesInBuffer)
+ return NS_OK; /* end of buff, go on for the nxet calls. */
+
+ c = GetNextChar(numBytesInBuffer);
+ if (c == 0) return NS_OK;
+
+ if ((val = BHEXVAL(c)) == uint32_t(-1))
+ {
+ /* we incount an invalid character. */
+ if (c)
+ {
+ /* rolling back. */
+ --mDonePos;
+ if (mOctetin >= 14)
+ --mDonePos;
+ if (mOctetin >= 20)
+ --mDonePos;
+ }
+ break;
+ }
+ mOctetBuf.val |= val << mOctetin;
+ }
+ while ((mOctetin -= 6) > 2);
+
+ /* handle decoded characters -- run length encoding (rle) detection */
+
+ // We put decoded chars into mOctetBuf.val in order from high to low (via
+ // bitshifting, above). But we want to byte-address them, so we want the
+ // first byte to correspond to the high byte. In other words, we want
+ // these bytes to be in network order.
+ mOctetBuf.val = PR_htonl(mOctetBuf.val);
+
+ for (octetpos = 0; octetpos < mDonePos; ++octetpos)
+ {
+ c = mOctetBuf.c[octetpos];
+
+ if (c == 0x90 && !mMarker++)
+ continue;
+
+ if (mMarker)
+ {
+ if (c == 0)
+ {
+ mRlebuf = 0x90;
+ ProcessNextState(aRequest, aContext);
+ }
+ else
+ {
+ /* we are in the run length mode */
+ while (--c > 0)
+ ProcessNextState(aRequest, aContext);
+ }
+ mMarker = 0;
+ }
+ else
+ {
+ mRlebuf = (unsigned char) c;
+ ProcessNextState(aRequest, aContext);
+ }
+
+ if (mState >= BINHEX_STATE_DONE)
+ break;
+ }
+
+ /* prepare for next 3 characters. */
+ if (mDonePos < 3 && mState < BINHEX_STATE_DONE)
+ mState = BINHEX_STATE_DONE;
+
+ mOctetin = 26;
+ mOctetBuf.val = 0;
+ }
+
+ return NS_OK;
+}
+
+int16_t nsBinHexDecoder::GetNextChar(uint32_t numBytesInBuffer)
+{
+ char c = 0;
+
+ while (mPosInDataBuffer < numBytesInBuffer)
+ {
+ c = mDataBuffer[mPosInDataBuffer++];
+ if (c != nsCRT::LF && c != nsCRT::CR)
+ break;
+ }
+ return (c == nsCRT::LF || c == nsCRT::CR) ? 0 : (int) c;
+}
+
+//////////////////////////////////////////////////////
+// nsIRequestObserver methods...
+//////////////////////////////////////////////////////
+
+NS_IMETHODIMP
+nsBinHexDecoder::OnStartRequest(nsIRequest* request, nsISupports *aCtxt)
+{
+ nsresult rv = NS_OK;
+
+ NS_ENSURE_TRUE(mNextListener, NS_ERROR_FAILURE);
+
+ mDataBuffer = (char *) malloc((sizeof(char) * nsIOService::gDefaultSegmentSize));
+ mOutgoingBuffer = (char *) malloc((sizeof(char) * nsIOService::gDefaultSegmentSize));
+ if (!mDataBuffer || !mOutgoingBuffer) return NS_ERROR_FAILURE; // out of memory;
+
+ // now we want to create a pipe which we'll use to write our converted data...
+ rv = NS_NewPipe(getter_AddRefs(mInputStream), getter_AddRefs(mOutputStream),
+ nsIOService::gDefaultSegmentSize,
+ nsIOService::gDefaultSegmentSize,
+ true, true);
+
+ // don't propagate the on start request to mNextListener until we have determined the content type.
+ return rv;
+}
+
+// Given the fileName we discovered inside the bin hex decoding, figure out the
+// content type and set it on the channel associated with the request. If the
+// filename tells us nothing useful, just report an unknown type and let the
+// unknown decoder handle things.
+nsresult nsBinHexDecoder::DetectContentType(nsIRequest* aRequest,
+ const nsAFlatCString &aFilename)
+{
+ if (aFilename.IsEmpty()) {
+ // Nothing to do here.
+ return NS_OK;
+ }
+
+ nsresult rv;
+ nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest, &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIMIMEService> mimeService(do_GetService("@mozilla.org/mime;1", &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsAutoCString contentType;
+
+ // extract the extension from aFilename and look it up.
+ const char * fileExt = strrchr(aFilename.get(), '.');
+ if (!fileExt) {
+ return NS_OK;
+ }
+
+ mimeService->GetTypeFromExtension(nsDependentCString(fileExt), contentType);
+
+ // Only set the type if it's not empty and, to prevent recursive loops, not the binhex type
+ if (!contentType.IsEmpty() && !contentType.Equals(APPLICATION_BINHEX)) {
+ channel->SetContentType(contentType);
+ } else {
+ channel->SetContentType(NS_LITERAL_CSTRING(UNKNOWN_CONTENT_TYPE));
+ }
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsBinHexDecoder::OnStopRequest(nsIRequest* request, nsISupports *aCtxt,
+ nsresult aStatus)
+{
+ nsresult rv = NS_OK;
+
+ if (!mNextListener) return NS_ERROR_FAILURE;
+ // don't do anything here...we'll fire our own on stop request when we are done
+ // processing the data....
+
+ return rv;
+}
+
+} // namespace net
+} // namespace mozilla
diff --git a/netwerk/streamconv/converters/nsBinHexDecoder.h b/netwerk/streamconv/converters/nsBinHexDecoder.h
new file mode 100644
index 000000000..01d9b5c15
--- /dev/null
+++ b/netwerk/streamconv/converters/nsBinHexDecoder.h
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// A decoder for Mac Bin Hex 4.0.
+
+// This decoder is currently only intended to be used on NON-Mac platforms. It isn't hooked up to
+// code which would actually save the file to disk. As a result, we can't leverage the resource fork.
+// This makes this decoder most unhelpful for the Mac. Our assumption is that if you save a bin hex file
+// on the mac and try to open it, stuffit or some other tool is already going to be on the Mac which knows how
+// to handle bin hex. On windows and unix, that's not the case. We need client code to strip out the data fork.
+// So this decoder currently just strips out the data fork.
+
+// Note: it's possible that we can eventually turn this decoder into both a decoder and into a file stream (much
+// like the apple double decoder) so on the Mac, if we are saving to disk, we can invoke the decoder as a file stream
+// and it will process the resource fork and do the right magic.
+
+#ifndef nsBinHexDecoder_h__
+#define nsBinHexDecoder_h__
+
+#include "nsIStreamConverter.h"
+#include "nsIChannel.h"
+#include "nsIOutputStream.h"
+#include "nsIInputStream.h"
+
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+#define NS_BINHEXDECODER_CID \
+{ /* 301DEA42-6850-4cda-8945-81F7DBC2186B */ \
+ 0x301dea42, 0x6850, 0x4cda, \
+ { 0x89, 0x45, 0x81, 0xf7, 0xdb, 0xc2, 0x18, 0x6b } \
+}
+
+namespace mozilla {
+namespace net {
+
+typedef struct _binhex_header
+{
+ uint32_t type, creator;
+ uint16_t flags;
+ int32_t dlen, rlen;
+} binhex_header;
+
+typedef union
+{
+ unsigned char c[4];
+ uint32_t val;
+} longbuf;
+
+#define BINHEX_STATE_START 0
+#define BINHEX_STATE_FNAME 1
+#define BINHEX_STATE_HEADER 2
+#define BINHEX_STATE_HCRC 3
+#define BINHEX_STATE_DFORK 4
+#define BINHEX_STATE_DCRC 5
+#define BINHEX_STATE_RFORK 6
+#define BINHEX_STATE_RCRC 7
+#define BINHEX_STATE_FINISH 8
+#define BINHEX_STATE_DONE 9
+/* #define BINHEX_STATE_ERROR 10 */
+
+class nsBinHexDecoder : public nsIStreamConverter
+{
+public:
+ // nsISupports methods
+ NS_DECL_ISUPPORTS
+
+ // nsIStreamConverter methods
+ NS_DECL_NSISTREAMCONVERTER
+
+ // nsIStreamListener methods
+ NS_DECL_NSISTREAMLISTENER
+
+ // nsIRequestObserver methods
+ NS_DECL_NSIREQUESTOBSERVER
+
+ nsBinHexDecoder();
+
+protected:
+ virtual ~nsBinHexDecoder();
+
+ int16_t GetNextChar(uint32_t numBytesInBuffer);
+ nsresult ProcessNextChunk(nsIRequest * aRequest, nsISupports * aContext, uint32_t numBytesInBuffer);
+ nsresult ProcessNextState(nsIRequest * aRequest, nsISupports * aContext);
+ nsresult DetectContentType(nsIRequest * aRequest, const nsAFlatCString &aFilename);
+
+protected:
+ nsCOMPtr<nsIStreamListener> mNextListener;
+
+ // the input and output streams form a pipe...they need to be passed around together..
+ nsCOMPtr<nsIOutputStream> mOutputStream; // output stream
+ nsCOMPtr<nsIInputStream> mInputStream;
+
+ int16_t mState; /* current state */
+ uint16_t mCRC; /* cumulative CRC */
+ uint16_t mFileCRC; /* CRC value from file */
+ longbuf mOctetBuf; /* buffer for decoded 6-bit values */
+ int16_t mOctetin; /* current input position in octetbuf */
+ int16_t mDonePos; /* ending position in octetbuf */
+ int16_t mInCRC; /* flag set when reading a CRC */
+
+ // Bin Hex Header Information
+ binhex_header mHeader;
+ nsCString mName; /* fsspec for the output file */
+
+ // unfortunately we are going to need 2 8K buffers here. One for the data we are currently digesting. Another
+ // for the outgoing decoded data. I tried getting them to share a buffer but things didn't work out so nicely.
+ char * mDataBuffer; // temporary holding pen for the incoming data.
+ char * mOutgoingBuffer; // temporary holding pen for the incoming data.
+ uint32_t mPosInDataBuffer;
+
+ unsigned char mRlebuf; /* buffer for last run length encoding value */
+
+ uint32_t mCount; /* generic counter */
+ int16_t mMarker; /* flag indicating maker */
+
+ int32_t mPosInbuff; /* the index of the inbuff. */
+ int32_t mPosOutputBuff; /* the position of the out buff. */
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif /* nsBinHexDecoder_h__ */
diff --git a/netwerk/streamconv/converters/nsDirIndex.cpp b/netwerk/streamconv/converters/nsDirIndex.cpp
new file mode 100644
index 000000000..0ad77805a
--- /dev/null
+++ b/netwerk/streamconv/converters/nsDirIndex.cpp
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsDirIndex.h"
+
+NS_IMPL_ISUPPORTS(nsDirIndex,
+ nsIDirIndex)
+
+nsDirIndex::nsDirIndex() : mType(TYPE_UNKNOWN),
+ mSize(UINT64_MAX),
+ mLastModified(-1LL)
+{
+}
+
+nsDirIndex::~nsDirIndex() {}
+
+NS_IMETHODIMP
+nsDirIndex::GetType(uint32_t* aType)
+{
+ NS_ENSURE_ARG_POINTER(aType);
+
+ *aType = mType;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDirIndex::SetType(uint32_t aType)
+{
+ mType = aType;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDirIndex::GetContentType(char* *aContentType)
+{
+ NS_ENSURE_ARG_POINTER(aContentType);
+
+ *aContentType = ToNewCString(mContentType);
+ if (!*aContentType)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDirIndex::SetContentType(const char* aContentType)
+{
+ mContentType = aContentType;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDirIndex::GetLocation(char* *aLocation)
+{
+ NS_ENSURE_ARG_POINTER(aLocation);
+
+ *aLocation = ToNewCString(mLocation);
+ if (!*aLocation)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDirIndex::SetLocation(const char* aLocation)
+{
+ mLocation = aLocation;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDirIndex::GetDescription(char16_t* *aDescription)
+{
+ NS_ENSURE_ARG_POINTER(aDescription);
+
+ *aDescription = ToNewUnicode(mDescription);
+ if (!*aDescription)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDirIndex::SetDescription(const char16_t* aDescription)
+{
+ mDescription.Assign(aDescription);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDirIndex::GetSize(int64_t* aSize)
+{
+ NS_ENSURE_ARG_POINTER(aSize);
+
+ *aSize = mSize;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDirIndex::SetSize(int64_t aSize)
+{
+ mSize = aSize;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDirIndex::GetLastModified(PRTime* aLastModified)
+{
+ NS_ENSURE_ARG_POINTER(aLastModified);
+
+ *aLastModified = mLastModified;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDirIndex::SetLastModified(PRTime aLastModified)
+{
+ mLastModified = aLastModified;
+ return NS_OK;
+}
diff --git a/netwerk/streamconv/converters/nsDirIndex.h b/netwerk/streamconv/converters/nsDirIndex.h
new file mode 100644
index 000000000..b4b3b3c56
--- /dev/null
+++ b/netwerk/streamconv/converters/nsDirIndex.h
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIDirIndex.h"
+#include "nsString.h"
+#include "mozilla/Attributes.h"
+
+/* CID: {f6913e2e-1dd1-11b2-84be-f455dee342af} */
+
+class nsDirIndex final : public nsIDirIndex {
+
+private:
+ ~nsDirIndex();
+
+public:
+ nsDirIndex();
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIDIRINDEX
+
+protected:
+ uint32_t mType;
+ nsXPIDLCString mContentType;
+ nsXPIDLCString mLocation;
+ nsString mDescription;
+ int64_t mSize;
+ PRTime mLastModified;
+};
diff --git a/netwerk/streamconv/converters/nsDirIndexParser.cpp b/netwerk/streamconv/converters/nsDirIndexParser.cpp
new file mode 100644
index 000000000..1f4bc78cb
--- /dev/null
+++ b/netwerk/streamconv/converters/nsDirIndexParser.cpp
@@ -0,0 +1,427 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* This parsing code originally lived in xpfe/components/directory/ - bbaetz */
+
+#include "mozilla/ArrayUtils.h"
+
+#include "prprf.h"
+
+#include "nsDirIndexParser.h"
+#include "nsEscape.h"
+#include "nsIInputStream.h"
+#include "nsCRT.h"
+#include "mozilla/dom/FallbackEncoding.h"
+#include "nsITextToSubURI.h"
+#include "nsIDirIndex.h"
+#include "nsServiceManagerUtils.h"
+
+using namespace mozilla;
+
+NS_IMPL_ISUPPORTS(nsDirIndexParser,
+ nsIRequestObserver,
+ nsIStreamListener,
+ nsIDirIndexParser)
+
+nsDirIndexParser::nsDirIndexParser() {
+}
+
+nsresult
+nsDirIndexParser::Init() {
+ mLineStart = 0;
+ mHasDescription = false;
+ mFormat[0] = -1;
+ mozilla::dom::FallbackEncoding::FromLocale(mEncoding);
+
+ nsresult rv;
+ // XXX not threadsafe
+ if (gRefCntParser++ == 0)
+ rv = CallGetService(NS_ITEXTTOSUBURI_CONTRACTID, &gTextToSubURI);
+ else
+ rv = NS_OK;
+
+ return rv;
+}
+
+nsDirIndexParser::~nsDirIndexParser() {
+ // XXX not threadsafe
+ if (--gRefCntParser == 0) {
+ NS_IF_RELEASE(gTextToSubURI);
+ }
+}
+
+NS_IMETHODIMP
+nsDirIndexParser::SetListener(nsIDirIndexListener* aListener) {
+ mListener = aListener;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDirIndexParser::GetListener(nsIDirIndexListener** aListener) {
+ NS_IF_ADDREF(*aListener = mListener.get());
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDirIndexParser::GetComment(char** aComment) {
+ *aComment = ToNewCString(mComment);
+
+ if (!*aComment)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDirIndexParser::SetEncoding(const char* aEncoding) {
+ mEncoding.Assign(aEncoding);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDirIndexParser::GetEncoding(char** aEncoding) {
+ *aEncoding = ToNewCString(mEncoding);
+
+ if (!*aEncoding)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDirIndexParser::OnStartRequest(nsIRequest* aRequest, nsISupports* aCtxt) {
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDirIndexParser::OnStopRequest(nsIRequest *aRequest, nsISupports *aCtxt,
+ nsresult aStatusCode) {
+ // Finish up
+ if (mBuf.Length() > (uint32_t) mLineStart) {
+ ProcessData(aRequest, aCtxt);
+ }
+
+ return NS_OK;
+}
+
+nsDirIndexParser::Field
+nsDirIndexParser::gFieldTable[] = {
+ { "Filename", FIELD_FILENAME },
+ { "Description", FIELD_DESCRIPTION },
+ { "Content-Length", FIELD_CONTENTLENGTH },
+ { "Last-Modified", FIELD_LASTMODIFIED },
+ { "Content-Type", FIELD_CONTENTTYPE },
+ { "File-Type", FIELD_FILETYPE },
+ { nullptr, FIELD_UNKNOWN }
+};
+
+nsrefcnt nsDirIndexParser::gRefCntParser = 0;
+nsITextToSubURI *nsDirIndexParser::gTextToSubURI;
+
+nsresult
+nsDirIndexParser::ParseFormat(const char* aFormatStr)
+{
+ // Parse a "200" format line, and remember the fields and their
+ // ordering in mFormat. Multiple 200 lines stomp on each other.
+ unsigned int formatNum = 0;
+ mFormat[0] = -1;
+
+ do {
+ while (*aFormatStr && nsCRT::IsAsciiSpace(char16_t(*aFormatStr)))
+ ++aFormatStr;
+
+ if (! *aFormatStr)
+ break;
+
+ nsAutoCString name;
+ int32_t len = 0;
+ while (aFormatStr[len] && !nsCRT::IsAsciiSpace(char16_t(aFormatStr[len])))
+ ++len;
+ name.SetCapacity(len + 1);
+ name.Append(aFormatStr, len);
+ aFormatStr += len;
+
+ // Okay, we're gonna monkey with the nsStr. Bold!
+ name.SetLength(nsUnescapeCount(name.BeginWriting()));
+
+ // All tokens are case-insensitive - http://www.mozilla.org/projects/netlib/dirindexformat.html
+ if (name.LowerCaseEqualsLiteral("description"))
+ mHasDescription = true;
+
+ for (Field* i = gFieldTable; i->mName; ++i) {
+ if (name.EqualsIgnoreCase(i->mName)) {
+ mFormat[formatNum] = i->mType;
+ mFormat[++formatNum] = -1;
+ break;
+ }
+ }
+
+ } while (*aFormatStr && (formatNum < (ArrayLength(mFormat)-1)));
+
+ return NS_OK;
+}
+
+nsresult
+nsDirIndexParser::ParseData(nsIDirIndex *aIdx, char* aDataStr, int32_t aLineLen)
+{
+ // Parse a "201" data line, using the field ordering specified in
+ // mFormat.
+
+ if(mFormat[0] == -1) {
+ // Ignore if we haven't seen a format yet.
+ return NS_OK;
+ }
+
+ nsresult rv = NS_OK;
+ nsAutoCString filename;
+ int32_t lineLen = aLineLen;
+
+ for (int32_t i = 0; mFormat[i] != -1; ++i) {
+ // If we've exhausted the data before we run out of fields, just bail.
+ if (!*aDataStr || (lineLen < 1)) {
+ return NS_OK;
+ }
+
+ while ((lineLen > 0) && nsCRT::IsAsciiSpace(*aDataStr)) {
+ ++aDataStr;
+ --lineLen;
+ }
+
+ if (lineLen < 1) {
+ // invalid format, bail
+ return NS_OK;
+ }
+
+ char *value = aDataStr;
+ if (*aDataStr == '"' || *aDataStr == '\'') {
+ // it's a quoted string. snarf everything up to the next quote character
+ const char quotechar = *(aDataStr++);
+ lineLen--;
+ ++value;
+ while ((lineLen > 0) && *aDataStr != quotechar) {
+ ++aDataStr;
+ --lineLen;
+ }
+ if (lineLen > 0) {
+ *aDataStr++ = '\0';
+ --lineLen;
+ }
+
+ if (!lineLen) {
+ // invalid format, bail
+ return NS_OK;
+ }
+ } else {
+ // it's unquoted. snarf until we see whitespace.
+ value = aDataStr;
+ while ((lineLen > 0) && (!nsCRT::IsAsciiSpace(*aDataStr))) {
+ ++aDataStr;
+ --lineLen;
+ }
+ if (lineLen > 0) {
+ *aDataStr++ = '\0';
+ --lineLen;
+ }
+ // even if we ran out of line length here, there's still a trailing zero
+ // byte afterwards
+ }
+
+ fieldType t = fieldType(mFormat[i]);
+ switch (t) {
+ case FIELD_FILENAME: {
+ // don't unescape at this point, so that UnEscapeAndConvert() can
+ filename = value;
+
+ bool success = false;
+
+ nsAutoString entryuri;
+
+ if (gTextToSubURI) {
+ char16_t *result = nullptr;
+ if (NS_SUCCEEDED(rv = gTextToSubURI->UnEscapeAndConvert(mEncoding.get(), filename.get(),
+ &result)) && (result)) {
+ if (*result) {
+ aIdx->SetLocation(filename.get());
+ if (!mHasDescription)
+ aIdx->SetDescription(result);
+ success = true;
+ }
+ free(result);
+ } else {
+ NS_WARNING("UnEscapeAndConvert error");
+ }
+ }
+
+ if (!success) {
+ // if unsuccessfully at charset conversion, then
+ // just fallback to unescape'ing in-place
+ // XXX - this shouldn't be using UTF8, should it?
+ // when can we fail to get the service, anyway? - bbaetz
+ aIdx->SetLocation(filename.get());
+ if (!mHasDescription) {
+ aIdx->SetDescription(NS_ConvertUTF8toUTF16(value).get());
+ }
+ }
+ }
+ break;
+ case FIELD_DESCRIPTION:
+ nsUnescape(value);
+ aIdx->SetDescription(NS_ConvertUTF8toUTF16(value).get());
+ break;
+ case FIELD_CONTENTLENGTH:
+ {
+ int64_t len;
+ int32_t status = PR_sscanf(value, "%lld", &len);
+ if (status == 1)
+ aIdx->SetSize(len);
+ else
+ aIdx->SetSize(UINT64_MAX); // UINT64_MAX means unknown
+ }
+ break;
+ case FIELD_LASTMODIFIED:
+ {
+ PRTime tm;
+ nsUnescape(value);
+ if (PR_ParseTimeString(value, false, &tm) == PR_SUCCESS) {
+ aIdx->SetLastModified(tm);
+ }
+ }
+ break;
+ case FIELD_CONTENTTYPE:
+ aIdx->SetContentType(value);
+ break;
+ case FIELD_FILETYPE:
+ // unescape in-place
+ nsUnescape(value);
+ if (!nsCRT::strcasecmp(value, "directory")) {
+ aIdx->SetType(nsIDirIndex::TYPE_DIRECTORY);
+ } else if (!nsCRT::strcasecmp(value, "file")) {
+ aIdx->SetType(nsIDirIndex::TYPE_FILE);
+ } else if (!nsCRT::strcasecmp(value, "symbolic-link")) {
+ aIdx->SetType(nsIDirIndex::TYPE_SYMLINK);
+ } else {
+ aIdx->SetType(nsIDirIndex::TYPE_UNKNOWN);
+ }
+ break;
+ case FIELD_UNKNOWN:
+ // ignore
+ break;
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsDirIndexParser::OnDataAvailable(nsIRequest *aRequest, nsISupports *aCtxt,
+ nsIInputStream *aStream,
+ uint64_t aSourceOffset,
+ uint32_t aCount) {
+ if (aCount < 1)
+ return NS_OK;
+
+ int32_t len = mBuf.Length();
+
+ // Ensure that our mBuf has capacity to hold the data we're about to
+ // read.
+ if (!mBuf.SetLength(len + aCount, fallible))
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ // Now read the data into our buffer.
+ nsresult rv;
+ uint32_t count;
+ rv = aStream->Read(mBuf.BeginWriting() + len, aCount, &count);
+ if (NS_FAILED(rv)) return rv;
+
+ // Set the string's length according to the amount of data we've read.
+ // Note: we know this to work on nsCString. This isn't guaranteed to
+ // work on other strings.
+ mBuf.SetLength(len + count);
+
+ return ProcessData(aRequest, aCtxt);
+}
+
+nsresult
+nsDirIndexParser::ProcessData(nsIRequest *aRequest, nsISupports *aCtxt) {
+ if (!mListener)
+ return NS_ERROR_FAILURE;
+
+ int32_t numItems = 0;
+
+ while(true) {
+ ++numItems;
+
+ int32_t eol = mBuf.FindCharInSet("\n\r", mLineStart);
+ if (eol < 0) break;
+ mBuf.SetCharAt(char16_t('\0'), eol);
+
+ const char *line = mBuf.get() + mLineStart;
+
+ int32_t lineLen = eol - mLineStart;
+ mLineStart = eol + 1;
+
+ if (lineLen >= 4) {
+ nsresult rv;
+ const char *buf = line;
+
+ if (buf[0] == '1') {
+ if (buf[1] == '0') {
+ if (buf[2] == '0' && buf[3] == ':') {
+ // 100. Human-readable comment line. Ignore
+ } else if (buf[2] == '1' && buf[3] == ':') {
+ // 101. Human-readable information line.
+ mComment.Append(buf + 4);
+
+ char *value = ((char *)buf) + 4;
+ nsUnescape(value);
+ mListener->OnInformationAvailable(aRequest, aCtxt, NS_ConvertUTF8toUTF16(value));
+
+ } else if (buf[2] == '2' && buf[3] == ':') {
+ // 102. Human-readable information line, HTML.
+ mComment.Append(buf + 4);
+ }
+ }
+ } else if (buf[0] == '2') {
+ if (buf[1] == '0') {
+ if (buf[2] == '0' && buf[3] == ':') {
+ // 200. Define field names
+ rv = ParseFormat(buf + 4);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ } else if (buf[2] == '1' && buf[3] == ':') {
+ // 201. Field data
+ nsCOMPtr<nsIDirIndex> idx = do_CreateInstance("@mozilla.org/dirIndex;1",&rv);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = ParseData(idx, ((char *)buf) + 4, lineLen - 4);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ mListener->OnIndexAvailable(aRequest, aCtxt, idx);
+ }
+ }
+ } else if (buf[0] == '3') {
+ if (buf[1] == '0') {
+ if (buf[2] == '0' && buf[3] == ':') {
+ // 300. Self-referring URL
+ } else if (buf[2] == '1' && buf[3] == ':') {
+ // 301. OUR EXTENSION - encoding
+ int i = 4;
+ while (buf[i] && nsCRT::IsAsciiSpace(buf[i]))
+ ++i;
+
+ if (buf[i])
+ SetEncoding(buf+i);
+ }
+ }
+ }
+ }
+ }
+
+ return NS_OK;
+}
diff --git a/netwerk/streamconv/converters/nsDirIndexParser.h b/netwerk/streamconv/converters/nsDirIndexParser.h
new file mode 100644
index 000000000..bc3b67ea4
--- /dev/null
+++ b/netwerk/streamconv/converters/nsDirIndexParser.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __NSDIRINDEX_H_
+#define __NSDIRINDEX_H_
+
+#include "nsString.h"
+#include "nsCOMPtr.h"
+#include "nsIDirIndexListener.h"
+
+class nsIDirIndex;
+class nsITextToSubURI;
+
+/* CID: {a0d6ad32-1dd1-11b2-aa55-a40187b54036} */
+
+class nsDirIndexParser : public nsIDirIndexParser {
+
+private:
+ virtual ~nsDirIndexParser();
+
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISTREAMLISTENER
+ NS_DECL_NSIREQUESTOBSERVER
+ NS_DECL_NSIDIRINDEXPARSER
+
+ nsDirIndexParser();
+ nsresult Init();
+
+ enum fieldType {
+ FIELD_UNKNOWN = 0, // MUST be 0
+ FIELD_FILENAME,
+ FIELD_DESCRIPTION,
+ FIELD_CONTENTLENGTH,
+ FIELD_LASTMODIFIED,
+ FIELD_CONTENTTYPE,
+ FIELD_FILETYPE
+ };
+
+protected:
+ nsCOMPtr<nsIDirIndexListener> mListener;
+
+ nsCString mEncoding;
+ nsCString mComment;
+ nsCString mBuf;
+ int32_t mLineStart;
+ bool mHasDescription;
+ int mFormat[8];
+
+ nsresult ProcessData(nsIRequest *aRequest, nsISupports *aCtxt);
+ nsresult ParseFormat(const char* buf);
+ nsresult ParseData(nsIDirIndex* aIdx, char* aDataStr, int32_t lineLen);
+
+ struct Field {
+ const char *mName;
+ fieldType mType;
+ };
+
+ static Field gFieldTable[];
+
+ static nsrefcnt gRefCntParser;
+ static nsITextToSubURI* gTextToSubURI;
+};
+
+#endif
diff --git a/netwerk/streamconv/converters/nsFTPDirListingConv.cpp b/netwerk/streamconv/converters/nsFTPDirListingConv.cpp
new file mode 100644
index 000000000..6e1bb8f34
--- /dev/null
+++ b/netwerk/streamconv/converters/nsFTPDirListingConv.cpp
@@ -0,0 +1,345 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsFTPDirListingConv.h"
+#include "nsMemory.h"
+#include "plstr.h"
+#include "mozilla/Logging.h"
+#include "nsCOMPtr.h"
+#include "nsEscape.h"
+#include "nsStringStream.h"
+#include "nsIStreamListener.h"
+#include "nsCRT.h"
+#include "nsIChannel.h"
+#include "nsIURI.h"
+
+#include "ParseFTPList.h"
+#include <algorithm>
+
+#include "mozilla/UniquePtrExtensions.h"
+#include "mozilla/Unused.h"
+
+//
+// Log module for FTP dir listing stream converter logging...
+//
+// To enable logging (see prlog.h for full details):
+//
+// set MOZ_LOG=nsFTPDirListConv:5
+// set MOZ_LOG_FILE=network.log
+//
+// This enables LogLevel::Debug level information and places all output in
+// the file network.log.
+//
+static mozilla::LazyLogModule gFTPDirListConvLog("nsFTPDirListingConv");
+using namespace mozilla;
+
+// nsISupports implementation
+NS_IMPL_ISUPPORTS(nsFTPDirListingConv,
+ nsIStreamConverter,
+ nsIStreamListener,
+ nsIRequestObserver)
+
+
+// nsIStreamConverter implementation
+NS_IMETHODIMP
+nsFTPDirListingConv::Convert(nsIInputStream *aFromStream,
+ const char *aFromType,
+ const char *aToType,
+ nsISupports *aCtxt, nsIInputStream **_retval) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+
+// Stream converter service calls this to initialize the actual stream converter (us).
+NS_IMETHODIMP
+nsFTPDirListingConv::AsyncConvertData(const char *aFromType, const char *aToType,
+ nsIStreamListener *aListener, nsISupports *aCtxt) {
+ NS_ASSERTION(aListener && aFromType && aToType, "null pointer passed into FTP dir listing converter");
+
+ // hook up our final listener. this guy gets the various On*() calls we want to throw
+ // at him.
+ mFinalListener = aListener;
+ NS_ADDREF(mFinalListener);
+
+ MOZ_LOG(gFTPDirListConvLog, LogLevel::Debug,
+ ("nsFTPDirListingConv::AsyncConvertData() converting FROM raw, TO application/http-index-format\n"));
+
+ return NS_OK;
+}
+
+
+// nsIStreamListener implementation
+NS_IMETHODIMP
+nsFTPDirListingConv::OnDataAvailable(nsIRequest* request, nsISupports *ctxt,
+ nsIInputStream *inStr, uint64_t sourceOffset, uint32_t count) {
+ NS_ASSERTION(request, "FTP dir listing stream converter needs a request");
+
+ nsresult rv;
+
+ nsCOMPtr<nsIChannel> channel = do_QueryInterface(request, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint32_t read, streamLen;
+
+ uint64_t streamLen64;
+ rv = inStr->Available(&streamLen64);
+ NS_ENSURE_SUCCESS(rv, rv);
+ streamLen = (uint32_t)std::min(streamLen64, uint64_t(UINT32_MAX - 1));
+
+ auto buffer = MakeUniqueFallible<char[]>(streamLen + 1);
+ NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
+
+ rv = inStr->Read(buffer.get(), streamLen, &read);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // the dir listings are ascii text, null terminate this sucker.
+ buffer[streamLen] = '\0';
+
+ MOZ_LOG(gFTPDirListConvLog, LogLevel::Debug, ("nsFTPDirListingConv::OnData(request = %x, ctxt = %x, inStr = %x, sourceOffset = %llu, count = %u)\n", request, ctxt, inStr, sourceOffset, count));
+
+ if (!mBuffer.IsEmpty()) {
+ // we have data left over from a previous OnDataAvailable() call.
+ // combine the buffers so we don't lose any data.
+ mBuffer.Append(buffer.get());
+
+ buffer = MakeUniqueFallible<char[]>(mBuffer.Length()+1);
+ NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
+
+ strncpy(buffer.get(), mBuffer.get(), mBuffer.Length()+1);
+ mBuffer.Truncate();
+ }
+
+ MOZ_LOG(gFTPDirListConvLog, LogLevel::Debug, ("::OnData() received the following %d bytes...\n\n%s\n\n", streamLen, buffer.get()) );
+
+ nsAutoCString indexFormat;
+ if (!mSentHeading) {
+ // build up the 300: line
+ nsCOMPtr<nsIURI> uri;
+ rv = channel->GetURI(getter_AddRefs(uri));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = GetHeaders(indexFormat, uri);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ mSentHeading = true;
+ }
+
+ char *line = buffer.get();
+ line = DigestBufferLines(line, indexFormat);
+
+ MOZ_LOG(gFTPDirListConvLog, LogLevel::Debug, ("::OnData() sending the following %d bytes...\n\n%s\n\n",
+ indexFormat.Length(), indexFormat.get()) );
+
+ // if there's any data left over, buffer it.
+ if (line && *line) {
+ mBuffer.Append(line);
+ MOZ_LOG(gFTPDirListConvLog, LogLevel::Debug, ("::OnData() buffering the following %d bytes...\n\n%s\n\n",
+ strlen(line), line) );
+ }
+
+ // send the converted data out.
+ nsCOMPtr<nsIInputStream> inputData;
+
+ rv = NS_NewCStringInputStream(getter_AddRefs(inputData), indexFormat);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = mFinalListener->OnDataAvailable(request, ctxt, inputData, 0, indexFormat.Length());
+
+ return rv;
+}
+
+
+// nsIRequestObserver implementation
+NS_IMETHODIMP
+nsFTPDirListingConv::OnStartRequest(nsIRequest* request, nsISupports *ctxt) {
+ // we don't care about start. move along... but start masqeurading
+ // as the http-index channel now.
+ return mFinalListener->OnStartRequest(request, ctxt);
+}
+
+NS_IMETHODIMP
+nsFTPDirListingConv::OnStopRequest(nsIRequest* request, nsISupports *ctxt,
+ nsresult aStatus) {
+ // we don't care about stop. move along...
+
+ return mFinalListener->OnStopRequest(request, ctxt, aStatus);
+}
+
+
+// nsFTPDirListingConv methods
+nsFTPDirListingConv::nsFTPDirListingConv() {
+ mFinalListener = nullptr;
+ mSentHeading = false;
+}
+
+nsFTPDirListingConv::~nsFTPDirListingConv() {
+ NS_IF_RELEASE(mFinalListener);
+}
+
+nsresult
+nsFTPDirListingConv::GetHeaders(nsACString& headers,
+ nsIURI* uri)
+{
+ nsresult rv = NS_OK;
+ // build up 300 line
+ headers.AppendLiteral("300: ");
+
+ // Bug 111117 - don't print the password
+ nsAutoCString pw;
+ nsAutoCString spec;
+ uri->GetPassword(pw);
+ if (!pw.IsEmpty()) {
+ rv = uri->SetPassword(EmptyCString());
+ if (NS_FAILED(rv)) return rv;
+ rv = uri->GetAsciiSpec(spec);
+ if (NS_FAILED(rv)) return rv;
+ headers.Append(spec);
+ rv = uri->SetPassword(pw);
+ if (NS_FAILED(rv)) return rv;
+ } else {
+ rv = uri->GetAsciiSpec(spec);
+ if (NS_FAILED(rv)) return rv;
+
+ headers.Append(spec);
+ }
+ headers.Append(char(nsCRT::LF));
+ // END 300:
+
+ // build up the column heading; 200:
+ headers.AppendLiteral("200: filename content-length last-modified file-type\n");
+ // END 200:
+ return rv;
+}
+
+char *
+nsFTPDirListingConv::DigestBufferLines(char *aBuffer, nsCString &aString) {
+ char *line = aBuffer;
+ char *eol;
+ bool cr = false;
+
+ list_state state;
+
+ // while we have new lines, parse 'em into application/http-index-format.
+ while ( line && (eol = PL_strchr(line, nsCRT::LF)) ) {
+ // yank any carriage returns too.
+ if (eol > line && *(eol-1) == nsCRT::CR) {
+ eol--;
+ *eol = '\0';
+ cr = true;
+ } else {
+ *eol = '\0';
+ cr = false;
+ }
+
+ list_result result;
+
+ int type = ParseFTPList(line, &state, &result );
+
+ // 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] == '.'))) )
+ {
+ if (cr)
+ line = eol+2;
+ else
+ line = eol+1;
+
+ continue;
+ }
+
+ // blast the index entry into the indexFormat buffer as a 201: line.
+ aString.AppendLiteral("201: ");
+ // FILENAME
+
+ // parsers for styles 'U' and 'W' handle sequence " -> " themself
+ if (state.lstyle != 'U' && state.lstyle != 'W') {
+ const char* offset = strstr(result.fe_fname, " -> ");
+ if (offset) {
+ result.fe_fnlen = offset - result.fe_fname;
+ }
+ }
+
+ nsAutoCString buf;
+ aString.Append('\"');
+ aString.Append(NS_EscapeURL(Substring(result.fe_fname,
+ result.fe_fname+result.fe_fnlen),
+ esc_Minimal|esc_OnlyASCII|esc_Forced,buf));
+ aString.AppendLiteral("\" ");
+
+ // CONTENT LENGTH
+
+ if (type != 'd')
+ {
+ for (int i = 0; i < int(sizeof(result.fe_size)); ++i)
+ {
+ if (result.fe_size[i] != '\0')
+ aString.Append((const char*)&result.fe_size[i], 1);
+ }
+
+ aString.Append(' ');
+ }
+ else
+ aString.AppendLiteral("0 ");
+
+
+ // MODIFIED DATE
+ char buffer[256] = "";
+
+ // ParseFTPList can return time structure with invalid values.
+ // PR_NormalizeTime will set all values into valid limits.
+ result.fe_time.tm_params.tp_gmt_offset = 0;
+ result.fe_time.tm_params.tp_dst_offset = 0;
+ PR_NormalizeTime(&result.fe_time, PR_GMTParameters);
+
+ // 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),
+ "%a, %d %b %Y %H:%M:%S", &result.fe_time );
+
+ nsAutoCString escaped;
+ Unused << NS_WARN_IF(!NS_Escape(nsDependentCString(buffer), escaped, url_Path));
+ aString.Append(escaped);
+ aString.Append(' ');
+
+ // ENTRY TYPE
+ if (type == 'd')
+ aString.AppendLiteral("DIRECTORY");
+ else if (type == 'l')
+ aString.AppendLiteral("SYMBOLIC-LINK");
+ else
+ aString.AppendLiteral("FILE");
+
+ aString.Append(' ');
+
+ aString.Append(char(nsCRT::LF)); // complete this line
+ // END 201:
+
+ if (cr)
+ line = eol+2;
+ else
+ line = eol+1;
+ } // end while(eol)
+
+ return line;
+}
+
+nsresult
+NS_NewFTPDirListingConv(nsFTPDirListingConv** aFTPDirListingConv)
+{
+ NS_PRECONDITION(aFTPDirListingConv != nullptr, "null ptr");
+ if (! aFTPDirListingConv)
+ return NS_ERROR_NULL_POINTER;
+
+ *aFTPDirListingConv = new nsFTPDirListingConv();
+ if (! *aFTPDirListingConv)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(*aFTPDirListingConv);
+ return NS_OK;
+}
diff --git a/netwerk/streamconv/converters/nsFTPDirListingConv.h b/netwerk/streamconv/converters/nsFTPDirListingConv.h
new file mode 100644
index 000000000..b85877a05
--- /dev/null
+++ b/netwerk/streamconv/converters/nsFTPDirListingConv.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef __nsftpdirlistingdconv__h__
+#define __nsftpdirlistingdconv__h__
+
+#include "nsIStreamConverter.h"
+#include "nsString.h"
+
+class nsIURI;
+
+#define NS_FTPDIRLISTINGCONVERTER_CID \
+{ /* 14C0E880-623E-11d3-A178-0050041CAF44 */ \
+ 0x14c0e880, \
+ 0x623e, \
+ 0x11d3, \
+ {0xa1, 0x78, 0x00, 0x50, 0x04, 0x1c, 0xaf, 0x44} \
+}
+
+class nsFTPDirListingConv : public nsIStreamConverter {
+public:
+ // nsISupports methods
+ NS_DECL_ISUPPORTS
+
+ // nsIStreamConverter methods
+ NS_DECL_NSISTREAMCONVERTER
+
+ // nsIStreamListener methods
+ NS_DECL_NSISTREAMLISTENER
+
+ // nsIRequestObserver methods
+ NS_DECL_NSIREQUESTOBSERVER
+
+ // nsFTPDirListingConv methods
+ nsFTPDirListingConv();
+
+private:
+ virtual ~nsFTPDirListingConv();
+
+ // Get the application/http-index-format headers
+ nsresult GetHeaders(nsACString& str, nsIURI* uri);
+ char* DigestBufferLines(char *aBuffer, nsCString &aString);
+
+ // member data
+ nsCString mBuffer; // buffered data.
+ bool mSentHeading; // have we sent 100, 101, 200, and 300 lines yet?
+
+ nsIStreamListener *mFinalListener; // this guy gets the converted data via his OnDataAvailable()
+};
+
+#endif /* __nsftpdirlistingdconv__h__ */
diff --git a/netwerk/streamconv/converters/nsHTTPCompressConv.cpp b/netwerk/streamconv/converters/nsHTTPCompressConv.cpp
new file mode 100644
index 000000000..37b4b28b0
--- /dev/null
+++ b/netwerk/streamconv/converters/nsHTTPCompressConv.cpp
@@ -0,0 +1,659 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsHTTPCompressConv.h"
+#include "nsMemory.h"
+#include "plstr.h"
+#include "nsCOMPtr.h"
+#include "nsError.h"
+#include "nsStreamUtils.h"
+#include "nsStringStream.h"
+#include "nsComponentManagerUtils.h"
+#include "nsThreadUtils.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/Logging.h"
+#include "nsIForcePendingChannel.h"
+#include "nsIRequest.h"
+
+// brotli headers
+#include "state.h"
+#include "decode.h"
+
+namespace mozilla {
+namespace net {
+
+extern LazyLogModule gHttpLog;
+#define LOG(args) MOZ_LOG(mozilla::net::gHttpLog, mozilla::LogLevel::Debug, args)
+
+// nsISupports implementation
+NS_IMPL_ISUPPORTS(nsHTTPCompressConv,
+ nsIStreamConverter,
+ nsIStreamListener,
+ nsIRequestObserver,
+ nsICompressConvStats)
+
+// nsFTPDirListingConv methods
+nsHTTPCompressConv::nsHTTPCompressConv()
+ : mMode(HTTP_COMPRESS_IDENTITY)
+ , mOutBuffer(nullptr)
+ , mInpBuffer(nullptr)
+ , mOutBufferLen(0)
+ , mInpBufferLen(0)
+ , mCheckHeaderDone(false)
+ , mStreamEnded(false)
+ , mStreamInitialized(false)
+ , mLen(0)
+ , hMode(0)
+ , mSkipCount(0)
+ , mFlags(0)
+ , mDecodedDataLength(0)
+{
+ LOG(("nsHttpCompresssConv %p ctor\n", this));
+ if (NS_IsMainThread()) {
+ mFailUncleanStops =
+ Preferences::GetBool("network.http.enforce-framing.http", false);
+ } else {
+ mFailUncleanStops = false;
+ }
+}
+
+nsHTTPCompressConv::~nsHTTPCompressConv()
+{
+ LOG(("nsHttpCompresssConv %p dtor\n", this));
+ if (mInpBuffer) {
+ free(mInpBuffer);
+ }
+
+ if (mOutBuffer) {
+ free(mOutBuffer);
+ }
+
+ // For some reason we are not getting Z_STREAM_END. But this was also seen
+ // for mozilla bug 198133. Need to handle this case.
+ if (mStreamInitialized && !mStreamEnded) {
+ inflateEnd (&d_stream);
+ }
+}
+
+NS_IMETHODIMP
+nsHTTPCompressConv::GetDecodedDataLength(uint64_t *aDecodedDataLength)
+{
+ *aDecodedDataLength = mDecodedDataLength;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHTTPCompressConv::AsyncConvertData(const char *aFromType,
+ const char *aToType,
+ nsIStreamListener *aListener,
+ nsISupports *aCtxt)
+{
+ if (!PL_strncasecmp(aFromType, HTTP_COMPRESS_TYPE, sizeof(HTTP_COMPRESS_TYPE)-1) ||
+ !PL_strncasecmp(aFromType, HTTP_X_COMPRESS_TYPE, sizeof(HTTP_X_COMPRESS_TYPE)-1)) {
+ mMode = HTTP_COMPRESS_COMPRESS;
+ } else if (!PL_strncasecmp(aFromType, HTTP_GZIP_TYPE, sizeof(HTTP_GZIP_TYPE)-1) ||
+ !PL_strncasecmp(aFromType, HTTP_X_GZIP_TYPE, sizeof(HTTP_X_GZIP_TYPE)-1)) {
+ mMode = HTTP_COMPRESS_GZIP;
+ } else if (!PL_strncasecmp(aFromType, HTTP_DEFLATE_TYPE, sizeof(HTTP_DEFLATE_TYPE)-1)) {
+ mMode = HTTP_COMPRESS_DEFLATE;
+ } else if (!PL_strncasecmp(aFromType, HTTP_BROTLI_TYPE, sizeof(HTTP_BROTLI_TYPE)-1)) {
+ mMode = HTTP_COMPRESS_BROTLI;
+ }
+ LOG(("nsHttpCompresssConv %p AsyncConvertData %s %s mode %d\n",
+ this, aFromType, aToType, mMode));
+
+ // hook ourself up with the receiving listener.
+ mListener = aListener;
+
+ mAsyncConvContext = aCtxt;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsHTTPCompressConv::OnStartRequest(nsIRequest* request, nsISupports *aContext)
+{
+ LOG(("nsHttpCompresssConv %p onstart\n", this));
+ return mListener->OnStartRequest(request, aContext);
+}
+
+NS_IMETHODIMP
+nsHTTPCompressConv::OnStopRequest(nsIRequest* request, nsISupports *aContext,
+ nsresult aStatus)
+{
+ nsresult status = aStatus;
+ LOG(("nsHttpCompresssConv %p onstop %x\n", this, aStatus));
+
+ // Framing integrity is enforced for content-encoding: gzip, but not for
+ // content-encoding: deflate. Note that gzip vs deflate is NOT determined
+ // by content sniffing but only via header.
+ if (!mStreamEnded && NS_SUCCEEDED(status) &&
+ (mFailUncleanStops && (mMode == HTTP_COMPRESS_GZIP)) ) {
+ // This is not a clean end of gzip stream: the transfer is incomplete.
+ status = NS_ERROR_NET_PARTIAL_TRANSFER;
+ LOG(("nsHttpCompresssConv %p onstop partial gzip\n", this));
+ }
+ if (NS_SUCCEEDED(status) && mMode == HTTP_COMPRESS_BROTLI) {
+ nsCOMPtr<nsIForcePendingChannel> fpChannel = do_QueryInterface(request);
+ bool isPending = false;
+ if (request) {
+ request->IsPending(&isPending);
+ }
+ if (fpChannel && !isPending) {
+ fpChannel->ForcePending(true);
+ }
+ if (mBrotli && (mBrotli->mTotalOut == 0) && !BrotliStateIsStreamEnd(&mBrotli->mState)) {
+ status = NS_ERROR_INVALID_CONTENT_ENCODING;
+ }
+ LOG(("nsHttpCompresssConv %p onstop brotlihandler rv %x\n", this, status));
+ if (fpChannel && !isPending) {
+ fpChannel->ForcePending(false);
+ }
+ }
+ return mListener->OnStopRequest(request, aContext, status);
+}
+
+
+/* static */ nsresult
+nsHTTPCompressConv::BrotliHandler(nsIInputStream *stream, void *closure, const char *dataIn,
+ uint32_t, uint32_t aAvail, uint32_t *countRead)
+{
+ MOZ_ASSERT(stream);
+ nsHTTPCompressConv *self = static_cast<nsHTTPCompressConv *>(closure);
+ *countRead = 0;
+
+ const size_t kOutSize = 128 * 1024; // just a chunk size, we call in a loop
+ uint8_t *outPtr;
+ size_t outSize;
+ size_t avail = aAvail;
+ BrotliResult res;
+
+ if (!self->mBrotli) {
+ *countRead = aAvail;
+ return NS_OK;
+ }
+
+ auto outBuffer = MakeUniqueFallible<uint8_t[]>(kOutSize);
+ if (outBuffer == nullptr) {
+ self->mBrotli->mStatus = NS_ERROR_OUT_OF_MEMORY;
+ return self->mBrotli->mStatus;
+ }
+
+ do {
+ outSize = kOutSize;
+ outPtr = outBuffer.get();
+
+ // brotli api is documented in brotli/dec/decode.h and brotli/dec/decode.c
+ LOG(("nsHttpCompresssConv %p brotlihandler decompress %d\n", self, avail));
+ res = ::BrotliDecompressStream(
+ &avail, reinterpret_cast<const unsigned char **>(&dataIn),
+ &outSize, &outPtr, &self->mBrotli->mTotalOut, &self->mBrotli->mState);
+ outSize = kOutSize - outSize;
+ LOG(("nsHttpCompresssConv %p brotlihandler decompress rv=%x out=%d\n",
+ self, res, outSize));
+
+ if (res == BROTLI_RESULT_ERROR) {
+ LOG(("nsHttpCompressConv %p marking invalid encoding", self));
+ self->mBrotli->mStatus = NS_ERROR_INVALID_CONTENT_ENCODING;
+ return self->mBrotli->mStatus;
+ }
+
+ // in 'the current implementation' brotli must consume everything before
+ // asking for more input
+ if (res == BROTLI_RESULT_NEEDS_MORE_INPUT) {
+ MOZ_ASSERT(!avail);
+ if (avail) {
+ LOG(("nsHttpCompressConv %p did not consume all input", self));
+ self->mBrotli->mStatus = NS_ERROR_UNEXPECTED;
+ return self->mBrotli->mStatus;
+ }
+ }
+ if (outSize > 0) {
+ nsresult rv = self->do_OnDataAvailable(self->mBrotli->mRequest,
+ self->mBrotli->mContext,
+ self->mBrotli->mSourceOffset,
+ reinterpret_cast<const char *>(outBuffer.get()),
+ outSize);
+ LOG(("nsHttpCompressConv %p BrotliHandler ODA rv=%x", self, rv));
+ if (NS_FAILED(rv)) {
+ self->mBrotli->mStatus = rv;
+ return self->mBrotli->mStatus;
+ }
+ }
+
+ if (res == BROTLI_RESULT_SUCCESS ||
+ res == BROTLI_RESULT_NEEDS_MORE_INPUT) {
+ *countRead = aAvail;
+ return NS_OK;
+ }
+ MOZ_ASSERT (res == BROTLI_RESULT_NEEDS_MORE_OUTPUT);
+ } while (res == BROTLI_RESULT_NEEDS_MORE_OUTPUT);
+
+ self->mBrotli->mStatus = NS_ERROR_UNEXPECTED;
+ return self->mBrotli->mStatus;
+}
+
+NS_IMETHODIMP
+nsHTTPCompressConv::OnDataAvailable(nsIRequest* request,
+ nsISupports *aContext,
+ nsIInputStream *iStr,
+ uint64_t aSourceOffset,
+ uint32_t aCount)
+{
+ nsresult rv = NS_ERROR_INVALID_CONTENT_ENCODING;
+ uint32_t streamLen = aCount;
+ LOG(("nsHttpCompressConv %p OnDataAvailable %d", this, aCount));
+
+ if (streamLen == 0) {
+ NS_ERROR("count of zero passed to OnDataAvailable");
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ if (mStreamEnded) {
+ // Hmm... this may just indicate that the data stream is done and that
+ // what's left is either metadata or padding of some sort.... throwing
+ // it out is probably the safe thing to do.
+ uint32_t n;
+ return iStr->ReadSegments(NS_DiscardSegment, nullptr, streamLen, &n);
+ }
+
+ switch (mMode) {
+ case HTTP_COMPRESS_GZIP:
+ streamLen = check_header(iStr, streamLen, &rv);
+
+ if (rv != NS_OK) {
+ return rv;
+ }
+
+ if (streamLen == 0) {
+ return NS_OK;
+ }
+
+ MOZ_FALLTHROUGH;
+
+ case HTTP_COMPRESS_DEFLATE:
+
+ if (mInpBuffer != nullptr && streamLen > mInpBufferLen) {
+ mInpBuffer = (unsigned char *) realloc(mInpBuffer, mInpBufferLen = streamLen);
+
+ if (mOutBufferLen < streamLen * 2) {
+ mOutBuffer = (unsigned char *) realloc(mOutBuffer, mOutBufferLen = streamLen * 3);
+ }
+
+ if (mInpBuffer == nullptr || mOutBuffer == nullptr) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ if (mInpBuffer == nullptr) {
+ mInpBuffer = (unsigned char *) malloc(mInpBufferLen = streamLen);
+ }
+
+ if (mOutBuffer == nullptr) {
+ mOutBuffer = (unsigned char *) malloc(mOutBufferLen = streamLen * 3);
+ }
+
+ if (mInpBuffer == nullptr || mOutBuffer == nullptr) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ uint32_t unused;
+ iStr->Read((char *)mInpBuffer, streamLen, &unused);
+
+ if (mMode == HTTP_COMPRESS_DEFLATE) {
+ if (!mStreamInitialized) {
+ memset(&d_stream, 0, sizeof (d_stream));
+
+ if (inflateInit(&d_stream) != Z_OK) {
+ return NS_ERROR_FAILURE;
+ }
+
+ mStreamInitialized = true;
+ }
+ d_stream.next_in = mInpBuffer;
+ d_stream.avail_in = (uInt)streamLen;
+
+ mDummyStreamInitialised = false;
+ for (;;) {
+ d_stream.next_out = mOutBuffer;
+ d_stream.avail_out = (uInt)mOutBufferLen;
+
+ int code = inflate(&d_stream, Z_NO_FLUSH);
+ unsigned bytesWritten = (uInt)mOutBufferLen - d_stream.avail_out;
+
+ if (code == Z_STREAM_END) {
+ if (bytesWritten) {
+ rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char *)mOutBuffer, bytesWritten);
+ if (NS_FAILED (rv)) {
+ return rv;
+ }
+ }
+
+ inflateEnd(&d_stream);
+ mStreamEnded = true;
+ break;
+ } else if (code == Z_OK) {
+ if (bytesWritten) {
+ rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char *)mOutBuffer, bytesWritten);
+ if (NS_FAILED (rv)) {
+ return rv;
+ }
+ }
+ } else if (code == Z_BUF_ERROR) {
+ if (bytesWritten) {
+ rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char *)mOutBuffer, bytesWritten);
+ if (NS_FAILED (rv)) {
+ return rv;
+ }
+ }
+ break;
+ } else if (code == Z_DATA_ERROR) {
+ // some servers (notably Apache with mod_deflate) don't generate zlib headers
+ // insert a dummy header and try again
+ static char dummy_head[2] =
+ {
+ 0x8 + 0x7 * 0x10,
+ (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,
+ };
+ inflateReset(&d_stream);
+ d_stream.next_in = (Bytef*) dummy_head;
+ d_stream.avail_in = sizeof(dummy_head);
+
+ code = inflate(&d_stream, Z_NO_FLUSH);
+ if (code != Z_OK) {
+ return NS_ERROR_FAILURE;
+ }
+
+ // stop an endless loop caused by non-deflate data being labelled as deflate
+ if (mDummyStreamInitialised) {
+ NS_WARNING("endless loop detected"
+ " - invalid deflate");
+ return NS_ERROR_INVALID_CONTENT_ENCODING;
+ }
+ mDummyStreamInitialised = true;
+ // reset stream pointers to our original data
+ d_stream.next_in = mInpBuffer;
+ d_stream.avail_in = (uInt)streamLen;
+ } else {
+ return NS_ERROR_INVALID_CONTENT_ENCODING;
+ }
+ } /* for */
+ } else {
+ if (!mStreamInitialized) {
+ memset(&d_stream, 0, sizeof (d_stream));
+
+ if (inflateInit2(&d_stream, -MAX_WBITS) != Z_OK) {
+ return NS_ERROR_FAILURE;
+ }
+
+ mStreamInitialized = true;
+ }
+
+ d_stream.next_in = mInpBuffer;
+ d_stream.avail_in = (uInt)streamLen;
+
+ for (;;) {
+ d_stream.next_out = mOutBuffer;
+ d_stream.avail_out = (uInt)mOutBufferLen;
+
+ int code = inflate (&d_stream, Z_NO_FLUSH);
+ unsigned bytesWritten = (uInt)mOutBufferLen - d_stream.avail_out;
+
+ if (code == Z_STREAM_END) {
+ if (bytesWritten) {
+ rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char *)mOutBuffer, bytesWritten);
+ if (NS_FAILED (rv)) {
+ return rv;
+ }
+ }
+
+ inflateEnd(&d_stream);
+ mStreamEnded = true;
+ break;
+ } else if (code == Z_OK) {
+ if (bytesWritten) {
+ rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char *)mOutBuffer, bytesWritten);
+ if (NS_FAILED (rv)) {
+ return rv;
+ }
+ }
+ } else if (code == Z_BUF_ERROR) {
+ if (bytesWritten) {
+ rv = do_OnDataAvailable(request, aContext, aSourceOffset, (char *)mOutBuffer, bytesWritten);
+ if (NS_FAILED (rv)) {
+ return rv;
+ }
+ }
+ break;
+ } else {
+ return NS_ERROR_INVALID_CONTENT_ENCODING;
+ }
+ } /* for */
+ } /* gzip */
+ break;
+
+ case HTTP_COMPRESS_BROTLI:
+ {
+ if (!mBrotli) {
+ mBrotli = new BrotliWrapper();
+ }
+
+ mBrotli->mRequest = request;
+ mBrotli->mContext = aContext;
+ mBrotli->mSourceOffset = aSourceOffset;
+
+ uint32_t countRead;
+ rv = iStr->ReadSegments(BrotliHandler, this, streamLen, &countRead);
+ if (NS_SUCCEEDED(rv)) {
+ rv = mBrotli->mStatus;
+ }
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ }
+ break;
+
+ default:
+ rv = mListener->OnDataAvailable(request, aContext, iStr, aSourceOffset, aCount);
+ if (NS_FAILED (rv)) {
+ return rv;
+ }
+ } /* switch */
+
+ return NS_OK;
+} /* OnDataAvailable */
+
+// XXX/ruslan: need to implement this too
+
+NS_IMETHODIMP
+nsHTTPCompressConv::Convert(nsIInputStream *aFromStream,
+ const char *aFromType,
+ const char *aToType,
+ nsISupports *aCtxt,
+ nsIInputStream **_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+nsHTTPCompressConv::do_OnDataAvailable(nsIRequest* request,
+ nsISupports *context, uint64_t offset,
+ const char *buffer, uint32_t count)
+{
+ if (!mStream) {
+ mStream = do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID);
+ NS_ENSURE_STATE(mStream);
+ }
+
+ mStream->ShareData(buffer, count);
+
+ nsresult rv = mListener->OnDataAvailable(request, context, mStream,
+ offset, count);
+
+ // Make sure the stream no longer references |buffer| in case our listener
+ // is crazy enough to try to read from |mStream| after ODA.
+ mStream->ShareData("", 0);
+ mDecodedDataLength += count;
+
+ return rv;
+}
+
+#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
+#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
+#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
+#define COMMENT 0x10 /* bit 4 set: file comment present */
+#define RESERVED 0xE0 /* bits 5..7: reserved */
+
+static unsigned gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
+
+uint32_t
+nsHTTPCompressConv::check_header(nsIInputStream *iStr, uint32_t streamLen, nsresult *rs)
+{
+ enum { GZIP_INIT = 0, GZIP_OS, GZIP_EXTRA0, GZIP_EXTRA1, GZIP_EXTRA2, GZIP_ORIG, GZIP_COMMENT, GZIP_CRC };
+ char c;
+
+ *rs = NS_OK;
+
+ if (mCheckHeaderDone) {
+ return streamLen;
+ }
+
+ while (streamLen) {
+ switch (hMode) {
+ case GZIP_INIT:
+ uint32_t unused;
+ iStr->Read(&c, 1, &unused);
+ streamLen--;
+
+ if (mSkipCount == 0 && ((unsigned)c & 0377) != gz_magic[0]) {
+ *rs = NS_ERROR_INVALID_CONTENT_ENCODING;
+ return 0;
+ }
+
+ if (mSkipCount == 1 && ((unsigned)c & 0377) != gz_magic[1]) {
+ *rs = NS_ERROR_INVALID_CONTENT_ENCODING;
+ return 0;
+ }
+
+ if (mSkipCount == 2 && ((unsigned)c & 0377) != Z_DEFLATED) {
+ *rs = NS_ERROR_INVALID_CONTENT_ENCODING;
+ return 0;
+ }
+
+ mSkipCount++;
+ if (mSkipCount == 4) {
+ mFlags = (unsigned) c & 0377;
+ if (mFlags & RESERVED) {
+ *rs = NS_ERROR_INVALID_CONTENT_ENCODING;
+ return 0;
+ }
+ hMode = GZIP_OS;
+ mSkipCount = 0;
+ }
+ break;
+
+ case GZIP_OS:
+ iStr->Read(&c, 1, &unused);
+ streamLen--;
+ mSkipCount++;
+
+ if (mSkipCount == 6) {
+ hMode = GZIP_EXTRA0;
+ }
+ break;
+
+ case GZIP_EXTRA0:
+ if (mFlags & EXTRA_FIELD) {
+ iStr->Read(&c, 1, &unused);
+ streamLen--;
+ mLen = (uInt) c & 0377;
+ hMode = GZIP_EXTRA1;
+ } else {
+ hMode = GZIP_ORIG;
+ }
+ break;
+
+ case GZIP_EXTRA1:
+ iStr->Read(&c, 1, &unused);
+ streamLen--;
+ mLen |= ((uInt) c & 0377) << 8;
+ mSkipCount = 0;
+ hMode = GZIP_EXTRA2;
+ break;
+
+ case GZIP_EXTRA2:
+ if (mSkipCount == mLen) {
+ hMode = GZIP_ORIG;
+ } else {
+ iStr->Read(&c, 1, &unused);
+ streamLen--;
+ mSkipCount++;
+ }
+ break;
+
+ case GZIP_ORIG:
+ if (mFlags & ORIG_NAME) {
+ iStr->Read(&c, 1, &unused);
+ streamLen--;
+ if (c == 0)
+ hMode = GZIP_COMMENT;
+ } else {
+ hMode = GZIP_COMMENT;
+ }
+ break;
+
+ case GZIP_COMMENT:
+ if (mFlags & COMMENT) {
+ iStr->Read(&c, 1, &unused);
+ streamLen--;
+ if (c == 0) {
+ hMode = GZIP_CRC;
+ mSkipCount = 0;
+ }
+ } else {
+ hMode = GZIP_CRC;
+ mSkipCount = 0;
+ }
+ break;
+
+ case GZIP_CRC:
+ if (mFlags & HEAD_CRC) {
+ iStr->Read(&c, 1, &unused);
+ streamLen--;
+ mSkipCount++;
+ if (mSkipCount == 2) {
+ mCheckHeaderDone = true;
+ return streamLen;
+ }
+ } else {
+ mCheckHeaderDone = true;
+ return streamLen;
+ }
+ break;
+ }
+ }
+ return streamLen;
+}
+
+} // namespace net
+} // namespace mozilla
+
+nsresult
+NS_NewHTTPCompressConv(mozilla::net::nsHTTPCompressConv **aHTTPCompressConv)
+{
+ NS_PRECONDITION(aHTTPCompressConv != nullptr, "null ptr");
+ if (!aHTTPCompressConv) {
+ return NS_ERROR_NULL_POINTER;
+ }
+
+ RefPtr<mozilla::net::nsHTTPCompressConv> outVal =
+ new mozilla::net::nsHTTPCompressConv();
+ if (!outVal) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ outVal.forget(aHTTPCompressConv);
+ return NS_OK;
+}
diff --git a/netwerk/streamconv/converters/nsHTTPCompressConv.h b/netwerk/streamconv/converters/nsHTTPCompressConv.h
new file mode 100644
index 000000000..38889a8f7
--- /dev/null
+++ b/netwerk/streamconv/converters/nsHTTPCompressConv.h
@@ -0,0 +1,135 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#if !defined (__nsHTTPCompressConv__h__)
+#define __nsHTTPCompressConv__h__ 1
+
+#include "nsIStreamConverter.h"
+#include "nsICompressConvStats.h"
+#include "nsCOMPtr.h"
+#include "nsAutoPtr.h"
+
+#include "zlib.h"
+
+// brotli includes
+#undef assert
+#include "assert.h"
+#include "state.h"
+
+class nsIStringInputStream;
+
+#define NS_HTTPCOMPRESSCONVERTER_CID \
+ { \
+ /* 66230b2b-17fa-4bd3-abf4-07986151022d */ \
+ 0x66230b2b, \
+ 0x17fa, \
+ 0x4bd3, \
+ {0xab, 0xf4, 0x07, 0x98, 0x61, 0x51, 0x02, 0x2d} \
+ }
+
+
+#define HTTP_DEFLATE_TYPE "deflate"
+#define HTTP_GZIP_TYPE "gzip"
+#define HTTP_X_GZIP_TYPE "x-gzip"
+#define HTTP_COMPRESS_TYPE "compress"
+#define HTTP_X_COMPRESS_TYPE "x-compress"
+#define HTTP_BROTLI_TYPE "br"
+#define HTTP_IDENTITY_TYPE "identity"
+#define HTTP_UNCOMPRESSED_TYPE "uncompressed"
+
+namespace mozilla {
+namespace net {
+
+typedef enum {
+ HTTP_COMPRESS_GZIP,
+ HTTP_COMPRESS_DEFLATE,
+ HTTP_COMPRESS_COMPRESS,
+ HTTP_COMPRESS_BROTLI,
+ HTTP_COMPRESS_IDENTITY
+} CompressMode;
+
+class BrotliWrapper
+{
+public:
+ BrotliWrapper()
+ : mTotalOut(0)
+ , mStatus(NS_OK)
+ {
+ BrotliStateInit(&mState);
+ }
+ ~BrotliWrapper()
+ {
+ BrotliStateCleanup(&mState);
+ }
+
+ BrotliState mState;
+ size_t mTotalOut;
+ nsresult mStatus;
+
+ nsIRequest *mRequest;
+ nsISupports *mContext;
+ uint64_t mSourceOffset;
+};
+
+class nsHTTPCompressConv
+ : public nsIStreamConverter
+ , public nsICompressConvStats
+{
+ public:
+ // nsISupports methods
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_NSIREQUESTOBSERVER
+ NS_DECL_NSISTREAMLISTENER
+ NS_DECL_NSICOMPRESSCONVSTATS
+
+ // nsIStreamConverter methods
+ NS_DECL_NSISTREAMCONVERTER
+
+ nsHTTPCompressConv ();
+
+private:
+ virtual ~nsHTTPCompressConv ();
+
+ nsCOMPtr<nsIStreamListener> mListener; // this guy gets the converted data via his OnDataAvailable ()
+ CompressMode mMode;
+
+ unsigned char *mOutBuffer;
+ unsigned char *mInpBuffer;
+
+ uint32_t mOutBufferLen;
+ uint32_t mInpBufferLen;
+
+ nsAutoPtr<BrotliWrapper> mBrotli;
+
+ nsCOMPtr<nsISupports> mAsyncConvContext;
+ nsCOMPtr<nsIStringInputStream> mStream;
+
+ static nsresult
+ BrotliHandler(nsIInputStream *stream, void *closure, const char *dataIn,
+ uint32_t, uint32_t avail, uint32_t *countRead);
+
+ nsresult do_OnDataAvailable (nsIRequest *request, nsISupports *aContext,
+ uint64_t aSourceOffset, const char *buffer,
+ uint32_t aCount);
+
+ bool mCheckHeaderDone;
+ bool mStreamEnded;
+ bool mStreamInitialized;
+ bool mDummyStreamInitialised;
+ bool mFailUncleanStops;
+
+ z_stream d_stream;
+ unsigned mLen, hMode, mSkipCount, mFlags;
+
+ uint32_t check_header (nsIInputStream *iStr, uint32_t streamLen, nsresult *rv);
+
+ uint32_t mDecodedDataLength;
+};
+
+} // namespace net
+} // namespace mozilla
+
+#endif
diff --git a/netwerk/streamconv/converters/nsICompressConvStats.idl b/netwerk/streamconv/converters/nsICompressConvStats.idl
new file mode 100644
index 000000000..a8837563e
--- /dev/null
+++ b/netwerk/streamconv/converters/nsICompressConvStats.idl
@@ -0,0 +1,17 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+/**
+ * nsICompressConvStats
+ *
+ * This interface allows for the observation of decoded resource sizes
+ */
+[builtinclass, scriptable, uuid(58172ad0-46a9-4893-8fde-cd909c10792a)]
+interface nsICompressConvStats : nsISupports
+{
+ readonly attribute uint64_t decodedDataLength;
+};
diff --git a/netwerk/streamconv/converters/nsIndexedToHTML.cpp b/netwerk/streamconv/converters/nsIndexedToHTML.cpp
new file mode 100644
index 000000000..0414c4841
--- /dev/null
+++ b/netwerk/streamconv/converters/nsIndexedToHTML.cpp
@@ -0,0 +1,895 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIndexedToHTML.h"
+#include "mozilla/dom/EncodingUtils.h"
+#include "nsNetUtil.h"
+#include "netCore.h"
+#include "nsStringStream.h"
+#include "nsIFile.h"
+#include "nsIFileURL.h"
+#include "nsEscape.h"
+#include "nsIDirIndex.h"
+#include "nsURLHelper.h"
+#include "nsIPlatformCharset.h"
+#include "nsIPrefService.h"
+#include "nsIPrefBranch.h"
+#include "nsIPrefLocalizedString.h"
+#include "nsIChromeRegistry.h"
+#include "nsIDateTimeFormat.h"
+#include "nsIStringBundle.h"
+#include "nsITextToSubURI.h"
+#include "nsXPIDLString.h"
+#include <algorithm>
+#include "nsIChannel.h"
+
+NS_IMPL_ISUPPORTS(nsIndexedToHTML,
+ nsIDirIndexListener,
+ nsIStreamConverter,
+ nsIRequestObserver,
+ nsIStreamListener)
+
+static void AppendNonAsciiToNCR(const nsAString& in, nsCString& out)
+{
+ nsAString::const_iterator start, end;
+
+ in.BeginReading(start);
+ in.EndReading(end);
+
+ while (start != end) {
+ if (*start < 128) {
+ out.Append(*start++);
+ } else {
+ out.AppendLiteral("&#x");
+ out.AppendInt(*start++, 16);
+ out.Append(';');
+ }
+ }
+}
+
+nsresult
+nsIndexedToHTML::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) {
+ nsresult rv;
+ if (aOuter)
+ return NS_ERROR_NO_AGGREGATION;
+
+ nsIndexedToHTML* _s = new nsIndexedToHTML();
+ if (_s == nullptr)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = _s->QueryInterface(aIID, aResult);
+ return rv;
+}
+
+nsresult
+nsIndexedToHTML::Init(nsIStreamListener* aListener) {
+ nsresult rv = NS_OK;
+
+ mListener = aListener;
+
+ mDateTime = nsIDateTimeFormat::Create();
+ if (!mDateTime)
+ return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIStringBundleService> sbs =
+ do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
+ if (NS_FAILED(rv)) return rv;
+ rv = sbs->CreateBundle(NECKO_MSGS_URL, getter_AddRefs(mBundle));
+
+ mExpectAbsLoc = false;
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsIndexedToHTML::Convert(nsIInputStream* aFromStream,
+ const char* aFromType,
+ const char* aToType,
+ nsISupports* aCtxt,
+ nsIInputStream** res) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsIndexedToHTML::AsyncConvertData(const char *aFromType,
+ const char *aToType,
+ nsIStreamListener *aListener,
+ nsISupports *aCtxt) {
+ return Init(aListener);
+}
+
+NS_IMETHODIMP
+nsIndexedToHTML::OnStartRequest(nsIRequest* request, nsISupports *aContext) {
+ nsCString buffer;
+ nsresult rv = DoOnStartRequest(request, aContext, buffer);
+ if (NS_FAILED(rv)) {
+ request->Cancel(rv);
+ }
+
+ rv = mListener->OnStartRequest(request, aContext);
+ if (NS_FAILED(rv)) return rv;
+
+ // The request may have been canceled, and if that happens, we want to
+ // suppress calls to OnDataAvailable.
+ request->GetStatus(&rv);
+ if (NS_FAILED(rv)) return rv;
+
+ // Push our buffer to the listener.
+
+ rv = SendToListener(request, aContext, buffer);
+ return rv;
+}
+
+nsresult
+nsIndexedToHTML::DoOnStartRequest(nsIRequest* request, nsISupports *aContext,
+ nsCString& aBuffer) {
+ nsresult rv;
+
+ nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
+ nsCOMPtr<nsIURI> uri;
+ rv = channel->GetURI(getter_AddRefs(uri));
+ if (NS_FAILED(rv)) return rv;
+
+ channel->SetContentType(NS_LITERAL_CSTRING("text/html"));
+
+ mParser = do_CreateInstance("@mozilla.org/dirIndexParser;1",&rv);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = mParser->SetListener(this);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = mParser->OnStartRequest(request, aContext);
+ if (NS_FAILED(rv)) return rv;
+
+ nsAutoCString baseUri, titleUri;
+ rv = uri->GetAsciiSpec(baseUri);
+ if (NS_FAILED(rv)) return rv;
+ titleUri = baseUri;
+
+ nsCString parentStr;
+
+ nsCString buffer;
+ buffer.AppendLiteral("<!DOCTYPE html>\n<html>\n<head>\n");
+
+ // XXX - should be using the 300: line from the parser.
+ // We can't guarantee that that comes before any entry, so we'd have to
+ // buffer, and do other painful stuff.
+ // I'll deal with this when I make the changes to handle welcome messages
+ // The .. stuff should also come from the lower level protocols, but that
+ // would muck up the XUL display
+ // - bbaetz
+
+ bool isScheme = false;
+ bool isSchemeFile = false;
+ if (NS_SUCCEEDED(uri->SchemeIs("ftp", &isScheme)) && isScheme) {
+
+ // strip out the password here, so it doesn't show in the page title
+ // This is done by the 300: line generation in ftp, but we don't use
+ // that - see above
+
+ nsAutoCString pw;
+ rv = uri->GetPassword(pw);
+ if (NS_FAILED(rv)) return rv;
+ if (!pw.IsEmpty()) {
+ nsCOMPtr<nsIURI> newUri;
+ rv = uri->Clone(getter_AddRefs(newUri));
+ if (NS_FAILED(rv)) return rv;
+ rv = newUri->SetPassword(EmptyCString());
+ if (NS_FAILED(rv)) return rv;
+ rv = newUri->GetAsciiSpec(titleUri);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ nsAutoCString path;
+ rv = uri->GetPath(path);
+ if (NS_FAILED(rv)) return rv;
+
+ if (!path.EqualsLiteral("//") && !path.LowerCaseEqualsLiteral("/%2f")) {
+ rv = uri->Resolve(NS_LITERAL_CSTRING(".."),parentStr);
+ if (NS_FAILED(rv)) return rv;
+ }
+ } else if (NS_SUCCEEDED(uri->SchemeIs("file", &isSchemeFile)) && isSchemeFile) {
+ nsCOMPtr<nsIFileURL> fileUrl = do_QueryInterface(uri);
+ nsCOMPtr<nsIFile> file;
+ rv = fileUrl->GetFile(getter_AddRefs(file));
+ if (NS_FAILED(rv)) return rv;
+ file->SetFollowLinks(true);
+
+ nsAutoCString url;
+ rv = net_GetURLSpecFromFile(file, url);
+ if (NS_FAILED(rv)) return rv;
+ baseUri.Assign(url);
+
+ nsCOMPtr<nsIFile> parent;
+ rv = file->GetParent(getter_AddRefs(parent));
+
+ if (parent && NS_SUCCEEDED(rv)) {
+ net_GetURLSpecFromDir(parent, url);
+ if (NS_FAILED(rv)) return rv;
+ parentStr.Assign(url);
+ }
+
+ // Directory index will be always encoded in UTF-8 if this is file url
+ buffer.AppendLiteral("<meta charset=\"UTF-8\">\n");
+
+ } else if (NS_SUCCEEDED(uri->SchemeIs("jar", &isScheme)) && isScheme) {
+ nsAutoCString path;
+ rv = uri->GetPath(path);
+ if (NS_FAILED(rv)) return rv;
+
+ // a top-level jar directory URL is of the form jar:foo.zip!/
+ // path will be of the form foo.zip!/, and its last two characters
+ // will be "!/"
+ //XXX this won't work correctly when the name of the directory being
+ //XXX displayed ends with "!", but then again, jar: URIs don't deal
+ //XXX particularly well with such directories anyway
+ if (!StringEndsWith(path, NS_LITERAL_CSTRING("!/"))) {
+ rv = uri->Resolve(NS_LITERAL_CSTRING(".."), parentStr);
+ if (NS_FAILED(rv)) return rv;
+ }
+ }
+ else {
+ // default behavior for other protocols is to assume the channel's
+ // URL references a directory ending in '/' -- fixup if necessary.
+ nsAutoCString path;
+ rv = uri->GetPath(path);
+ if (NS_FAILED(rv)) return rv;
+ if (baseUri.Last() != '/') {
+ baseUri.Append('/');
+ path.Append('/');
+ uri->SetPath(path);
+ }
+ if (!path.EqualsLiteral("/")) {
+ rv = uri->Resolve(NS_LITERAL_CSTRING(".."), parentStr);
+ if (NS_FAILED(rv)) return rv;
+ }
+ }
+
+ buffer.AppendLiteral("<style type=\"text/css\">\n"
+ ":root {\n"
+ " font-family: sans-serif;\n"
+ "}\n"
+ "img {\n"
+ " border: 0;\n"
+ "}\n"
+ "th {\n"
+ " text-align: start;\n"
+ " white-space: nowrap;\n"
+ "}\n"
+ "th > a {\n"
+ " color: inherit;\n"
+ "}\n"
+ "table[order] > thead > tr > th {\n"
+ " cursor: pointer;\n"
+ "}\n"
+ "table[order] > thead > tr > th::after {\n"
+ " display: none;\n"
+ " width: .8em;\n"
+ " margin-inline-end: -.8em;\n"
+ " text-align: end;\n"
+ "}\n"
+ "table[order=\"asc\"] > thead > tr > th::after {\n"
+ " content: \"\\2193\"; /* DOWNWARDS ARROW (U+2193) */\n"
+ "}\n"
+ "table[order=\"desc\"] > thead > tr > th::after {\n"
+ " content: \"\\2191\"; /* UPWARDS ARROW (U+2191) */\n"
+ "}\n"
+ "table[order][order-by=\"0\"] > thead > tr > th:first-child > a ,\n"
+ "table[order][order-by=\"1\"] > thead > tr > th:first-child + th > a ,\n"
+ "table[order][order-by=\"2\"] > thead > tr > th:first-child + th + th > a {\n"
+ " text-decoration: underline;\n"
+ "}\n"
+ "table[order][order-by=\"0\"] > thead > tr > th:first-child::after ,\n"
+ "table[order][order-by=\"1\"] > thead > tr > th:first-child + th::after ,\n"
+ "table[order][order-by=\"2\"] > thead > tr > th:first-child + th + th::after {\n"
+ " display: inline-block;\n"
+ "}\n"
+ "table.remove-hidden > tbody > tr.hidden-object {\n"
+ " display: none;\n"
+ "}\n"
+ "td {\n"
+ " white-space: nowrap;\n"
+ "}\n"
+ "table.ellipsis {\n"
+ " width: 100%;\n"
+ " table-layout: fixed;\n"
+ " border-spacing: 0;\n"
+ "}\n"
+ "table.ellipsis > tbody > tr > td {\n"
+ " padding: 0;\n"
+ " overflow: hidden;\n"
+ " text-overflow: ellipsis;\n"
+ "}\n"
+ "/* name */\n"
+ "/* name */\n"
+ "th:first-child {\n"
+ " padding-inline-end: 2em;\n"
+ "}\n"
+ "/* size */\n"
+ "th:first-child + th {\n"
+ " padding-inline-end: 1em;\n"
+ "}\n"
+ "td:first-child + td {\n"
+ " text-align: end;\n"
+ " padding-inline-end: 1em;\n"
+ "}\n"
+ "/* date */\n"
+ "td:first-child + td + td {\n"
+ " padding-inline-start: 1em;\n"
+ " padding-inline-end: .5em;\n"
+ "}\n"
+ "/* time */\n"
+ "td:first-child + td + td + td {\n"
+ " padding-inline-start: .5em;\n"
+ "}\n"
+ ".symlink {\n"
+ " font-style: italic;\n"
+ "}\n"
+ ".dir ,\n"
+ ".symlink ,\n"
+ ".file {\n"
+ " margin-inline-start: 20px;\n"
+ "}\n"
+ ".dir::before ,\n"
+ ".file > img {\n"
+ " margin-inline-end: 4px;\n"
+ " margin-inline-start: -20px;\n"
+ " max-width: 16px;\n"
+ " max-height: 16px;\n"
+ " vertical-align: middle;\n"
+ "}\n"
+ ".dir::before {\n"
+ " content: url(resource://gre/res/html/folder.png);\n"
+ "}\n"
+ "</style>\n"
+ "<link rel=\"stylesheet\" media=\"screen, projection\" type=\"text/css\""
+ " href=\"chrome://global/skin/dirListing/dirListing.css\">\n"
+ "<script type=\"application/javascript\">\n"
+ "'use strict';\n"
+ "var gTable, gOrderBy, gTBody, gRows, gUI_showHidden;\n"
+ "document.addEventListener(\"DOMContentLoaded\", function() {\n"
+ " gTable = document.getElementsByTagName(\"table\")[0];\n"
+ " gTBody = gTable.tBodies[0];\n"
+ " if (gTBody.rows.length < 2)\n"
+ " return;\n"
+ " gUI_showHidden = document.getElementById(\"UI_showHidden\");\n"
+ " var headCells = gTable.tHead.rows[0].cells,\n"
+ " hiddenObjects = false;\n"
+ " function rowAction(i) {\n"
+ " return function(event) {\n"
+ " event.preventDefault();\n"
+ " orderBy(i);\n"
+ " }\n"
+ " }\n"
+ " for (var i = headCells.length - 1; i >= 0; i--) {\n"
+ " var anchor = document.createElement(\"a\");\n"
+ " anchor.href = \"\";\n"
+ " anchor.appendChild(headCells[i].firstChild);\n"
+ " headCells[i].appendChild(anchor);\n"
+ " headCells[i].addEventListener(\"click\", rowAction(i), true);\n"
+ " }\n"
+ " if (gUI_showHidden) {\n"
+ " gRows = Array.slice(gTBody.rows);\n"
+ " hiddenObjects = gRows.some(row => row.className == \"hidden-object\");\n"
+ " }\n"
+ " gTable.setAttribute(\"order\", \"\");\n"
+ " if (hiddenObjects) {\n"
+ " gUI_showHidden.style.display = \"block\";\n"
+ " updateHidden();\n"
+ " }\n"
+ "}, \"false\");\n"
+ "function compareRows(rowA, rowB) {\n"
+ " var a = rowA.cells[gOrderBy].getAttribute(\"sortable-data\") || \"\";\n"
+ " var b = rowB.cells[gOrderBy].getAttribute(\"sortable-data\") || \"\";\n"
+ " var intA = +a;\n"
+ " var intB = +b;\n"
+ " if (a == intA && b == intB) {\n"
+ " a = intA;\n"
+ " b = intB;\n"
+ " } else {\n"
+ " a = a.toLowerCase();\n"
+ " b = b.toLowerCase();\n"
+ " }\n"
+ " if (a < b)\n"
+ " return -1;\n"
+ " if (a > b)\n"
+ " return 1;\n"
+ " return 0;\n"
+ "}\n"
+ "function orderBy(column) {\n"
+ " if (!gRows)\n"
+ " gRows = Array.slice(gTBody.rows);\n"
+ " var order;\n"
+ " if (gOrderBy == column) {\n"
+ " order = gTable.getAttribute(\"order\") == \"asc\" ? \"desc\" : \"asc\";\n"
+ " } else {\n"
+ " order = \"asc\";\n"
+ " gOrderBy = column;\n"
+ " gTable.setAttribute(\"order-by\", column);\n"
+ " gRows.sort(compareRows);\n"
+ " }\n"
+ " gTable.removeChild(gTBody);\n"
+ " gTable.setAttribute(\"order\", order);\n"
+ " if (order == \"asc\")\n"
+ " for (var i = 0; i < gRows.length; i++)\n"
+ " gTBody.appendChild(gRows[i]);\n"
+ " else\n"
+ " for (var i = gRows.length - 1; i >= 0; i--)\n"
+ " gTBody.appendChild(gRows[i]);\n"
+ " gTable.appendChild(gTBody);\n"
+ "}\n"
+ "function updateHidden() {\n"
+ " gTable.className = gUI_showHidden.getElementsByTagName(\"input\")[0].checked ?\n"
+ " \"\" :\n"
+ " \"remove-hidden\";\n"
+ "}\n"
+ "</script>\n");
+
+ buffer.AppendLiteral("<link rel=\"icon\" type=\"image/png\" href=\"");
+ nsCOMPtr<nsIURI> innerUri = NS_GetInnermostURI(uri);
+ if (!innerUri)
+ return NS_ERROR_UNEXPECTED;
+ nsCOMPtr<nsIFileURL> fileURL(do_QueryInterface(innerUri));
+ //XXX bug 388553: can't use skinnable icons here due to security restrictions
+ if (fileURL) {
+ //buffer.AppendLiteral("chrome://global/skin/dirListing/local.png");
+ buffer.AppendLiteral("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB"
+ "AAAAAQCAYAAAAf8%2F9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
+ "ZSBJbWFnZVJlYWR5ccllPAAAAjFJREFUeNqsU8uOElEQPffR"
+ "3XQ3ONASdBJCSBxHos5%2B3Bg3rvkCv8PElS78gPkO%2FATj"
+ "QoUdO2ftrJiRh6aneTb9sOpC4weMN6lcuFV16pxDIfI8x12O"
+ "YIDhcPiu2Wx%2B%2FHF5CW1Z6Jyegt%2FTNEWSJIjjGFEUIQ"
+ "xDrFYrWFSzXC4%2FdLvd95pRKpXKy%2BpRFZ7nwaWo1%2BsG"
+ "nQG2260BKJfLKJVKGI1GEEJw7ateryd0v993W63WEwjgxfn5"
+ "obGYzgCbzcaEbdsIggDj8Riu6z6iUk9SYZMSx8W0LMsM%2FS"
+ "KK75xnJlIq80anQXdbEp0OhcPJ0eiaJnGRMEyyPDsAKKUM9c"
+ "lkYoDo3SZJzzSdp0VSKYmfV1co%2Bz580kw5KDIM8RbRfEnU"
+ "f1HzxtQyMAGcaGruTKczMzEIaqhKifV6jd%2BzGQQB5llunF"
+ "%2FM52BizC2K5sYPYvZcu653tjOM9O93wnYc08gmkgg4VAxi"
+ "xfqFUJT36AYBZGd6PJkFCZnnlBxMp38gqIgLpZB0y4Nph18l"
+ "yWh5FFbrOSxbl3V4G%2BVB7T4ajYYxTyuLtO%2BCvWGgJE1M"
+ "c7JNsJEhvgw%2FQV4fo%2F24nbEsX2u1d5sVyn8sJO0ZAQiI"
+ "YnFh%2BxrfLz%2Fj29cBS%2FO14zg3i8XigW3ZkErDtmKoeM"
+ "%2BAJGRMnXeEPGKf0nCD1ydvkDzU9Jbc6OpR7WIw6L8lQ%2B"
+ "4pQ1%2FlPF0RGM9Ns91Wmptk0GfB4EJkt77vXYj%2F8m%2B8"
+ "y%2FkrwABHbz2H9V68DQAAAABJRU5ErkJggg%3D%3D");
+ } else {
+ //buffer.AppendLiteral("chrome://global/skin/dirListing/remote.png");
+ buffer.AppendLiteral("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB"
+ "AAAAAQCAYAAAAf8%2F9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
+ "ZSBJbWFnZVJlYWR5ccllPAAAAeBJREFUeNqcU81O20AQ%2Ft"
+ "Z2AgQSYQRqL1UPVG2hAUQkxLEStz4DrXpLpD5Drz31Cajax%"
+ "2Bghhx6qHIJURBTxIwQRwopCBbZjHMcOTrzermPipsSt1Iw0"
+ "3p3ZmW%2B%2B2R0TxhgOD34wjCHZlQ0iDYz9yvEfhxMTCYhE"
+ "QDIZhkxKd2sqzX2TOD2vBQCQhpPefng1ZP2dVPlLLdpL8SEM"
+ "cxng%2Fbs0RIHhtgs4twxOh%2BHjZxvzDx%2F3GQQiDFISiR"
+ "BLFMPKTRMollzcWECrDVhtxtdRVsL9youPxGj%2FbdfFlUZh"
+ "tDyYbYqWRUdai1oQRZ5oHeHl2gNM%2B01Uqio8RlH%2Bnsaz"
+ "JzNwXcq1B%2BiXPHprlEEymeBfXs1w8XxxihfyuXqoHqpoGj"
+ "ZM04bddgG%2F9%2B8WGj87qDdsrK9m%2BoA%2BpbhQTDh2l1"
+ "%2Bi2weNbSHMZyjvNXmVbqh9Fj5Oz27uEoP%2BSTxANruJs9"
+ "L%2FT6P0ewqPx5nmiAG5f6AoCtN1PbJzuRyJAyDBzzSQYvEr"
+ "f06yYxhGXlEa8H2KVGoasjwLx3Ewk858opQWXm%2B%2Fib9E"
+ "QrBzclLLLy89xYvlpchvtixcX6uo1y%2FzsiwHrkIsgKbp%2"
+ "BYWFOWicuqppoNTnStHzPFCPQhBEBOyGAX4JMADFetubi4BS"
+ "YAAAAABJRU5ErkJggg%3D%3D");
+ }
+ buffer.AppendLiteral("\">\n<title>");
+
+ // Everything needs to end in a /,
+ // otherwise we end up linking to file:///foo/dirfile
+
+ if (!mTextToSubURI) {
+ mTextToSubURI = do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ nsXPIDLCString encoding;
+ rv = uri->GetOriginCharset(encoding);
+ if (NS_FAILED(rv)) return rv;
+ if (encoding.IsEmpty()) {
+ encoding.AssignLiteral("UTF-8");
+ }
+
+ nsXPIDLString unEscapeSpec;
+ rv = mTextToSubURI->UnEscapeAndConvert(encoding, titleUri.get(),
+ 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);
+ nsAutoCString 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;
+
+ nsXPIDLString htmlEscSpec;
+ htmlEscSpec.Adopt(nsEscapeHTML2(unEscapeSpec.get(),
+ unEscapeSpec.Length()));
+
+ nsXPIDLString title;
+ const char16_t* formatTitle[] = {
+ htmlEscSpec.get()
+ };
+
+ rv = mBundle->FormatStringFromName(u"DirTitle",
+ formatTitle,
+ sizeof(formatTitle)/sizeof(char16_t*),
+ getter_Copies(title));
+ if (NS_FAILED(rv)) return rv;
+
+ // we want to convert string bundle to NCR
+ // to ensure they're shown in any charsets
+ AppendNonAsciiToNCR(title, buffer);
+
+ buffer.AppendLiteral("</title>\n");
+
+ // If there is a quote character in the baseUri, then
+ // lets not add a base URL. The reason for this is that
+ // if we stick baseUri containing a quote into a quoted
+ // string, the quote character will prematurely close
+ // the base href string. This is a fall-back check;
+ // that's why it is OK to not use a base rather than
+ // trying to play nice and escaping the quotes. See bug
+ // 358128.
+
+ if (!baseUri.Contains('"'))
+ {
+ // Great, the baseUri does not contain a char that
+ // will prematurely close the string. Go ahead an
+ // add a base href, but only do so if we're not
+ // dealing with a resource URI.
+ nsCOMPtr<nsIURI> originalUri;
+ rv = channel->GetOriginalURI(getter_AddRefs(originalUri));
+ bool wasResource = false;
+ if (NS_FAILED(rv) ||
+ NS_FAILED(originalUri->SchemeIs("resource", &wasResource)) ||
+ !wasResource) {
+ buffer.AppendLiteral("<base href=\"");
+ nsAdoptingCString htmlEscapedUri(nsEscapeHTML(baseUri.get()));
+ buffer.Append(htmlEscapedUri);
+ buffer.AppendLiteral("\" />\n");
+ }
+ }
+ else
+ {
+ NS_ERROR("broken protocol handler didn't escape double-quote.");
+ }
+
+ nsCString direction(NS_LITERAL_CSTRING("ltr"));
+ nsCOMPtr<nsIXULChromeRegistry> reg =
+ mozilla::services::GetXULChromeRegistryService();
+ if (reg) {
+ bool isRTL = false;
+ reg->IsLocaleRTL(NS_LITERAL_CSTRING("global"), &isRTL);
+ if (isRTL) {
+ direction.AssignLiteral("rtl");
+ }
+ }
+
+ buffer.AppendLiteral("</head>\n<body dir=\"");
+ buffer.Append(direction);
+ buffer.AppendLiteral("\">\n<h1>");
+
+ const char16_t* formatHeading[] = {
+ htmlEscSpec.get()
+ };
+
+ rv = mBundle->FormatStringFromName(u"DirTitle",
+ formatHeading,
+ sizeof(formatHeading)/sizeof(char16_t*),
+ getter_Copies(title));
+ if (NS_FAILED(rv)) return rv;
+
+ AppendNonAsciiToNCR(title, buffer);
+ buffer.AppendLiteral("</h1>\n");
+
+ if (!parentStr.IsEmpty()) {
+ nsXPIDLString parentText;
+ rv = mBundle->GetStringFromName(u"DirGoUp",
+ getter_Copies(parentText));
+ if (NS_FAILED(rv)) return rv;
+
+ buffer.AppendLiteral("<p id=\"UI_goUp\"><a class=\"up\" href=\"");
+
+ nsAdoptingCString htmlParentStr(nsEscapeHTML(parentStr.get()));
+ buffer.Append(htmlParentStr);
+ buffer.AppendLiteral("\">");
+ AppendNonAsciiToNCR(parentText, buffer);
+ buffer.AppendLiteral("</a></p>\n");
+ }
+
+ if (isSchemeFile) {
+ nsXPIDLString showHiddenText;
+ rv = mBundle->GetStringFromName(u"ShowHidden",
+ getter_Copies(showHiddenText));
+ if (NS_FAILED(rv)) return rv;
+
+ buffer.AppendLiteral("<p id=\"UI_showHidden\" style=\"display:none\"><label><input type=\"checkbox\" checked onchange=\"updateHidden()\">");
+ AppendNonAsciiToNCR(showHiddenText, buffer);
+ buffer.AppendLiteral("</label></p>\n");
+ }
+
+ buffer.AppendLiteral("<table>\n");
+
+ nsXPIDLString columnText;
+
+ buffer.AppendLiteral(" <thead>\n"
+ " <tr>\n"
+ " <th>");
+
+ rv = mBundle->GetStringFromName(u"DirColName",
+ getter_Copies(columnText));
+ if (NS_FAILED(rv)) return rv;
+ AppendNonAsciiToNCR(columnText, buffer);
+ buffer.AppendLiteral("</th>\n"
+ " <th>");
+
+ rv = mBundle->GetStringFromName(u"DirColSize",
+ getter_Copies(columnText));
+ if (NS_FAILED(rv)) return rv;
+ AppendNonAsciiToNCR(columnText, buffer);
+ buffer.AppendLiteral("</th>\n"
+ " <th colspan=\"2\">");
+
+ rv = mBundle->GetStringFromName(u"DirColMTime",
+ getter_Copies(columnText));
+ if (NS_FAILED(rv)) return rv;
+ AppendNonAsciiToNCR(columnText, buffer);
+ buffer.AppendLiteral("</th>\n"
+ " </tr>\n"
+ " </thead>\n");
+ buffer.AppendLiteral(" <tbody>\n");
+
+ aBuffer = buffer;
+ return rv;
+}
+
+NS_IMETHODIMP
+nsIndexedToHTML::OnStopRequest(nsIRequest* request, nsISupports *aContext,
+ nsresult aStatus) {
+ if (NS_SUCCEEDED(aStatus)) {
+ nsCString buffer;
+ buffer.AssignLiteral("</tbody></table></body></html>\n");
+
+ aStatus = SendToListener(request, aContext, buffer);
+ }
+
+ mParser->OnStopRequest(request, aContext, aStatus);
+ mParser = nullptr;
+
+ return mListener->OnStopRequest(request, aContext, aStatus);
+}
+
+nsresult
+nsIndexedToHTML::SendToListener(nsIRequest* aRequest, nsISupports *aContext, const nsACString &aBuffer)
+{
+ nsCOMPtr<nsIInputStream> inputData;
+ nsresult rv = NS_NewCStringInputStream(getter_AddRefs(inputData), aBuffer);
+ NS_ENSURE_SUCCESS(rv, rv);
+ return mListener->OnDataAvailable(aRequest, aContext,
+ inputData, 0, aBuffer.Length());
+}
+
+NS_IMETHODIMP
+nsIndexedToHTML::OnDataAvailable(nsIRequest *aRequest,
+ nsISupports *aCtxt,
+ nsIInputStream* aInput,
+ uint64_t aOffset,
+ uint32_t aCount) {
+ return mParser->OnDataAvailable(aRequest, aCtxt, aInput, aOffset, aCount);
+}
+
+NS_IMETHODIMP
+nsIndexedToHTML::OnIndexAvailable(nsIRequest *aRequest,
+ nsISupports *aCtxt,
+ nsIDirIndex *aIndex) {
+ nsresult rv;
+ if (!aIndex)
+ return NS_ERROR_NULL_POINTER;
+
+ nsCString pushBuffer;
+ pushBuffer.AppendLiteral("<tr");
+
+ // We don't know the file's character set yet, so retrieve the raw bytes
+ // which will be decoded by the HTML parser.
+ nsXPIDLCString loc;
+ aIndex->GetLocation(getter_Copies(loc));
+
+ // Adjust the length in case unescaping shortened the string.
+ loc.Truncate(nsUnescapeCount(loc.BeginWriting()));
+
+ if (loc.IsEmpty()) {
+ return NS_ERROR_ILLEGAL_VALUE;
+ }
+ if (loc.First() == char16_t('.'))
+ pushBuffer.AppendLiteral(" class=\"hidden-object\"");
+
+ pushBuffer.AppendLiteral(">\n <td sortable-data=\"");
+
+ // The sort key is the name of the item, prepended by either 0, 1 or 2
+ // in order to group items.
+ uint32_t type;
+ aIndex->GetType(&type);
+ switch (type) {
+ case nsIDirIndex::TYPE_SYMLINK:
+ pushBuffer.Append('0');
+ break;
+ case nsIDirIndex::TYPE_DIRECTORY:
+ pushBuffer.Append('1');
+ break;
+ default:
+ pushBuffer.Append('2');
+ break;
+ }
+ nsAdoptingCString escaped(nsEscapeHTML(loc));
+ pushBuffer.Append(escaped);
+
+ pushBuffer.AppendLiteral("\"><table class=\"ellipsis\"><tbody><tr><td><a class=\"");
+ switch (type) {
+ case nsIDirIndex::TYPE_DIRECTORY:
+ pushBuffer.AppendLiteral("dir");
+ break;
+ case nsIDirIndex::TYPE_SYMLINK:
+ pushBuffer.AppendLiteral("symlink");
+ break;
+ default:
+ pushBuffer.AppendLiteral("file");
+ break;
+ }
+
+ pushBuffer.AppendLiteral("\" href=\"");
+
+ // need to escape links
+ nsAutoCString locEscaped;
+
+ // Adding trailing slash helps to recognize whether the URL points to a file
+ // or a directory (bug #214405).
+ if ((type == nsIDirIndex::TYPE_DIRECTORY) && (loc.Last() != '/')) {
+ loc.Append('/');
+ }
+
+ // now minimally re-escape the location...
+ uint32_t escFlags;
+ // for some protocols, we expect the location to be absolute.
+ // if so, and if the location indeed appears to be a valid URI, then go
+ // ahead and treat it like one.
+
+ nsAutoCString scheme;
+ if (mExpectAbsLoc &&
+ NS_SUCCEEDED(net_ExtractURLScheme(loc, scheme))) {
+ // escape as absolute
+ escFlags = esc_Forced | esc_AlwaysCopy | esc_Minimal;
+ }
+ else {
+ // escape as relative
+ // esc_Directory is needed because directories have a trailing slash.
+ // Without it, the trailing '/' will be escaped, and links from within
+ // that directory will be incorrect
+ escFlags = esc_Forced | esc_AlwaysCopy | esc_FileBaseName | esc_Colon | esc_Directory;
+ }
+ NS_EscapeURL(loc.get(), loc.Length(), escFlags, locEscaped);
+ // esc_Directory does not escape the semicolons, so if a filename
+ // contains semicolons we need to manually escape them.
+ // This replacement should be removed in bug #473280
+ locEscaped.ReplaceSubstring(";", "%3b");
+ nsAdoptingCString htmlEscapedURL(nsEscapeHTML(locEscaped.get()));
+ pushBuffer.Append(htmlEscapedURL);
+
+ pushBuffer.AppendLiteral("\">");
+
+ if (type == nsIDirIndex::TYPE_FILE || type == nsIDirIndex::TYPE_UNKNOWN) {
+ pushBuffer.AppendLiteral("<img src=\"moz-icon://");
+ int32_t lastDot = locEscaped.RFindChar('.');
+ if (lastDot != kNotFound) {
+ locEscaped.Cut(0, lastDot);
+ nsAdoptingCString htmlFileExt(nsEscapeHTML(locEscaped.get()));
+ pushBuffer.Append(htmlFileExt);
+ } else {
+ pushBuffer.AppendLiteral("unknown");
+ }
+ pushBuffer.AppendLiteral("?size=16\" alt=\"");
+
+ nsXPIDLString altText;
+ rv = mBundle->GetStringFromName(u"DirFileLabel",
+ getter_Copies(altText));
+ if (NS_FAILED(rv)) return rv;
+ AppendNonAsciiToNCR(altText, pushBuffer);
+ pushBuffer.AppendLiteral("\">");
+ }
+
+ pushBuffer.Append(escaped);
+ pushBuffer.AppendLiteral("</a></td></tr></tbody></table></td>\n <td");
+
+ if (type == nsIDirIndex::TYPE_DIRECTORY || type == nsIDirIndex::TYPE_SYMLINK) {
+ pushBuffer.Append('>');
+ } else {
+ int64_t size;
+ aIndex->GetSize(&size);
+
+ if (uint64_t(size) != UINT64_MAX) {
+ pushBuffer.AppendLiteral(" sortable-data=\"");
+ pushBuffer.AppendInt(size);
+ pushBuffer.AppendLiteral("\">");
+ nsAutoCString sizeString;
+ FormatSizeString(size, sizeString);
+ pushBuffer.Append(sizeString);
+ } else {
+ pushBuffer.Append('>');
+ }
+ }
+ pushBuffer.AppendLiteral("</td>\n <td");
+
+ PRTime t;
+ aIndex->GetLastModified(&t);
+
+ if (t == -1LL) {
+ pushBuffer.AppendLiteral("></td>\n <td>");
+ } else {
+ pushBuffer.AppendLiteral(" sortable-data=\"");
+ pushBuffer.AppendInt(static_cast<int64_t>(t));
+ pushBuffer.AppendLiteral("\">");
+ nsAutoString formatted;
+ mDateTime->FormatPRTime(nullptr,
+ kDateFormatShort,
+ kTimeFormatNone,
+ t,
+ formatted);
+ AppendNonAsciiToNCR(formatted, pushBuffer);
+ pushBuffer.AppendLiteral("</td>\n <td>");
+ mDateTime->FormatPRTime(nullptr,
+ kDateFormatNone,
+ kTimeFormatSeconds,
+ t,
+ formatted);
+ // use NCR to show date in any doc charset
+ AppendNonAsciiToNCR(formatted, pushBuffer);
+ }
+
+ pushBuffer.AppendLiteral("</td>\n</tr>");
+
+ return SendToListener(aRequest, aCtxt, pushBuffer);
+}
+
+NS_IMETHODIMP
+nsIndexedToHTML::OnInformationAvailable(nsIRequest *aRequest,
+ nsISupports *aCtxt,
+ const nsAString& aInfo) {
+ nsAutoCString pushBuffer;
+ nsAdoptingString escaped(nsEscapeHTML2(PromiseFlatString(aInfo).get()));
+ if (!escaped)
+ return NS_ERROR_OUT_OF_MEMORY;
+ pushBuffer.AppendLiteral("<tr>\n <td>");
+ // escaped is provided in Unicode, so write hex NCRs as necessary
+ // to prevent the HTML parser from applying a character set.
+ AppendNonAsciiToNCR(escaped, pushBuffer);
+ pushBuffer.AppendLiteral("</td>\n <td></td>\n <td></td>\n <td></td>\n</tr>\n");
+
+ return SendToListener(aRequest, aCtxt, pushBuffer);
+}
+
+void nsIndexedToHTML::FormatSizeString(int64_t inSize, nsCString& outSizeString)
+{
+ outSizeString.Truncate();
+ if (inSize > int64_t(0)) {
+ // round up to the nearest Kilobyte
+ int64_t upperSize = (inSize + int64_t(1023)) / int64_t(1024);
+ outSizeString.AppendInt(upperSize);
+ outSizeString.AppendLiteral(" KB");
+ }
+}
+
+nsIndexedToHTML::nsIndexedToHTML() {
+}
+
+nsIndexedToHTML::~nsIndexedToHTML() {
+}
diff --git a/netwerk/streamconv/converters/nsIndexedToHTML.h b/netwerk/streamconv/converters/nsIndexedToHTML.h
new file mode 100644
index 000000000..6f0fe9479
--- /dev/null
+++ b/netwerk/streamconv/converters/nsIndexedToHTML.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef ____nsindexedtohtml___h___
+#define ____nsindexedtohtml___h___
+
+#include "nsCOMPtr.h"
+#include "nsString.h"
+#include "nsIStreamConverter.h"
+#include "nsIDirIndexListener.h"
+
+#define NS_NSINDEXEDTOHTMLCONVERTER_CID \
+{ 0xcf0f71fd, 0xfafd, 0x4e2b, {0x9f, 0xdc, 0x13, 0x4d, 0x97, 0x2e, 0x16, 0xe2} }
+
+class nsIDateTimeFormat;
+class nsIStringBundle;
+class nsITextToSubURI;
+
+class nsIndexedToHTML : public nsIStreamConverter,
+ public nsIDirIndexListener
+{
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISTREAMCONVERTER
+ NS_DECL_NSIREQUESTOBSERVER
+ NS_DECL_NSISTREAMLISTENER
+ NS_DECL_NSIDIRINDEXLISTENER
+
+ nsIndexedToHTML();
+
+ nsresult Init(nsIStreamListener *aListener);
+
+ static nsresult
+ Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
+
+protected:
+
+ void FormatSizeString(int64_t inSize, nsCString& outSizeString);
+ nsresult SendToListener(nsIRequest* aRequest, nsISupports *aContext, const nsACString &aBuffer);
+ // Helper to properly implement OnStartRequest
+ nsresult DoOnStartRequest(nsIRequest* request, nsISupports *aContext,
+ nsCString& aBuffer);
+
+protected:
+ nsCOMPtr<nsIDirIndexParser> mParser;
+ nsCOMPtr<nsIStreamListener> mListener; // final listener (consumer)
+
+ nsCOMPtr<nsIDateTimeFormat> mDateTime;
+ nsCOMPtr<nsIStringBundle> mBundle;
+
+ nsCOMPtr<nsITextToSubURI> mTextToSubURI;
+
+private:
+ // Expecting absolute locations, given by 201 lines.
+ bool mExpectAbsLoc;
+
+ virtual ~nsIndexedToHTML();
+};
+
+#endif
+
diff --git a/netwerk/streamconv/converters/nsMultiMixedConv.cpp b/netwerk/streamconv/converters/nsMultiMixedConv.cpp
new file mode 100644
index 000000000..4ebd61d9c
--- /dev/null
+++ b/netwerk/streamconv/converters/nsMultiMixedConv.cpp
@@ -0,0 +1,1121 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsMultiMixedConv.h"
+#include "plstr.h"
+#include "nsIHttpChannel.h"
+#include "nsNetCID.h"
+#include "nsMimeTypes.h"
+#include "nsIStringStream.h"
+#include "nsCRT.h"
+#include "nsIHttpChannelInternal.h"
+#include "nsURLHelper.h"
+#include "nsIStreamConverterService.h"
+#include "nsICacheInfoChannel.h"
+#include <algorithm>
+#include "nsContentSecurityManager.h"
+#include "nsHttp.h"
+#include "nsNetUtil.h"
+#include "nsIURI.h"
+#include "nsHttpHeaderArray.h"
+
+//
+// Helper function for determining the length of data bytes up to
+// the next multipart token. A token is usually preceded by a LF
+// or CRLF delimiter.
+//
+static uint32_t
+LengthToToken(const char *cursor, const char *token)
+{
+ uint32_t len = token - cursor;
+ // Trim off any LF or CRLF preceding the token
+ if (len && *(token-1) == '\n') {
+ --len;
+ if (len && *(token-2) == '\r')
+ --len;
+ }
+ return len;
+}
+
+nsPartChannel::nsPartChannel(nsIChannel *aMultipartChannel, uint32_t aPartID,
+ nsIStreamListener* aListener) :
+ mMultipartChannel(aMultipartChannel),
+ mListener(aListener),
+ mStatus(NS_OK),
+ mContentLength(UINT64_MAX),
+ mIsByteRangeRequest(false),
+ mByteRangeStart(0),
+ mByteRangeEnd(0),
+ mPartID(aPartID),
+ mIsLastPart(false)
+{
+ // Inherit the load flags from the original channel...
+ mMultipartChannel->GetLoadFlags(&mLoadFlags);
+
+ mMultipartChannel->GetLoadGroup(getter_AddRefs(mLoadGroup));
+}
+
+nsPartChannel::~nsPartChannel()
+{
+}
+
+void nsPartChannel::InitializeByteRange(int64_t aStart, int64_t aEnd)
+{
+ mIsByteRangeRequest = true;
+
+ mByteRangeStart = aStart;
+ mByteRangeEnd = aEnd;
+}
+
+nsresult nsPartChannel::SendOnStartRequest(nsISupports* aContext)
+{
+ return mListener->OnStartRequest(this, aContext);
+}
+
+nsresult nsPartChannel::SendOnDataAvailable(nsISupports* aContext,
+ nsIInputStream* aStream,
+ uint64_t aOffset, uint32_t aLen)
+{
+ return mListener->OnDataAvailable(this, aContext, aStream, aOffset, aLen);
+}
+
+nsresult nsPartChannel::SendOnStopRequest(nsISupports* aContext,
+ nsresult aStatus)
+{
+ // Drop the listener
+ nsCOMPtr<nsIStreamListener> listener;
+ listener.swap(mListener);
+ return listener->OnStopRequest(this, aContext, aStatus);
+}
+
+void nsPartChannel::SetContentDisposition(const nsACString& aContentDispositionHeader)
+{
+ mContentDispositionHeader = aContentDispositionHeader;
+ nsCOMPtr<nsIURI> uri;
+ GetURI(getter_AddRefs(uri));
+ NS_GetFilenameFromDisposition(mContentDispositionFilename,
+ mContentDispositionHeader, uri);
+ mContentDisposition = NS_GetContentDispositionFromHeader(mContentDispositionHeader, this);
+}
+
+//
+// nsISupports implementation...
+//
+
+NS_IMPL_ADDREF(nsPartChannel)
+NS_IMPL_RELEASE(nsPartChannel)
+
+NS_INTERFACE_MAP_BEGIN(nsPartChannel)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIChannel)
+ NS_INTERFACE_MAP_ENTRY(nsIRequest)
+ NS_INTERFACE_MAP_ENTRY(nsIChannel)
+ NS_INTERFACE_MAP_ENTRY(nsIByteRangeRequest)
+ NS_INTERFACE_MAP_ENTRY(nsIMultiPartChannel)
+NS_INTERFACE_MAP_END
+
+//
+// nsIRequest implementation...
+//
+
+NS_IMETHODIMP
+nsPartChannel::GetName(nsACString &aResult)
+{
+ return mMultipartChannel->GetName(aResult);
+}
+
+NS_IMETHODIMP
+nsPartChannel::IsPending(bool *aResult)
+{
+ // For now, consider the active lifetime of each part the same as
+ // the underlying multipart channel... This is not exactly right,
+ // but it is good enough :-)
+ return mMultipartChannel->IsPending(aResult);
+}
+
+NS_IMETHODIMP
+nsPartChannel::GetStatus(nsresult *aResult)
+{
+ nsresult rv = NS_OK;
+
+ if (NS_FAILED(mStatus)) {
+ *aResult = mStatus;
+ } else {
+ rv = mMultipartChannel->GetStatus(aResult);
+ }
+
+ return rv;
+}
+
+NS_IMETHODIMP
+nsPartChannel::Cancel(nsresult aStatus)
+{
+ // Cancelling an individual part must not cancel the underlying
+ // multipart channel...
+ // XXX but we should stop sending data for _this_ part channel!
+ mStatus = aStatus;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPartChannel::Suspend(void)
+{
+ // Suspending an individual part must not suspend the underlying
+ // multipart channel...
+ // XXX why not?
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPartChannel::Resume(void)
+{
+ // Resuming an individual part must not resume the underlying
+ // multipart channel...
+ // XXX why not?
+ return NS_OK;
+}
+
+//
+// nsIChannel implementation
+//
+
+NS_IMETHODIMP
+nsPartChannel::GetOriginalURI(nsIURI * *aURI)
+{
+ return mMultipartChannel->GetOriginalURI(aURI);
+}
+
+NS_IMETHODIMP
+nsPartChannel::SetOriginalURI(nsIURI *aURI)
+{
+ return mMultipartChannel->SetOriginalURI(aURI);
+}
+
+NS_IMETHODIMP
+nsPartChannel::GetURI(nsIURI * *aURI)
+{
+ return mMultipartChannel->GetURI(aURI);
+}
+
+NS_IMETHODIMP
+nsPartChannel::Open(nsIInputStream **result)
+{
+ // This channel cannot be opened!
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsPartChannel::Open2(nsIInputStream** aStream)
+{
+ nsCOMPtr<nsIStreamListener> listener;
+ nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+ NS_ENSURE_SUCCESS(rv, rv);
+ return Open(aStream);
+}
+
+NS_IMETHODIMP
+nsPartChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
+{
+ // This channel cannot be opened!
+ return NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+nsPartChannel::AsyncOpen2(nsIStreamListener *aListener)
+{
+ nsCOMPtr<nsIStreamListener> listener = aListener;
+ nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
+ NS_ENSURE_SUCCESS(rv, rv);
+ return AsyncOpen(listener, nullptr);
+}
+
+NS_IMETHODIMP
+nsPartChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
+{
+ *aLoadFlags = mLoadFlags;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPartChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
+{
+ mLoadFlags = aLoadFlags;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPartChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
+{
+ *aLoadGroup = mLoadGroup;
+ NS_IF_ADDREF(*aLoadGroup);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPartChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
+{
+ mLoadGroup = aLoadGroup;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPartChannel::GetOwner(nsISupports* *aOwner)
+{
+ return mMultipartChannel->GetOwner(aOwner);
+}
+
+NS_IMETHODIMP
+nsPartChannel::SetOwner(nsISupports* aOwner)
+{
+ return mMultipartChannel->SetOwner(aOwner);
+}
+
+NS_IMETHODIMP
+nsPartChannel::GetLoadInfo(nsILoadInfo* *aLoadInfo)
+{
+ return mMultipartChannel->GetLoadInfo(aLoadInfo);
+}
+
+NS_IMETHODIMP
+nsPartChannel::SetLoadInfo(nsILoadInfo* aLoadInfo)
+{
+ return mMultipartChannel->SetLoadInfo(aLoadInfo);
+}
+
+NS_IMETHODIMP
+nsPartChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aCallbacks)
+{
+ return mMultipartChannel->GetNotificationCallbacks(aCallbacks);
+}
+
+NS_IMETHODIMP
+nsPartChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks)
+{
+ return mMultipartChannel->SetNotificationCallbacks(aCallbacks);
+}
+
+NS_IMETHODIMP
+nsPartChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
+{
+ return mMultipartChannel->GetSecurityInfo(aSecurityInfo);
+}
+
+NS_IMETHODIMP
+nsPartChannel::GetContentType(nsACString &aContentType)
+{
+ aContentType = mContentType;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPartChannel::SetContentType(const nsACString &aContentType)
+{
+ bool dummy;
+ net_ParseContentType(aContentType, mContentType, mContentCharset, &dummy);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPartChannel::GetContentCharset(nsACString &aContentCharset)
+{
+ aContentCharset = mContentCharset;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPartChannel::SetContentCharset(const nsACString &aContentCharset)
+{
+ mContentCharset = aContentCharset;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPartChannel::GetContentLength(int64_t *aContentLength)
+{
+ *aContentLength = mContentLength;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPartChannel::SetContentLength(int64_t aContentLength)
+{
+ mContentLength = aContentLength;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPartChannel::GetContentDisposition(uint32_t *aContentDisposition)
+{
+ if (mContentDispositionHeader.IsEmpty())
+ return NS_ERROR_NOT_AVAILABLE;
+
+ *aContentDisposition = mContentDisposition;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPartChannel::SetContentDisposition(uint32_t aContentDisposition)
+{
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+NS_IMETHODIMP
+nsPartChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename)
+{
+ if (mContentDispositionFilename.IsEmpty())
+ return NS_ERROR_NOT_AVAILABLE;
+
+ aContentDispositionFilename = mContentDispositionFilename;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPartChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename)
+{
+ return NS_ERROR_NOT_AVAILABLE;
+}
+
+
+NS_IMETHODIMP
+nsPartChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader)
+{
+ if (mContentDispositionHeader.IsEmpty())
+ return NS_ERROR_NOT_AVAILABLE;
+
+ aContentDispositionHeader = mContentDispositionHeader;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPartChannel::GetPartID(uint32_t *aPartID)
+{
+ *aPartID = mPartID;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPartChannel::GetIsLastPart(bool *aIsLastPart)
+{
+ *aIsLastPart = mIsLastPart;
+ return NS_OK;
+}
+
+//
+// nsIByteRangeRequest implementation...
+//
+
+NS_IMETHODIMP
+nsPartChannel::GetIsByteRangeRequest(bool *aIsByteRangeRequest)
+{
+ *aIsByteRangeRequest = mIsByteRangeRequest;
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsPartChannel::GetStartRange(int64_t *aStartRange)
+{
+ *aStartRange = mByteRangeStart;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPartChannel::GetEndRange(int64_t *aEndRange)
+{
+ *aEndRange = mByteRangeEnd;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPartChannel::GetBaseChannel(nsIChannel ** aReturn)
+{
+ NS_ENSURE_ARG_POINTER(aReturn);
+
+ *aReturn = mMultipartChannel;
+ NS_IF_ADDREF(*aReturn);
+ return NS_OK;
+}
+
+// nsISupports implementation
+NS_IMPL_ISUPPORTS(nsMultiMixedConv,
+ nsIStreamConverter,
+ nsIStreamListener,
+ nsIRequestObserver)
+
+
+// nsIStreamConverter implementation
+
+// No syncronous conversion at this time.
+NS_IMETHODIMP
+nsMultiMixedConv::Convert(nsIInputStream *aFromStream,
+ const char *aFromType,
+ const char *aToType,
+ nsISupports *aCtxt, nsIInputStream **_retval) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+// Stream converter service calls this to initialize the actual stream converter (us).
+NS_IMETHODIMP
+nsMultiMixedConv::AsyncConvertData(const char *aFromType, const char *aToType,
+ nsIStreamListener *aListener, nsISupports *aCtxt) {
+ NS_ASSERTION(aListener && aFromType && aToType, "null pointer passed into multi mixed converter");
+
+ // hook up our final listener. this guy gets the various On*() calls we want to throw
+ // at him.
+ //
+ // WARNING: this listener must be able to handle multiple OnStartRequest, OnDataAvail()
+ // and OnStopRequest() call combinations. We call of series of these for each sub-part
+ // in the raw stream.
+ mFinalListener = aListener;
+
+ return NS_OK;
+}
+
+// AutoFree implementation to prevent memory leaks
+class AutoFree
+{
+public:
+ AutoFree() : mBuffer(nullptr) {}
+
+ explicit AutoFree(char *buffer) : mBuffer(buffer) {}
+
+ ~AutoFree() {
+ free(mBuffer);
+ }
+
+ AutoFree& operator=(char *buffer) {
+ mBuffer = buffer;
+ return *this;
+ }
+
+ operator char*() const {
+ return mBuffer;
+ }
+private:
+ char *mBuffer;
+};
+
+// nsIStreamListener implementation
+NS_IMETHODIMP
+nsMultiMixedConv::OnDataAvailable(nsIRequest *request, nsISupports *context,
+ nsIInputStream *inStr, uint64_t sourceOffset,
+ uint32_t count) {
+ nsresult rv = NS_OK;
+ AutoFree buffer(nullptr);
+ uint32_t bufLen = 0, read = 0;
+
+ NS_ASSERTION(request, "multimixed converter needs a request");
+
+ nsCOMPtr<nsIChannel> channel = do_QueryInterface(request, &rv);
+ if (NS_FAILED(rv)) return rv;
+
+ // fill buffer
+ {
+ bufLen = count + mBufLen;
+ NS_ENSURE_TRUE((bufLen >= count) && (bufLen >= mBufLen),
+ NS_ERROR_FAILURE);
+ buffer = (char *) malloc(bufLen);
+ if (!buffer)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (mBufLen) {
+ // incorporate any buffered data into the parsing
+ memcpy(buffer, mBuffer, mBufLen);
+ free(mBuffer);
+ mBuffer = 0;
+ mBufLen = 0;
+ }
+
+ rv = inStr->Read(buffer + (bufLen - count), count, &read);
+
+ if (NS_FAILED(rv) || read == 0) return rv;
+ NS_ASSERTION(read == count, "poor data size assumption");
+ }
+
+ char *cursor = buffer;
+
+ if (mFirstOnData) {
+ // this is the first OnData() for this request. some servers
+ // don't bother sending a token in the first "part." This is
+ // illegal, but we'll handle the case anyway by shoving the
+ // boundary token in for the server.
+ mFirstOnData = false;
+ NS_ASSERTION(!mBufLen, "this is our first time through, we can't have buffered data");
+ const char * token = mToken.get();
+
+ PushOverLine(cursor, bufLen);
+
+ bool needMoreChars = bufLen < mTokenLen + 2;
+ nsAutoCString firstBuffer(buffer, bufLen);
+ int32_t posCR = firstBuffer.Find("\r");
+
+ if (needMoreChars || (posCR == kNotFound)) {
+ // we don't have enough data yet to make this comparison.
+ // skip this check, and try again the next time OnData()
+ // is called.
+ mFirstOnData = true;
+ } else if (!PL_strnstr(cursor, token, mTokenLen + 2)) {
+ char *newBuffer = (char *) realloc(buffer, bufLen + mTokenLen + 1);
+ if (!newBuffer)
+ return NS_ERROR_OUT_OF_MEMORY;
+ buffer = newBuffer;
+
+ memmove(buffer + mTokenLen + 1, buffer, bufLen);
+ memcpy(buffer, token, mTokenLen);
+ buffer[mTokenLen] = '\n';
+
+ bufLen += (mTokenLen + 1);
+
+ // need to reset cursor to the buffer again (bug 100595)
+ cursor = buffer;
+ }
+ }
+
+ char *token = nullptr;
+
+ if (mProcessingHeaders) {
+ // we were not able to process all the headers
+ // for this "part" given the previous buffer given to
+ // us in the previous OnDataAvailable callback.
+ bool done = false;
+ rv = ParseHeaders(channel, cursor, bufLen, &done);
+ if (NS_FAILED(rv)) return rv;
+
+ if (done) {
+ mProcessingHeaders = false;
+ rv = SendStart(channel);
+ if (NS_FAILED(rv)) return rv;
+ }
+ }
+
+ int32_t tokenLinefeed = 1;
+ while ( (token = FindToken(cursor, bufLen)) ) {
+
+ if (((token + mTokenLen + 1) < (cursor + bufLen)) &&
+ (*(token + mTokenLen + 1) == '-')) {
+ // This was the last delimiter so we can stop processing
+ rv = SendData(cursor, LengthToToken(cursor, token));
+ if (NS_FAILED(rv)) return rv;
+ if (mPartChannel) {
+ mPartChannel->SetIsLastPart();
+ }
+ return SendStop(NS_OK);
+ }
+
+ if (!mNewPart && token > cursor) {
+ // headers are processed, we're pushing data now.
+ NS_ASSERTION(!mProcessingHeaders, "we should be pushing raw data");
+ rv = SendData(cursor, LengthToToken(cursor, token));
+ bufLen -= token - cursor;
+ if (NS_FAILED(rv)) return rv;
+ }
+ // XXX else NS_ASSERTION(token == cursor, "?");
+ token += mTokenLen;
+ bufLen -= mTokenLen;
+ tokenLinefeed = PushOverLine(token, bufLen);
+
+ if (mNewPart) {
+ // parse headers
+ mNewPart = false;
+ cursor = token;
+ bool done = false;
+ rv = ParseHeaders(channel, cursor, bufLen, &done);
+ if (NS_FAILED(rv)) return rv;
+
+ if (done) {
+ rv = SendStart(channel);
+ if (NS_FAILED(rv)) return rv;
+ }
+ else {
+ // we haven't finished processing header info.
+ // we'll break out and try to process later.
+ mProcessingHeaders = true;
+ break;
+ }
+ }
+ else {
+ mNewPart = true;
+ // Reset state so we don't carry it over from part to part
+ mContentType.Truncate();
+ mContentLength = UINT64_MAX;
+ mContentDisposition.Truncate();
+ mIsByteRangeRequest = false;
+ mByteRangeStart = 0;
+ mByteRangeEnd = 0;
+
+ rv = SendStop(NS_OK);
+ if (NS_FAILED(rv)) return rv;
+ // reset the token to front. this allows us to treat
+ // the token as a starting token.
+ token -= mTokenLen + tokenLinefeed;
+ bufLen += mTokenLen + tokenLinefeed;
+ cursor = token;
+ }
+ }
+
+ // at this point, we want to buffer up whatever amount (bufLen)
+ // we have leftover. However, we *always* want to ensure that
+ // we buffer enough data to handle a broken token.
+
+ // carry over
+ uint32_t bufAmt = 0;
+ if (mProcessingHeaders)
+ bufAmt = bufLen;
+ else if (bufLen) {
+ // if the data ends in a linefeed, and we're in the middle
+ // of a "part" (ie. mPartChannel exists) don't bother
+ // buffering, go ahead and send the data we have. Otherwise
+ // if we don't have a channel already, then we don't even
+ // have enough info to start a part, go ahead and buffer
+ // enough to collect a boundary token.
+ if (!mPartChannel || !(cursor[bufLen-1] == nsCRT::LF) )
+ bufAmt = std::min(mTokenLen - 1, bufLen);
+ }
+
+ if (bufAmt) {
+ rv = BufferData(cursor + (bufLen - bufAmt), bufAmt);
+ if (NS_FAILED(rv)) return rv;
+ bufLen -= bufAmt;
+ }
+
+ if (bufLen) {
+ rv = SendData(cursor, bufLen);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ return rv;
+}
+
+
+// nsIRequestObserver implementation
+NS_IMETHODIMP
+nsMultiMixedConv::OnStartRequest(nsIRequest *request, nsISupports *ctxt) {
+ // we're assuming the content-type is available at this stage
+ NS_ASSERTION(mToken.IsEmpty(), "a second on start???");
+ const char *bndry = nullptr;
+ nsAutoCString delimiter;
+ nsresult rv = NS_OK;
+ mContext = ctxt;
+
+ mFirstOnData = true;
+ mTotalSent = 0;
+
+ nsCOMPtr<nsIChannel> channel = do_QueryInterface(request, &rv);
+ if (NS_FAILED(rv)) return rv;
+
+ // ask the HTTP channel for the content-type and extract the boundary from it.
+ nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel, &rv);
+ if (NS_SUCCEEDED(rv)) {
+ rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("content-type"), delimiter);
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ } else {
+ // try asking the channel directly
+ rv = channel->GetContentType(delimiter);
+ if (NS_FAILED(rv)) {
+ return NS_ERROR_FAILURE;
+ }
+ }
+
+ bndry = strstr(delimiter.BeginWriting(), "boundary");
+
+ if (!bndry) {
+ return NS_ERROR_FAILURE;
+ }
+
+ bndry = strchr(bndry, '=');
+ if (!bndry) return NS_ERROR_FAILURE;
+
+ bndry++; // move past the equals sign
+
+ char *attrib = (char *) strchr(bndry, ';');
+ if (attrib) *attrib = '\0';
+
+ nsAutoCString boundaryString(bndry);
+ if (attrib) *attrib = ';';
+
+ boundaryString.Trim(" \"");
+
+ mToken = boundaryString;
+ mTokenLen = boundaryString.Length();
+
+ if (mTokenLen == 0) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsMultiMixedConv::OnStopRequest(nsIRequest *request, nsISupports *ctxt,
+ nsresult aStatus)
+{
+ if (mToken.IsEmpty()) { // no token, no love.
+ return NS_ERROR_FAILURE;
+ }
+
+ if (mPartChannel) {
+ mPartChannel->SetIsLastPart();
+
+ // we've already called SendStart() (which sets up the mPartChannel,
+ // and fires an OnStart()) send any data left over, and then fire the stop.
+ if (mBufLen > 0 && mBuffer) {
+ (void) SendData(mBuffer, mBufLen);
+ // don't bother checking the return value here, if the send failed
+ // we're done anyway as we're in the OnStop() callback.
+ free(mBuffer);
+ mBuffer = nullptr;
+ mBufLen = 0;
+ }
+ (void) SendStop(aStatus);
+ } else if (NS_FAILED(aStatus)) {
+ // underlying data production problem. we should not be in
+ // the middle of sending data. if we were, mPartChannel,
+ // above, would have been true.
+
+ // if we send the start, the URI Loader's m_targetStreamListener, may
+ // be pointing at us causing a nice stack overflow. So, don't call
+ // OnStartRequest! - This breaks necko's semantecs.
+ //(void) mFinalListener->OnStartRequest(request, ctxt);
+
+ (void) mFinalListener->OnStopRequest(request, ctxt, aStatus);
+ }
+
+ return NS_OK;
+}
+
+
+// nsMultiMixedConv methods
+nsMultiMixedConv::nsMultiMixedConv() :
+ mCurrentPartID(0)
+{
+ mTokenLen = 0;
+ mNewPart = true;
+ mContentLength = UINT64_MAX;
+ mBuffer = nullptr;
+ mBufLen = 0;
+ mProcessingHeaders = false;
+ mByteRangeStart = 0;
+ mByteRangeEnd = 0;
+ mTotalSent = 0;
+ mIsByteRangeRequest = false;
+}
+
+nsMultiMixedConv::~nsMultiMixedConv() {
+ NS_ASSERTION(!mBuffer, "all buffered data should be gone");
+ if (mBuffer) {
+ free(mBuffer);
+ mBuffer = nullptr;
+ }
+}
+
+nsresult
+nsMultiMixedConv::BufferData(char *aData, uint32_t aLen) {
+ NS_ASSERTION(!mBuffer, "trying to over-write buffer");
+
+ char *buffer = (char *) malloc(aLen);
+ if (!buffer) return NS_ERROR_OUT_OF_MEMORY;
+
+ memcpy(buffer, aData, aLen);
+ mBuffer = buffer;
+ mBufLen = aLen;
+ return NS_OK;
+}
+
+
+nsresult
+nsMultiMixedConv::SendStart(nsIChannel *aChannel) {
+ nsresult rv = NS_OK;
+
+ nsCOMPtr<nsIStreamListener> partListener(mFinalListener);
+ if (mContentType.IsEmpty()) {
+ mContentType.AssignLiteral(UNKNOWN_CONTENT_TYPE);
+ nsCOMPtr<nsIStreamConverterService> serv =
+ do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID, &rv);
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr<nsIStreamListener> converter;
+ rv = serv->AsyncConvertData(UNKNOWN_CONTENT_TYPE,
+ "*/*",
+ mFinalListener,
+ mContext,
+ getter_AddRefs(converter));
+ if (NS_SUCCEEDED(rv)) {
+ partListener = converter;
+ }
+ }
+ }
+
+ // if we already have an mPartChannel, that means we never sent a Stop()
+ // before starting up another "part." that would be bad.
+ NS_ASSERTION(!mPartChannel, "tisk tisk, shouldn't be overwriting a channel");
+
+ nsPartChannel *newChannel;
+ newChannel = new nsPartChannel(aChannel, mCurrentPartID++, partListener);
+ if (!newChannel)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (mIsByteRangeRequest) {
+ newChannel->InitializeByteRange(mByteRangeStart, mByteRangeEnd);
+ }
+
+ mTotalSent = 0;
+
+ // Set up the new part channel...
+ mPartChannel = newChannel;
+
+ rv = mPartChannel->SetContentType(mContentType);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = mPartChannel->SetContentLength(mContentLength);
+ if (NS_FAILED(rv)) return rv;
+
+ mPartChannel->SetContentDisposition(mContentDisposition);
+
+ nsLoadFlags loadFlags = 0;
+ mPartChannel->GetLoadFlags(&loadFlags);
+ loadFlags |= nsIChannel::LOAD_REPLACE;
+ mPartChannel->SetLoadFlags(loadFlags);
+
+ nsCOMPtr<nsILoadGroup> loadGroup;
+ (void)mPartChannel->GetLoadGroup(getter_AddRefs(loadGroup));
+
+ // Add the new channel to the load group (if any)
+ if (loadGroup) {
+ rv = loadGroup->AddRequest(mPartChannel, nullptr);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ // Let's start off the load. NOTE: we don't forward on the channel passed
+ // into our OnDataAvailable() as it's the root channel for the raw stream.
+ return mPartChannel->SendOnStartRequest(mContext);
+}
+
+
+nsresult
+nsMultiMixedConv::SendStop(nsresult aStatus) {
+
+ nsresult rv = NS_OK;
+ if (mPartChannel) {
+ rv = mPartChannel->SendOnStopRequest(mContext, aStatus);
+ // don't check for failure here, we need to remove the channel from
+ // the loadgroup.
+
+ // Remove the channel from its load group (if any)
+ nsCOMPtr<nsILoadGroup> loadGroup;
+ (void) mPartChannel->GetLoadGroup(getter_AddRefs(loadGroup));
+ if (loadGroup)
+ (void) loadGroup->RemoveRequest(mPartChannel, mContext, aStatus);
+ }
+
+ mPartChannel = nullptr;
+ return rv;
+}
+
+nsresult
+nsMultiMixedConv::SendData(char *aBuffer, uint32_t aLen) {
+
+ nsresult rv = NS_OK;
+
+ if (!mPartChannel) return NS_ERROR_FAILURE; // something went wrong w/ processing
+
+ if (mContentLength != UINT64_MAX) {
+ // make sure that we don't send more than the mContentLength
+ // XXX why? perhaps the Content-Length header was actually wrong!!
+ if ((uint64_t(aLen) + mTotalSent) > mContentLength)
+ aLen = static_cast<uint32_t>(mContentLength - mTotalSent);
+
+ if (aLen == 0)
+ return NS_OK;
+ }
+
+ uint64_t offset = mTotalSent;
+ mTotalSent += aLen;
+
+ nsCOMPtr<nsIStringInputStream> ss(
+ do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv));
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = ss->ShareData(aBuffer, aLen);
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsCOMPtr<nsIInputStream> inStream(do_QueryInterface(ss, &rv));
+ if (NS_FAILED(rv)) return rv;
+
+ return mPartChannel->SendOnDataAvailable(mContext, inStream, offset, aLen);
+}
+
+int32_t
+nsMultiMixedConv::PushOverLine(char *&aPtr, uint32_t &aLen) {
+ int32_t chars = 0;
+ if ((aLen > 0) && (*aPtr == nsCRT::CR || *aPtr == nsCRT::LF)) {
+ if ((aLen > 1) && (aPtr[1] == nsCRT::LF))
+ chars++;
+ chars++;
+ aPtr += chars;
+ aLen -= chars;
+ }
+ return chars;
+}
+
+nsresult
+nsMultiMixedConv::ParseHeaders(nsIChannel *aChannel, char *&aPtr,
+ uint32_t &aLen, bool *_retval) {
+ // NOTE: this data must be ascii.
+ // NOTE: aPtr is NOT null terminated!
+ nsresult rv = NS_OK;
+ char *cursor = aPtr, *newLine = nullptr;
+ uint32_t cursorLen = aLen;
+ bool done = false;
+ uint32_t lineFeedIncrement = 1;
+
+ mContentLength = UINT64_MAX; // XXX what if we were already called?
+ while (cursorLen && (newLine = (char *) memchr(cursor, nsCRT::LF, cursorLen))) {
+ // adjust for linefeeds
+ if ((newLine > cursor) && (newLine[-1] == nsCRT::CR) ) { // CRLF
+ lineFeedIncrement = 2;
+ newLine--;
+ }
+ else
+ lineFeedIncrement = 1; // reset
+
+ if (newLine == cursor) {
+ // move the newLine beyond the linefeed marker
+ NS_ASSERTION(cursorLen >= lineFeedIncrement, "oops!");
+
+ cursor += lineFeedIncrement;
+ cursorLen -= lineFeedIncrement;
+
+ done = true;
+ break;
+ }
+
+ char tmpChar = *newLine;
+ *newLine = '\0'; // cursor is now null terminated
+
+ char *colon = (char *) strchr(cursor, ':');
+ if (colon) {
+ *colon = '\0';
+ nsAutoCString headerStr(cursor);
+ headerStr.CompressWhitespace();
+ *colon = ':';
+
+ nsAutoCString headerVal(colon + 1);
+ headerVal.CompressWhitespace();
+
+ // examine header
+ if (headerStr.LowerCaseEqualsLiteral("content-type")) {
+ mContentType = headerVal;
+ } else if (headerStr.LowerCaseEqualsLiteral("content-length")) {
+ mContentLength = nsCRT::atoll(headerVal.get());
+ } else if (headerStr.LowerCaseEqualsLiteral("content-disposition")) {
+ mContentDisposition = headerVal;
+ } else if (headerStr.LowerCaseEqualsLiteral("set-cookie")) {
+ nsCOMPtr<nsIHttpChannelInternal> httpInternal =
+ do_QueryInterface(aChannel);
+ if (httpInternal) {
+ httpInternal->SetCookie(headerVal.get());
+ }
+ } else if (headerStr.LowerCaseEqualsLiteral("content-range") ||
+ headerStr.LowerCaseEqualsLiteral("range") ) {
+ // something like: Content-range: bytes 7000-7999/8000
+ char* tmpPtr;
+
+ tmpPtr = (char *) strchr(colon + 1, '/');
+ if (tmpPtr)
+ *tmpPtr = '\0';
+
+ // pass the bytes-unit and the SP
+ char *range = (char *) strchr(colon + 2, ' ');
+ if (!range)
+ return NS_ERROR_FAILURE;
+
+ do {
+ range++;
+ } while (*range == ' ');
+
+ if (range[0] == '*'){
+ mByteRangeStart = mByteRangeEnd = 0;
+ }
+ else {
+ tmpPtr = (char *) strchr(range, '-');
+ if (!tmpPtr)
+ return NS_ERROR_FAILURE;
+
+ tmpPtr[0] = '\0';
+
+ mByteRangeStart = nsCRT::atoll(range);
+ tmpPtr++;
+ mByteRangeEnd = nsCRT::atoll(tmpPtr);
+ }
+
+ mIsByteRangeRequest = true;
+ if (mContentLength == UINT64_MAX)
+ mContentLength = uint64_t(mByteRangeEnd - mByteRangeStart + 1);
+ }
+ }
+ *newLine = tmpChar;
+ newLine += lineFeedIncrement;
+ cursorLen -= (newLine - cursor);
+ cursor = newLine;
+ }
+
+ aPtr = cursor;
+ aLen = cursorLen;
+
+ *_retval = done;
+ return rv;
+}
+
+char *
+nsMultiMixedConv::FindToken(char *aCursor, uint32_t aLen) {
+ // strnstr without looking for null termination
+ const char *token = mToken.get();
+ char *cur = aCursor;
+
+ if (!(token && aCursor && *token)) {
+ NS_WARNING("bad data");
+ return nullptr;
+ }
+
+ for (; aLen >= mTokenLen; aCursor++, aLen--) {
+ if (!memcmp(aCursor, token, mTokenLen) ) {
+ if ((aCursor - cur) >= 2) {
+ // back the cursor up over a double dash for backwards compat.
+ if ((*(aCursor-1) == '-') && (*(aCursor-2) == '-')) {
+ aCursor -= 2;
+ aLen += 2;
+
+ // we're playing w/ double dash tokens, adjust.
+ mToken.Assign(aCursor, mTokenLen + 2);
+ mTokenLen = mToken.Length();
+ }
+ }
+ return aCursor;
+ }
+ }
+
+ return nullptr;
+}
+
+nsresult
+NS_NewMultiMixedConv(nsMultiMixedConv** aMultiMixedConv)
+{
+ NS_PRECONDITION(aMultiMixedConv != nullptr, "null ptr");
+ if (! aMultiMixedConv)
+ return NS_ERROR_NULL_POINTER;
+
+ *aMultiMixedConv = new nsMultiMixedConv();
+ if (! *aMultiMixedConv)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(*aMultiMixedConv);
+ return NS_OK;
+}
diff --git a/netwerk/streamconv/converters/nsMultiMixedConv.h b/netwerk/streamconv/converters/nsMultiMixedConv.h
new file mode 100644
index 000000000..fa058b072
--- /dev/null
+++ b/netwerk/streamconv/converters/nsMultiMixedConv.h
@@ -0,0 +1,176 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef __nsmultimixedconv__h__
+#define __nsmultimixedconv__h__
+
+#include "nsIStreamConverter.h"
+#include "nsIChannel.h"
+#include "nsString.h"
+#include "nsCOMPtr.h"
+#include "nsIByteRangeRequest.h"
+#include "nsILoadInfo.h"
+#include "nsIMultiPartChannel.h"
+#include "nsAutoPtr.h"
+#include "mozilla/Attributes.h"
+#include "nsHttpResponseHead.h"
+
+#define NS_MULTIMIXEDCONVERTER_CID \
+{ /* 7584CE90-5B25-11d3-A175-0050041CAF44 */ \
+ 0x7584ce90, \
+ 0x5b25, \
+ 0x11d3, \
+ {0xa1, 0x75, 0x0, 0x50, 0x4, 0x1c, 0xaf, 0x44} \
+}
+
+//
+// nsPartChannel is a "dummy" channel which represents an individual part of
+// a multipart/mixed stream...
+//
+// Instances on this channel are passed out to the consumer through the
+// nsIStreamListener interface.
+//
+class nsPartChannel final : public nsIChannel,
+ public nsIByteRangeRequest,
+ public nsIMultiPartChannel
+{
+public:
+ nsPartChannel(nsIChannel *aMultipartChannel, uint32_t aPartID,
+ nsIStreamListener* aListener);
+
+ void InitializeByteRange(int64_t aStart, int64_t aEnd);
+ void SetIsLastPart() { mIsLastPart = true; }
+ nsresult SendOnStartRequest(nsISupports* aContext);
+ nsresult SendOnDataAvailable(nsISupports* aContext, nsIInputStream* aStream,
+ uint64_t aOffset, uint32_t aLen);
+ nsresult SendOnStopRequest(nsISupports* aContext, nsresult aStatus);
+ /* SetContentDisposition expects the full value of the Content-Disposition
+ * header */
+ void SetContentDisposition(const nsACString& aContentDispositionHeader);
+ void SetResponseHead(mozilla::net::nsHttpResponseHead * head) { mResponseHead = head; }
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIREQUEST
+ NS_DECL_NSICHANNEL
+ NS_DECL_NSIBYTERANGEREQUEST
+ NS_DECL_NSIMULTIPARTCHANNEL
+
+protected:
+ ~nsPartChannel();
+
+protected:
+ nsCOMPtr<nsIChannel> mMultipartChannel;
+ nsCOMPtr<nsIStreamListener> mListener;
+ nsAutoPtr<mozilla::net::nsHttpResponseHead> mResponseHead;
+
+ nsresult mStatus;
+ nsLoadFlags mLoadFlags;
+
+ nsCOMPtr<nsILoadGroup> mLoadGroup;
+
+ nsCString mContentType;
+ nsCString mContentCharset;
+ uint32_t mContentDisposition;
+ nsString mContentDispositionFilename;
+ nsCString mContentDispositionHeader;
+ uint64_t mContentLength;
+
+ bool mIsByteRangeRequest;
+ int64_t mByteRangeStart;
+ int64_t mByteRangeEnd;
+
+ uint32_t mPartID; // unique ID that can be used to identify
+ // this part of the multipart document
+ bool mIsLastPart;
+};
+
+// The nsMultiMixedConv stream converter converts a stream of type "multipart/x-mixed-replace"
+// to it's subparts. There was some debate as to whether or not the functionality desired
+// when HTTP confronted this type required a stream converter. After all, this type really
+// prompts various viewer related actions rather than stream conversion. There simply needs
+// to be a piece in place that can strip out the multiple parts of a stream of this type, and
+// "display" them accordingly.
+//
+// With that said, this "stream converter" spends more time packaging up the sub parts of the
+// main stream and sending them off the destination stream listener, than doing any real
+// stream parsing/converting.
+//
+// WARNING: This converter requires that it's destination stream listener be able to handle
+// multiple OnStartRequest(), OnDataAvailable(), and OnStopRequest() call combinations.
+// Each series represents the beginning, data production, and ending phase of each sub-
+// part of the original stream.
+//
+// NOTE: this MIME-type is used by HTTP, *not* SMTP, or IMAP.
+//
+// NOTE: For reference, a general description of how this MIME type should be handled via
+// HTTP, see http://home.netscape.com/assist/net_sites/pushpull.html . Note that
+// real world server content deviates considerably from this overview.
+//
+// Implementation assumptions:
+// Assumed structue:
+// --BoundaryToken[\r]\n
+// content-type: foo/bar[\r]\n
+// ... (other headers if any)
+// [\r]\n (second line feed to delimit end of headers)
+// data
+// --BoundaryToken-- (end delimited by final "--")
+//
+// linebreaks can be either CRLF or LFLF. linebreaks preceding
+// boundary tokens are considered part of the data. BoundaryToken
+// is any opaque string.
+//
+//
+
+class nsMultiMixedConv : public nsIStreamConverter {
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISTREAMCONVERTER
+ NS_DECL_NSISTREAMLISTENER
+ NS_DECL_NSIREQUESTOBSERVER
+
+ nsMultiMixedConv();
+
+protected:
+ virtual ~nsMultiMixedConv();
+
+ nsresult SendStart(nsIChannel *aChannel);
+ nsresult SendStop(nsresult aStatus);
+ nsresult SendData(char *aBuffer, uint32_t aLen);
+ nsresult ParseHeaders(nsIChannel *aChannel, char *&aPtr,
+ uint32_t &aLen, bool *_retval);
+ int32_t PushOverLine(char *&aPtr, uint32_t &aLen);
+ char *FindToken(char *aCursor, uint32_t aLen);
+ nsresult BufferData(char *aData, uint32_t aLen);
+
+ // member data
+ bool mNewPart; // Are we processing the beginning of a part?
+ bool mProcessingHeaders;
+ nsCOMPtr<nsIStreamListener> mFinalListener; // this guy gets the converted data via his OnDataAvailable()
+
+ nsCString mToken;
+ uint32_t mTokenLen;
+
+ RefPtr<nsPartChannel> mPartChannel; // the channel for the given part we're processing.
+ // one channel per part.
+ nsCOMPtr<nsISupports> mContext;
+ nsCString mContentType;
+ nsCString mContentDisposition;
+ uint64_t mContentLength;
+
+ char *mBuffer;
+ uint32_t mBufLen;
+ uint64_t mTotalSent;
+ bool mFirstOnData; // used to determine if we're in our first OnData callback.
+
+ // The following members are for tracking the byte ranges in
+ // multipart/mixed content which specified the 'Content-Range:'
+ // header...
+ int64_t mByteRangeStart;
+ int64_t mByteRangeEnd;
+ bool mIsByteRangeRequest;
+
+ uint32_t mCurrentPartID;
+};
+
+#endif /* __nsmultimixedconv__h__ */
diff --git a/netwerk/streamconv/converters/nsTXTToHTMLConv.cpp b/netwerk/streamconv/converters/nsTXTToHTMLConv.cpp
new file mode 100644
index 000000000..ded3e9e6c
--- /dev/null
+++ b/netwerk/streamconv/converters/nsTXTToHTMLConv.cpp
@@ -0,0 +1,314 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsTXTToHTMLConv.h"
+#include "nsEscape.h"
+#include "nsStringStream.h"
+#include "nsAutoPtr.h"
+#include "nsIChannel.h"
+#include <algorithm>
+
+#include "mozilla/UniquePtrExtensions.h"
+
+#define TOKEN_DELIMITERS u"\t\r\n "
+
+using namespace mozilla;
+
+// nsISupports methods
+NS_IMPL_ISUPPORTS(nsTXTToHTMLConv,
+ nsIStreamConverter,
+ nsITXTToHTMLConv,
+ nsIRequestObserver,
+ nsIStreamListener)
+
+
+// nsIStreamConverter methods
+NS_IMETHODIMP
+nsTXTToHTMLConv::Convert(nsIInputStream *aFromStream,
+ const char *aFromType, const char *aToType,
+ nsISupports *aCtxt, nsIInputStream * *_retval)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsTXTToHTMLConv::AsyncConvertData(const char *aFromType,
+ const char *aToType,
+ nsIStreamListener *aListener,
+ nsISupports *aCtxt)
+{
+ NS_ASSERTION(aListener, "null pointer");
+ mListener = aListener;
+ return NS_OK;
+}
+
+
+// nsIRequestObserver methods
+NS_IMETHODIMP
+nsTXTToHTMLConv::OnStartRequest(nsIRequest* request, nsISupports *aContext)
+{
+ mBuffer.AssignLiteral("<html>\n<head><title>");
+ mBuffer.Append(mPageTitle);
+ mBuffer.AppendLiteral("</title></head>\n<body>\n");
+ if (mPreFormatHTML) { // Use <pre> tags
+ mBuffer.AppendLiteral("<pre>\n");
+ }
+
+ // Push mBuffer to the listener now, so the initial HTML will not
+ // be parsed in OnDataAvailable().
+
+ nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
+ if (channel)
+ channel->SetContentType(NS_LITERAL_CSTRING("text/html"));
+ // else, assume there is a channel somewhere that knows what it is doing!
+
+ nsresult rv = mListener->OnStartRequest(request, aContext);
+ if (NS_FAILED(rv)) return rv;
+
+ // The request may have been canceled, and if that happens, we want to
+ // suppress calls to OnDataAvailable.
+ request->GetStatus(&rv);
+ if (NS_FAILED(rv)) return rv;
+
+ nsCOMPtr<nsIInputStream> inputData;
+ NS_LossyConvertUTF16toASCII asciiData(mBuffer);
+ rv = NS_NewCStringInputStream(getter_AddRefs(inputData), asciiData);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = mListener->OnDataAvailable(request, aContext,
+ inputData, 0, mBuffer.Length());
+ if (NS_FAILED(rv)) return rv;
+ mBuffer.Truncate();
+ return rv;
+}
+
+NS_IMETHODIMP
+nsTXTToHTMLConv::OnStopRequest(nsIRequest* request, nsISupports *aContext,
+ nsresult aStatus)
+{
+ nsresult rv = NS_OK;
+ if (mToken) {
+ // we still have an outstanding token
+ NS_ASSERTION(mToken->prepend,
+ "Non prepending tokens should be handled in "
+ "OnDataAvailable. There should only be a single "
+ "prepending token left to be processed.");
+ (void)CatHTML(0, mBuffer.Length());
+ }
+ if (mPreFormatHTML) {
+ mBuffer.AppendLiteral("</pre>\n");
+ }
+ mBuffer.AppendLiteral("\n</body></html>");
+
+ nsCOMPtr<nsIInputStream> inputData;
+ NS_LossyConvertUTF16toASCII asciiData(mBuffer);
+ rv = NS_NewCStringInputStream(getter_AddRefs(inputData), asciiData);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = mListener->OnDataAvailable(request, aContext,
+ inputData, 0, mBuffer.Length());
+ if (NS_FAILED(rv)) return rv;
+
+ return mListener->OnStopRequest(request, aContext, aStatus);
+}
+
+// nsITXTToHTMLConv methods
+NS_IMETHODIMP
+nsTXTToHTMLConv::SetTitle(const char16_t *aTitle)
+{
+ mPageTitle.Assign(aTitle);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsTXTToHTMLConv::PreFormatHTML(bool value)
+{
+ mPreFormatHTML = value;
+ return NS_OK;
+}
+
+// nsIStreamListener method
+NS_IMETHODIMP
+nsTXTToHTMLConv::OnDataAvailable(nsIRequest* request, nsISupports *aContext,
+ nsIInputStream *aInStream,
+ uint64_t aOffset, uint32_t aCount)
+{
+ nsresult rv = NS_OK;
+ nsString pushBuffer;
+ uint32_t amtRead = 0;
+ auto buffer = MakeUniqueFallible<char[]>(aCount+1);
+ if (!buffer) return NS_ERROR_OUT_OF_MEMORY;
+
+ do {
+ uint32_t read = 0;
+ // XXX readSegments, to avoid the first copy?
+ rv = aInStream->Read(buffer.get(), aCount-amtRead, &read);
+ if (NS_FAILED(rv)) return rv;
+
+ buffer[read] = '\0';
+ // XXX charsets?? non-latin1 characters?? utf-16??
+ AppendASCIItoUTF16(buffer.get(), mBuffer);
+ amtRead += read;
+
+ int32_t front = -1, back = -1, tokenLoc = -1, cursor = 0;
+
+ while ( (tokenLoc = FindToken(cursor, &mToken)) > -1) {
+ if (mToken->prepend) {
+ front = mBuffer.RFindCharInSet(TOKEN_DELIMITERS, tokenLoc);
+ front++;
+ back = mBuffer.FindCharInSet(TOKEN_DELIMITERS, tokenLoc);
+ } else {
+ front = tokenLoc;
+ back = front + mToken->token.Length();
+ }
+ if (back == -1) {
+ // didn't find an ending, buffer up.
+ mBuffer.Left(pushBuffer, front);
+ cursor = front;
+ break;
+ }
+ // found the end of the token.
+ cursor = CatHTML(front, back);
+ }
+
+ int32_t end = mBuffer.RFind(TOKEN_DELIMITERS, mBuffer.Length());
+ mBuffer.Left(pushBuffer, std::max(cursor, end));
+ mBuffer.Cut(0, std::max(cursor, end));
+ cursor = 0;
+
+ if (!pushBuffer.IsEmpty()) {
+ nsCOMPtr<nsIInputStream> inputData;
+ NS_LossyConvertUTF16toASCII asciiData(pushBuffer);
+ rv = NS_NewCStringInputStream(getter_AddRefs(inputData), asciiData);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = mListener->OnDataAvailable(request, aContext,
+ inputData, 0, pushBuffer.Length());
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ } while (amtRead < aCount);
+
+ return rv;
+}
+
+// nsTXTToHTMLConv methods
+nsTXTToHTMLConv::nsTXTToHTMLConv()
+{
+ mToken = nullptr;
+ mPreFormatHTML = false;
+}
+
+nsTXTToHTMLConv::~nsTXTToHTMLConv()
+{
+ mTokens.Clear();
+}
+
+nsresult
+nsTXTToHTMLConv::Init()
+{
+ nsresult rv = NS_OK;
+
+ // build up the list of tokens to handle
+ convToken *token = new convToken;
+ if (!token) return NS_ERROR_OUT_OF_MEMORY;
+ token->prepend = false;
+ token->token.Assign(char16_t('<'));
+ token->modText.AssignLiteral("&lt;");
+ mTokens.AppendElement(token);
+
+ token = new convToken;
+ if (!token) return NS_ERROR_OUT_OF_MEMORY;
+ token->prepend = false;
+ token->token.Assign(char16_t('>'));
+ token->modText.AssignLiteral("&gt;");
+ mTokens.AppendElement(token);
+
+ token = new convToken;
+ if (!token) return NS_ERROR_OUT_OF_MEMORY;
+ token->prepend = false;
+ token->token.Assign(char16_t('&'));
+ token->modText.AssignLiteral("&amp;");
+ mTokens.AppendElement(token);
+
+ token = new convToken;
+ if (!token) return NS_ERROR_OUT_OF_MEMORY;
+ token->prepend = true;
+ token->token.AssignLiteral("http://"); // XXX need to iterate through all protos
+ mTokens.AppendElement(token);
+
+ token = new convToken;
+ if (!token) return NS_ERROR_OUT_OF_MEMORY;
+ token->prepend = true;
+ token->token.Assign(char16_t('@'));
+ token->modText.AssignLiteral("mailto:");
+ mTokens.AppendElement(token);
+
+ return rv;
+}
+
+int32_t
+nsTXTToHTMLConv::FindToken(int32_t cursor, convToken* *_retval)
+{
+ int32_t loc = -1, firstToken = mBuffer.Length();
+ int8_t token = -1;
+ for (uint8_t i=0; i < mTokens.Length(); i++) {
+ loc = mBuffer.Find(mTokens[i]->token, cursor);
+ if (loc != -1)
+ if (loc < firstToken) {
+ firstToken = loc;
+ token = i;
+ }
+ }
+ if (token == -1)
+ return -1;
+
+ *_retval = mTokens[token];
+ return firstToken;
+}
+
+int32_t
+nsTXTToHTMLConv::CatHTML(int32_t front, int32_t back)
+{
+ int32_t cursor = 0;
+ int32_t modLen = mToken->modText.Length();
+ if (!mToken->prepend) {
+ // replace the entire token (from delimiter to delimiter)
+ mBuffer.Cut(front, back - front);
+ mBuffer.Insert(mToken->modText, front);
+ cursor = front+modLen;
+ } else {
+ nsString linkText;
+ // href is implied
+ mBuffer.Mid(linkText, front, back-front);
+
+ mBuffer.Insert(NS_LITERAL_STRING("<a href=\""), front);
+ cursor += front+9;
+ if (modLen) {
+ mBuffer.Insert(mToken->modText, cursor);
+ cursor += modLen;
+ }
+
+ NS_ConvertUTF16toUTF8 linkTextUTF8(linkText);
+ nsCString escaped;
+ if (NS_EscapeURL(linkTextUTF8.Data(), linkTextUTF8.Length(), esc_Minimal, escaped)) {
+ mBuffer.Cut(cursor, back - front);
+ CopyUTF8toUTF16(escaped, linkText);
+ mBuffer.Insert(linkText, cursor);
+ back = front + linkText.Length();
+ }
+
+ cursor += back-front;
+ mBuffer.Insert(NS_LITERAL_STRING("\">"), cursor);
+ cursor += 2;
+ mBuffer.Insert(linkText, cursor);
+ cursor += linkText.Length();
+ mBuffer.Insert(NS_LITERAL_STRING("</a>"), cursor);
+ cursor += 4;
+ }
+ mToken = nullptr; // indicates completeness
+ return cursor;
+}
diff --git a/netwerk/streamconv/converters/nsTXTToHTMLConv.h b/netwerk/streamconv/converters/nsTXTToHTMLConv.h
new file mode 100644
index 000000000..30ca811a1
--- /dev/null
+++ b/netwerk/streamconv/converters/nsTXTToHTMLConv.h
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef ____nstxttohtmlconv___h___
+#define ____nstxttohtmlconv___h___
+
+#include "nsITXTToHTMLConv.h"
+#include "nsCOMPtr.h"
+#include "nsTArray.h"
+#include "nsString.h"
+
+#define NS_NSTXTTOHTMLCONVERTER_CID \
+{ /* 9ef9fa14-1dd1-11b2-9d65-d72d6d1f025e */ \
+ 0x9ef9fa14, \
+ 0x1dd1, \
+ 0x11b2, \
+ {0x9d, 0x65, 0xd7, 0x2d, 0x6d, 0x1f, 0x02, 0x5e} \
+}
+
+// Internal representation of a "token"
+typedef struct convToken {
+ nsString token; // the actual string (i.e. "http://")
+ nsString modText; // replacement text or href prepend text.
+ bool prepend; // flag indicating how the modText should be used.
+} convToken;
+
+template<class T> class nsAutoPtr;
+
+/**
+ * Convert plain text to HTML.
+ *
+ * OVERVIEW OF HOW THIS CLASS WORKS:
+ *
+ * This class stores an array of tokens that should be replaced by something,
+ * or something that should be prepended.
+ * The "token" member of convToken is the text to search for. This is a
+ * substring of the desired token. Tokens are delimited by TOKEN_DELIMITERS.
+ * That entire token will be replaced by modText (if prepend is false); or it
+ * will be linkified and modText will be prepended to the token if prepend is
+ * true.
+ *
+ * Note that all of the text will be in a preformatted block, so there is no
+ * need to emit line-end tags, or set the font face to monospace.
+ *
+ * This works as a stream converter, so data will arrive by
+ * OnStartRequest/OnDataAvailable/OnStopRequest calls.
+ *
+ * OStopR will possibly process a remaining token.
+ *
+ * If the data of one pass contains a part of a token, that part will be stored
+ * in mBuffer. The rest of the data will be sent to the next listener.
+ *
+ * XXX this seems suboptimal. this means that this design will only work for
+ * links. and it is impossible to append anything to the token. this means that,
+ * for example, making *foo* bold is not possible.
+ */
+class nsTXTToHTMLConv : public nsITXTToHTMLConv {
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSISTREAMCONVERTER
+ NS_DECL_NSITXTTOHTMLCONV
+ NS_DECL_NSIREQUESTOBSERVER
+ NS_DECL_NSISTREAMLISTENER
+
+ nsTXTToHTMLConv();
+ nsresult Init();
+
+protected:
+ virtual ~nsTXTToHTMLConv();
+
+ // return the token and it's location in the underlying buffer.
+ int32_t FindToken(int32_t cursor, convToken* *_retval);
+
+ // return the cursor location after munging HTML into the
+ // underlying buffer, according to mToken
+ int32_t CatHTML(int32_t front, int32_t back);
+
+ nsCOMPtr<nsIStreamListener> mListener; // final listener (consumer)
+ nsString mBuffer; // any carry over data
+ nsTArray<nsAutoPtr<convToken> > mTokens; // list of tokens to search for
+ convToken *mToken; // current token (if any)
+ nsString mPageTitle; // Page title
+ bool mPreFormatHTML; // Whether to use <pre> tags
+};
+
+#endif // ____nstxttohtmlconv___h___
+
diff --git a/netwerk/streamconv/converters/nsUnknownDecoder.cpp b/netwerk/streamconv/converters/nsUnknownDecoder.cpp
new file mode 100644
index 000000000..6382a9cb6
--- /dev/null
+++ b/netwerk/streamconv/converters/nsUnknownDecoder.cpp
@@ -0,0 +1,836 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsUnknownDecoder.h"
+#include "nsIPipe.h"
+#include "nsIInputStream.h"
+#include "nsIOutputStream.h"
+#include "nsMimeTypes.h"
+#include "nsIPrefService.h"
+#include "nsIPrefBranch.h"
+
+#include "nsCRT.h"
+
+#include "nsIMIMEService.h"
+
+#include "nsIDivertableChannel.h"
+#include "nsIViewSourceChannel.h"
+#include "nsIHttpChannel.h"
+#include "nsIForcePendingChannel.h"
+#include "nsIEncodedChannel.h"
+#include "nsIURI.h"
+#include "nsStringStream.h"
+#include "nsNetCID.h"
+#include "nsNetUtil.h"
+
+#include <algorithm>
+
+#define MAX_BUFFER_SIZE 512u
+
+NS_IMPL_ISUPPORTS(nsUnknownDecoder::ConvertedStreamListener,
+ nsIStreamListener,
+ nsIRequestObserver)
+
+nsUnknownDecoder::ConvertedStreamListener::
+ ConvertedStreamListener(nsUnknownDecoder *aDecoder)
+{
+ mDecoder = aDecoder;
+}
+
+nsUnknownDecoder::ConvertedStreamListener::~ConvertedStreamListener()
+{
+}
+
+nsresult
+nsUnknownDecoder::ConvertedStreamListener::
+ AppendDataToString(nsIInputStream* inputStream,
+ void* closure,
+ const char* rawSegment,
+ uint32_t toOffset,
+ uint32_t count,
+ uint32_t* writeCount)
+{
+ nsCString* decodedData = static_cast<nsCString*>(closure);
+ decodedData->Append(rawSegment, count);
+ *writeCount = count;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsUnknownDecoder::ConvertedStreamListener::OnStartRequest(nsIRequest* request,
+ nsISupports* context)
+{
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsUnknownDecoder::ConvertedStreamListener::
+ OnDataAvailable(nsIRequest* request,
+ nsISupports* context,
+ nsIInputStream* stream,
+ uint64_t offset,
+ uint32_t count)
+{
+ uint32_t read;
+ return stream->ReadSegments(AppendDataToString, &mDecoder->mDecodedData, count,
+ &read);
+}
+
+NS_IMETHODIMP
+nsUnknownDecoder::ConvertedStreamListener::OnStopRequest(nsIRequest* request,
+ nsISupports* context,
+ nsresult status)
+{
+ return NS_OK;
+}
+
+nsUnknownDecoder::nsUnknownDecoder()
+ : mBuffer(nullptr)
+ , mBufferLen(0)
+ , mRequireHTMLsuffix(false)
+ , mDecodedData("")
+{
+ nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
+ if (prefs) {
+ bool val;
+ if (NS_SUCCEEDED(prefs->GetBoolPref("security.requireHTMLsuffix", &val)))
+ mRequireHTMLsuffix = val;
+ }
+}
+
+nsUnknownDecoder::~nsUnknownDecoder()
+{
+ if (mBuffer) {
+ delete [] mBuffer;
+ mBuffer = nullptr;
+ }
+}
+
+// ----
+//
+// nsISupports implementation...
+//
+// ----
+
+NS_IMPL_ADDREF(nsUnknownDecoder)
+NS_IMPL_RELEASE(nsUnknownDecoder)
+
+NS_INTERFACE_MAP_BEGIN(nsUnknownDecoder)
+ NS_INTERFACE_MAP_ENTRY(nsIStreamConverter)
+ NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
+ NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
+ NS_INTERFACE_MAP_ENTRY(nsIContentSniffer)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStreamListener)
+NS_INTERFACE_MAP_END
+
+
+// ----
+//
+// nsIStreamConverter methods...
+//
+// ----
+
+NS_IMETHODIMP
+nsUnknownDecoder::Convert(nsIInputStream *aFromStream,
+ const char *aFromType,
+ const char *aToType,
+ nsISupports *aCtxt,
+ nsIInputStream **aResultStream)
+{
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsUnknownDecoder::AsyncConvertData(const char *aFromType,
+ const char *aToType,
+ nsIStreamListener *aListener,
+ nsISupports *aCtxt)
+{
+ NS_ASSERTION(aListener && aFromType && aToType,
+ "null pointer passed into multi mixed converter");
+ // hook up our final listener. this guy gets the various On*() calls we want to throw
+ // at him.
+ //
+ mNextListener = aListener;
+ return (aListener) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+// ----
+//
+// nsIStreamListener methods...
+//
+// ----
+
+NS_IMETHODIMP
+nsUnknownDecoder::OnDataAvailable(nsIRequest* request,
+ nsISupports *aCtxt,
+ nsIInputStream *aStream,
+ uint64_t aSourceOffset,
+ uint32_t aCount)
+{
+ nsresult rv = NS_OK;
+
+ if (!mNextListener) return NS_ERROR_FAILURE;
+
+ if (mContentType.IsEmpty()) {
+ uint32_t count, len;
+
+ // If the buffer has not been allocated by now, just fail...
+ if (!mBuffer) return NS_ERROR_OUT_OF_MEMORY;
+
+ //
+ // Determine how much of the stream should be read to fill up the
+ // sniffer buffer...
+ //
+ if (mBufferLen + aCount >= MAX_BUFFER_SIZE) {
+ count = MAX_BUFFER_SIZE-mBufferLen;
+ } else {
+ count = aCount;
+ }
+
+ // Read the data into the buffer...
+ rv = aStream->Read((mBuffer+mBufferLen), count, &len);
+ if (NS_FAILED(rv)) return rv;
+
+ mBufferLen += len;
+ aCount -= len;
+
+ if (aCount) {
+ //
+ // Adjust the source offset... The call to FireListenerNotifications(...)
+ // will make the first OnDataAvailable(...) call with an offset of 0.
+ // So, this offset needs to be adjusted to reflect that...
+ //
+ aSourceOffset += mBufferLen;
+
+ DetermineContentType(request);
+
+ rv = FireListenerNotifications(request, aCtxt);
+ }
+ }
+
+ // Must not fire ODA again if it failed once
+ if (aCount && NS_SUCCEEDED(rv)) {
+ NS_ASSERTION(!mContentType.IsEmpty(),
+ "Content type should be known by now.");
+
+ nsCOMPtr<nsIDivertableChannel> divertable = do_QueryInterface(request);
+ if (divertable) {
+ bool diverting;
+ divertable->GetDivertingToParent(&diverting);
+ if (diverting) {
+ // The channel is diverted to the parent do not send any more data here.
+ return rv;
+ }
+ }
+ rv = mNextListener->OnDataAvailable(request, aCtxt, aStream,
+ aSourceOffset, aCount);
+ }
+
+ return rv;
+}
+
+// ----
+//
+// nsIRequestObserver methods...
+//
+// ----
+
+NS_IMETHODIMP
+nsUnknownDecoder::OnStartRequest(nsIRequest* request, nsISupports *aCtxt)
+{
+ nsresult rv = NS_OK;
+
+ if (!mNextListener) return NS_ERROR_FAILURE;
+
+ // Allocate the sniffer buffer...
+ if (NS_SUCCEEDED(rv) && !mBuffer) {
+ mBuffer = new char[MAX_BUFFER_SIZE];
+
+ if (!mBuffer) {
+ rv = NS_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ nsCOMPtr<nsIDivertableChannel> divertable = do_QueryInterface(request);
+ if (divertable) {
+ divertable->UnknownDecoderInvolvedKeepData();
+ }
+
+ // Do not pass the OnStartRequest on to the next listener (yet)...
+ return rv;
+}
+
+NS_IMETHODIMP
+nsUnknownDecoder::OnStopRequest(nsIRequest* request, nsISupports *aCtxt,
+ nsresult aStatus)
+{
+ nsresult rv = NS_OK;
+
+ if (!mNextListener) return NS_ERROR_FAILURE;
+
+ //
+ // The total amount of data is less than the size of the sniffer buffer.
+ // Analyze the buffer now...
+ //
+ if (mContentType.IsEmpty()) {
+ DetermineContentType(request);
+
+ // Make sure channel listeners see channel as pending while we call
+ // OnStartRequest/OnDataAvailable, even though the underlying channel
+ // has already hit OnStopRequest.
+ nsCOMPtr<nsIForcePendingChannel> forcePendingChannel = do_QueryInterface(request);
+ if (forcePendingChannel) {
+ forcePendingChannel->ForcePending(true);
+ }
+
+ rv = FireListenerNotifications(request, aCtxt);
+
+ if (NS_FAILED(rv)) {
+ aStatus = rv;
+ }
+
+ // now we need to set pending state to false before calling OnStopRequest
+ if (forcePendingChannel) {
+ forcePendingChannel->ForcePending(false);
+ }
+ }
+
+ rv = mNextListener->OnStopRequest(request, aCtxt, aStatus);
+ mNextListener = nullptr;
+
+ return rv;
+}
+
+// ----
+//
+// nsIContentSniffer methods...
+//
+// ----
+NS_IMETHODIMP
+nsUnknownDecoder::GetMIMETypeFromContent(nsIRequest* aRequest,
+ const uint8_t* aData,
+ uint32_t aLength,
+ nsACString& type)
+{
+ mBuffer = const_cast<char*>(reinterpret_cast<const char*>(aData));
+ mBufferLen = aLength;
+ DetermineContentType(aRequest);
+ mBuffer = nullptr;
+ mBufferLen = 0;
+ type.Assign(mContentType);
+ mContentType.Truncate();
+ return type.IsEmpty() ? NS_ERROR_NOT_AVAILABLE : NS_OK;
+}
+
+
+// Actual sniffing code
+
+bool nsUnknownDecoder::AllowSniffing(nsIRequest* aRequest)
+{
+ if (!mRequireHTMLsuffix) {
+ return true;
+ }
+
+ nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
+ if (!channel) {
+ NS_ERROR("QI failed");
+ return false;
+ }
+
+ nsCOMPtr<nsIURI> uri;
+ if (NS_FAILED(channel->GetURI(getter_AddRefs(uri))) || !uri) {
+ return false;
+ }
+
+ bool isLocalFile = false;
+ if (NS_FAILED(uri->SchemeIs("file", &isLocalFile)) || isLocalFile) {
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * This is the array of sniffer entries that depend on "magic numbers"
+ * in the file. Each entry has either a type associated with it (set
+ * these with the SNIFFER_ENTRY macro) or a function to be executed
+ * (set these with the SNIFFER_ENTRY_WITH_FUNC macro). The function
+ * should take a single nsIRequest* and returns bool -- true if
+ * it sets mContentType, false otherwise
+ */
+nsUnknownDecoder::nsSnifferEntry nsUnknownDecoder::sSnifferEntries[] = {
+ SNIFFER_ENTRY("%PDF-", APPLICATION_PDF),
+
+ SNIFFER_ENTRY("%!PS-Adobe-", APPLICATION_POSTSCRIPT),
+
+ // Files that start with mailbox delimiters let's provisionally call
+ // text/plain
+ SNIFFER_ENTRY("From", TEXT_PLAIN),
+ SNIFFER_ENTRY(">From", TEXT_PLAIN),
+
+ // If the buffer begins with "#!" or "%!" then it is a script of
+ // some sort... "Scripts" can include arbitrary data to be passed
+ // to an interpreter, so we need to decide whether we can call this
+ // text or whether it's data.
+ SNIFFER_ENTRY_WITH_FUNC("#!", &nsUnknownDecoder::LastDitchSniff),
+
+ // XXXbz should (and can) we also include the various ways that <?xml can
+ // appear as UTF-16 and such? See http://www.w3.org/TR/REC-xml#sec-guessing
+ SNIFFER_ENTRY_WITH_FUNC("<?xml", &nsUnknownDecoder::SniffForXML)
+};
+
+uint32_t nsUnknownDecoder::sSnifferEntryNum =
+ sizeof(nsUnknownDecoder::sSnifferEntries) /
+ sizeof(nsUnknownDecoder::nsSnifferEntry);
+
+void nsUnknownDecoder::DetermineContentType(nsIRequest* aRequest)
+{
+ NS_ASSERTION(mContentType.IsEmpty(), "Content type is already known.");
+ if (!mContentType.IsEmpty()) return;
+
+ const char* testData = mBuffer;
+ uint32_t testDataLen = mBufferLen;
+ // Check if data are compressed.
+ nsCOMPtr<nsIHttpChannel> channel(do_QueryInterface(aRequest));
+ if (channel) {
+ nsresult rv = ConvertEncodedData(aRequest, mBuffer, mBufferLen);
+ if (NS_SUCCEEDED(rv)) {
+ if (!mDecodedData.IsEmpty()) {
+ testData = mDecodedData.get();
+ testDataLen = std::min(mDecodedData.Length(), MAX_BUFFER_SIZE);
+ }
+ }
+ }
+
+ // First, run through all the types we can detect reliably based on
+ // magic numbers
+ uint32_t i;
+ for (i = 0; i < sSnifferEntryNum; ++i) {
+ if (testDataLen >= sSnifferEntries[i].mByteLen && // enough data
+ memcmp(testData, sSnifferEntries[i].mBytes, sSnifferEntries[i].mByteLen) == 0) { // and type matches
+ NS_ASSERTION(sSnifferEntries[i].mMimeType ||
+ sSnifferEntries[i].mContentTypeSniffer,
+ "Must have either a type string or a function to set the type");
+ NS_ASSERTION(!sSnifferEntries[i].mMimeType ||
+ !sSnifferEntries[i].mContentTypeSniffer,
+ "Both a type string and a type sniffing function set;"
+ " using type string");
+ if (sSnifferEntries[i].mMimeType) {
+ mContentType = sSnifferEntries[i].mMimeType;
+ NS_ASSERTION(!mContentType.IsEmpty(),
+ "Content type should be known by now.");
+ return;
+ }
+ if ((this->*(sSnifferEntries[i].mContentTypeSniffer))(aRequest)) {
+ NS_ASSERTION(!mContentType.IsEmpty(),
+ "Content type should be known by now.");
+ return;
+ }
+ }
+ }
+
+ NS_SniffContent(NS_DATA_SNIFFER_CATEGORY, aRequest,
+ (const uint8_t*)testData, testDataLen, mContentType);
+ if (!mContentType.IsEmpty()) {
+ return;
+ }
+
+ if (SniffForHTML(aRequest)) {
+ NS_ASSERTION(!mContentType.IsEmpty(),
+ "Content type should be known by now.");
+ return;
+ }
+
+ // We don't know what this is yet. Before we just give up, try
+ // the URI from the request.
+ if (SniffURI(aRequest)) {
+ NS_ASSERTION(!mContentType.IsEmpty(),
+ "Content type should be known by now.");
+ return;
+ }
+
+ LastDitchSniff(aRequest);
+ NS_ASSERTION(!mContentType.IsEmpty(),
+ "Content type should be known by now.");
+}
+
+bool nsUnknownDecoder::SniffForHTML(nsIRequest* aRequest)
+{
+ /*
+ * To prevent a possible attack, we will not consider this to be
+ * html content if it comes from the local file system and our prefs
+ * are set right
+ */
+ if (!AllowSniffing(aRequest)) {
+ return false;
+ }
+
+ // Now look for HTML.
+ const char* str;
+ const char* end;
+ if (mDecodedData.IsEmpty()) {
+ str = mBuffer;
+ end = mBuffer + mBufferLen;
+ } else {
+ str = mDecodedData.get();
+ end = mDecodedData.get() + std::min(mDecodedData.Length(),
+ MAX_BUFFER_SIZE);
+ }
+
+ // skip leading whitespace
+ while (str != end && nsCRT::IsAsciiSpace(*str)) {
+ ++str;
+ }
+
+ // did we find something like a start tag?
+ if (str == end || *str != '<' || ++str == end) {
+ return false;
+ }
+
+ // If we seem to be SGML or XML and we got down here, just pretend we're HTML
+ if (*str == '!' || *str == '?') {
+ mContentType = TEXT_HTML;
+ return true;
+ }
+
+ uint32_t bufSize = end - str;
+ // We use sizeof(_tagstr) below because that's the length of _tagstr
+ // with the one char " " or ">" appended.
+#define MATCHES_TAG(_tagstr) \
+ (bufSize >= sizeof(_tagstr) && \
+ (PL_strncasecmp(str, _tagstr " ", sizeof(_tagstr)) == 0 || \
+ PL_strncasecmp(str, _tagstr ">", sizeof(_tagstr)) == 0))
+
+ if (MATCHES_TAG("html") ||
+ MATCHES_TAG("frameset") ||
+ MATCHES_TAG("body") ||
+ MATCHES_TAG("head") ||
+ MATCHES_TAG("script") ||
+ MATCHES_TAG("iframe") ||
+ MATCHES_TAG("a") ||
+ MATCHES_TAG("img") ||
+ MATCHES_TAG("table") ||
+ MATCHES_TAG("title") ||
+ MATCHES_TAG("link") ||
+ MATCHES_TAG("base") ||
+ MATCHES_TAG("style") ||
+ MATCHES_TAG("div") ||
+ MATCHES_TAG("p") ||
+ MATCHES_TAG("font") ||
+ MATCHES_TAG("applet") ||
+ MATCHES_TAG("meta") ||
+ MATCHES_TAG("center") ||
+ MATCHES_TAG("form") ||
+ MATCHES_TAG("isindex") ||
+ MATCHES_TAG("h1") ||
+ MATCHES_TAG("h2") ||
+ MATCHES_TAG("h3") ||
+ MATCHES_TAG("h4") ||
+ MATCHES_TAG("h5") ||
+ MATCHES_TAG("h6") ||
+ MATCHES_TAG("b") ||
+ MATCHES_TAG("pre")) {
+
+ mContentType = TEXT_HTML;
+ return true;
+ }
+
+#undef MATCHES_TAG
+
+ return false;
+}
+
+bool nsUnknownDecoder::SniffForXML(nsIRequest* aRequest)
+{
+ // Just like HTML, this should be able to be shut off.
+ if (!AllowSniffing(aRequest)) {
+ return false;
+ }
+
+ // First see whether we can glean anything from the uri...
+ if (!SniffURI(aRequest)) {
+ // Oh well; just generic XML will have to do
+ mContentType = TEXT_XML;
+ }
+
+ return true;
+}
+
+bool nsUnknownDecoder::SniffURI(nsIRequest* aRequest)
+{
+ nsCOMPtr<nsIMIMEService> mimeService(do_GetService("@mozilla.org/mime;1"));
+ if (mimeService) {
+ nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
+ if (channel) {
+ nsCOMPtr<nsIURI> uri;
+ nsresult result = channel->GetURI(getter_AddRefs(uri));
+ if (NS_SUCCEEDED(result) && uri) {
+ nsAutoCString type;
+ result = mimeService->GetTypeFromURI(uri, type);
+ if (NS_SUCCEEDED(result)) {
+ mContentType = type;
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+// This macro is based on RFC 2046 Section 4.1.2. Treat any char 0-31
+// except the 9-13 range (\t, \n, \v, \f, \r) and char 27 (used by
+// encodings like Shift_JIS) as non-text
+#define IS_TEXT_CHAR(ch) \
+ (((unsigned char)(ch)) > 31 || (9 <= (ch) && (ch) <= 13) || (ch) == 27)
+
+bool nsUnknownDecoder::LastDitchSniff(nsIRequest* aRequest)
+{
+ // All we can do now is try to guess whether this is text/plain or
+ // application/octet-stream
+
+ const char* testData;
+ uint32_t testDataLen;
+ if (mDecodedData.IsEmpty()) {
+ testData = mBuffer;
+ testDataLen = mBufferLen;
+ } else {
+ testData = mDecodedData.get();
+ testDataLen = std::min(mDecodedData.Length(), MAX_BUFFER_SIZE);
+ }
+
+ // First, check for a BOM. If we see one, assume this is text/plain
+ // in whatever encoding. If there is a BOM _and_ text we will
+ // always have at least 4 bytes in the buffer (since the 2-byte BOMs
+ // are for 2-byte encodings and the UTF-8 BOM is 3 bytes).
+ if (testDataLen >= 4) {
+ const unsigned char* buf = (const unsigned char*)testData;
+ if ((buf[0] == 0xFE && buf[1] == 0xFF) || // UTF-16, Big Endian
+ (buf[0] == 0xFF && buf[1] == 0xFE) || // UTF-16 or UCS-4, Little Endian
+ (buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF) || // UTF-8
+ (buf[0] == 0 && buf[1] == 0 && buf[2] == 0xFE && buf[3] == 0xFF)) { // UCS-4, Big Endian
+
+ mContentType = TEXT_PLAIN;
+ return true;
+ }
+ }
+
+ // Now see whether the buffer has any non-text chars. If not, then let's
+ // just call it text/plain...
+ //
+ uint32_t i;
+ for (i = 0; i < testDataLen && IS_TEXT_CHAR(testData[i]); i++) {
+ continue;
+ }
+
+ if (i == testDataLen) {
+ mContentType = TEXT_PLAIN;
+ }
+ else {
+ mContentType = APPLICATION_OCTET_STREAM;
+ }
+
+ return true;
+}
+
+
+nsresult nsUnknownDecoder::FireListenerNotifications(nsIRequest* request,
+ nsISupports *aCtxt)
+{
+ nsresult rv = NS_OK;
+
+ if (!mNextListener) return NS_ERROR_FAILURE;
+
+ if (!mContentType.IsEmpty()) {
+ nsCOMPtr<nsIViewSourceChannel> viewSourceChannel =
+ do_QueryInterface(request);
+ if (viewSourceChannel) {
+ rv = viewSourceChannel->SetOriginalContentType(mContentType);
+ } else {
+ nsCOMPtr<nsIChannel> channel = do_QueryInterface(request, &rv);
+ if (NS_SUCCEEDED(rv)) {
+ // Set the new content type on the channel...
+ rv = channel->SetContentType(mContentType);
+ }
+ }
+
+ NS_ASSERTION(NS_SUCCEEDED(rv), "Unable to set content type on channel!");
+
+ if (NS_FAILED(rv)) {
+ // Cancel the request to make sure it has the correct status if
+ // mNextListener looks at it.
+ request->Cancel(rv);
+ mNextListener->OnStartRequest(request, aCtxt);
+
+ nsCOMPtr<nsIDivertableChannel> divertable = do_QueryInterface(request);
+ if (divertable) {
+ rv = divertable->UnknownDecoderInvolvedOnStartRequestCalled();
+ }
+
+ return rv;
+ }
+ }
+
+ // Fire the OnStartRequest(...)
+ rv = mNextListener->OnStartRequest(request, aCtxt);
+
+ nsCOMPtr<nsIDivertableChannel> divertable = do_QueryInterface(request);
+ if (divertable) {
+ rv = divertable->UnknownDecoderInvolvedOnStartRequestCalled();
+ bool diverting;
+ divertable->GetDivertingToParent(&diverting);
+ if (diverting) {
+ // The channel is diverted to the parent do not send any more data here.
+ return rv;
+ }
+ }
+
+ if (NS_SUCCEEDED(rv)) {
+ // install stream converter if required
+ nsCOMPtr<nsIEncodedChannel> encodedChannel = do_QueryInterface(request);
+ if (encodedChannel) {
+ nsCOMPtr<nsIStreamListener> listener;
+ rv = encodedChannel->DoApplyContentConversions(mNextListener, getter_AddRefs(listener), aCtxt);
+ if (NS_SUCCEEDED(rv) && listener) {
+ mNextListener = listener;
+ }
+ }
+ }
+
+ if (!mBuffer) return NS_ERROR_OUT_OF_MEMORY;
+
+ // If the request was canceled, then we need to treat that equivalently
+ // to an error returned by OnStartRequest.
+ if (NS_SUCCEEDED(rv))
+ request->GetStatus(&rv);
+
+ // Fire the first OnDataAvailable for the data that was read from the
+ // stream into the sniffer buffer...
+ if (NS_SUCCEEDED(rv) && (mBufferLen > 0)) {
+ uint32_t len = 0;
+ nsCOMPtr<nsIInputStream> in;
+ nsCOMPtr<nsIOutputStream> out;
+
+ // Create a pipe and fill it with the data from the sniffer buffer.
+ rv = NS_NewPipe(getter_AddRefs(in), getter_AddRefs(out),
+ MAX_BUFFER_SIZE, MAX_BUFFER_SIZE);
+
+ if (NS_SUCCEEDED(rv)) {
+ rv = out->Write(mBuffer, mBufferLen, &len);
+ if (NS_SUCCEEDED(rv)) {
+ if (len == mBufferLen) {
+ rv = mNextListener->OnDataAvailable(request, aCtxt, in, 0, len);
+ } else {
+ NS_ERROR("Unable to write all the data into the pipe.");
+ rv = NS_ERROR_FAILURE;
+ }
+ }
+ }
+ }
+
+ delete [] mBuffer;
+ mBuffer = nullptr;
+ mBufferLen = 0;
+
+ return rv;
+}
+
+
+nsresult
+nsUnknownDecoder::ConvertEncodedData(nsIRequest* request,
+ const char* data,
+ uint32_t length)
+{
+ nsresult rv = NS_OK;
+
+ mDecodedData = "";
+ nsCOMPtr<nsIEncodedChannel> encodedChannel(do_QueryInterface(request));
+ if (encodedChannel) {
+
+ RefPtr<ConvertedStreamListener> strListener =
+ new ConvertedStreamListener(this);
+
+ nsCOMPtr<nsIStreamListener> listener;
+ rv = encodedChannel->DoApplyContentConversions(strListener,
+ getter_AddRefs(listener),
+ nullptr);
+
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+
+ if (listener) {
+ listener->OnStartRequest(request, nullptr);
+
+ nsCOMPtr<nsIStringInputStream> rawStream =
+ do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID);
+ if (!rawStream)
+ return NS_ERROR_FAILURE;
+
+ rv = rawStream->SetData((const char*)data, length);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = listener->OnDataAvailable(request, nullptr, rawStream, 0,
+ length);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ listener->OnStopRequest(request, nullptr, NS_OK);
+ }
+ }
+ return rv;
+}
+
+void
+nsBinaryDetector::DetermineContentType(nsIRequest* aRequest)
+{
+ nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest);
+ if (!httpChannel) {
+ return;
+ }
+
+ // It's an HTTP channel. Check for the text/plain mess
+ nsAutoCString contentTypeHdr;
+ httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Type"),
+ contentTypeHdr);
+ nsAutoCString contentType;
+ httpChannel->GetContentType(contentType);
+
+ // Make sure to do a case-sensitive exact match comparison here. Apache
+ // 1.x just sends text/plain for "unknown", while Apache 2.x sends
+ // text/plain with a ISO-8859-1 charset. Debian's Apache version, just to
+ // be different, sends text/plain with iso-8859-1 charset. For extra fun,
+ // FC7, RHEL4, and Ubuntu Feisty send charset=UTF-8. Don't do general
+ // case-insensitive comparison, since we really want to apply this crap as
+ // rarely as we can.
+ if (!contentType.EqualsLiteral("text/plain") ||
+ (!contentTypeHdr.EqualsLiteral("text/plain") &&
+ !contentTypeHdr.EqualsLiteral("text/plain; charset=ISO-8859-1") &&
+ !contentTypeHdr.EqualsLiteral("text/plain; charset=iso-8859-1") &&
+ !contentTypeHdr.EqualsLiteral("text/plain; charset=UTF-8"))) {
+ return;
+ }
+
+ // Check whether we have content-encoding. If we do, don't try to
+ // detect the type.
+ // XXXbz we could improve this by doing a local decompress if we
+ // wanted, I'm sure.
+ nsAutoCString contentEncoding;
+ httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Encoding"),
+ contentEncoding);
+ if (!contentEncoding.IsEmpty()) {
+ return;
+ }
+
+ LastDitchSniff(aRequest);
+ if (mContentType.Equals(APPLICATION_OCTET_STREAM)) {
+ // We want to guess at it instead
+ mContentType = APPLICATION_GUESS_FROM_EXT;
+ } else {
+ // Let the text/plain type we already have be, so that other content
+ // sniffers can also get a shot at this data.
+ mContentType.Truncate();
+ }
+}
diff --git a/netwerk/streamconv/converters/nsUnknownDecoder.h b/netwerk/streamconv/converters/nsUnknownDecoder.h
new file mode 100644
index 000000000..a5087ed06
--- /dev/null
+++ b/netwerk/streamconv/converters/nsUnknownDecoder.h
@@ -0,0 +1,159 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef nsUnknownDecoder_h__
+#define nsUnknownDecoder_h__
+
+#include "nsIStreamConverter.h"
+#include "nsIContentSniffer.h"
+
+#include "nsCOMPtr.h"
+#include "nsString.h"
+
+#define NS_UNKNOWNDECODER_CID \
+{ /* 7d7008a0-c49a-11d3-9b22-0080c7cb1080 */ \
+ 0x7d7008a0, \
+ 0xc49a, \
+ 0x11d3, \
+ {0x9b, 0x22, 0x00, 0x80, 0xc7, 0xcb, 0x10, 0x80} \
+}
+
+
+class nsUnknownDecoder : public nsIStreamConverter, public nsIContentSniffer
+{
+public:
+ // nsISupports methods
+ NS_DECL_ISUPPORTS
+
+ // nsIStreamConverter methods
+ NS_DECL_NSISTREAMCONVERTER
+
+ // nsIStreamListener methods
+ NS_DECL_NSISTREAMLISTENER
+
+ // nsIRequestObserver methods
+ NS_DECL_NSIREQUESTOBSERVER
+
+ // nsIContentSniffer methods
+ NS_DECL_NSICONTENTSNIFFER
+
+ nsUnknownDecoder();
+
+protected:
+ virtual ~nsUnknownDecoder();
+
+ virtual void DetermineContentType(nsIRequest* aRequest);
+ nsresult FireListenerNotifications(nsIRequest* request, nsISupports *aCtxt);
+
+ class ConvertedStreamListener: public nsIStreamListener
+ {
+ public:
+ explicit ConvertedStreamListener(nsUnknownDecoder *aDecoder);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIREQUESTOBSERVER
+ NS_DECL_NSISTREAMLISTENER
+
+ private:
+ virtual ~ConvertedStreamListener();
+ static nsresult AppendDataToString(nsIInputStream* inputStream,
+ void* closure,
+ const char* rawSegment,
+ uint32_t toOffset,
+ uint32_t count,
+ uint32_t* writeCount);
+ nsUnknownDecoder *mDecoder;
+ };
+
+protected:
+ nsCOMPtr<nsIStreamListener> mNextListener;
+
+ // Function to use to check whether sniffing some potentially
+ // dangerous types (eg HTML) is ok for this request. We can disable
+ // sniffing for local files if needed using this. Just a security
+ // precation thingy... who knows when we suddenly need to flip this
+ // pref?
+ bool AllowSniffing(nsIRequest* aRequest);
+
+ // Various sniffer functions. Returning true means that a type
+ // was determined; false means no luck.
+ bool SniffForHTML(nsIRequest* aRequest);
+ bool SniffForXML(nsIRequest* aRequest);
+
+ // SniffURI guesses at the content type based on the URI (typically
+ // using the extentsion)
+ bool SniffURI(nsIRequest* aRequest);
+
+ // LastDitchSniff guesses at text/plain vs. application/octet-stream
+ // by just looking at whether the data contains null bytes, and
+ // maybe at the fraction of chars with high bit set. Use this only
+ // as a last-ditch attempt to decide a content type!
+ bool LastDitchSniff(nsIRequest* aRequest);
+
+ /**
+ * An entry struct for our array of sniffers. Each entry has either
+ * a type associated with it (set these with the SNIFFER_ENTRY macro)
+ * or a function to be executed (set these with the
+ * SNIFFER_ENTRY_WITH_FUNC macro). The function should take a single
+ * nsIRequest* and returns bool -- true if it sets mContentType,
+ * false otherwise
+ */
+ struct nsSnifferEntry {
+ typedef bool (nsUnknownDecoder::*TypeSniffFunc)(nsIRequest* aRequest);
+
+ const char* mBytes;
+ uint32_t mByteLen;
+
+ // Exactly one of mMimeType and mContentTypeSniffer should be set non-null
+ const char* mMimeType;
+ TypeSniffFunc mContentTypeSniffer;
+ };
+
+#define SNIFFER_ENTRY(_bytes, _type) \
+ { _bytes, sizeof(_bytes) - 1, _type, nullptr }
+
+#define SNIFFER_ENTRY_WITH_FUNC(_bytes, _func) \
+ { _bytes, sizeof(_bytes) - 1, nullptr, _func }
+
+ static nsSnifferEntry sSnifferEntries[];
+ static uint32_t sSnifferEntryNum;
+
+ char *mBuffer;
+ uint32_t mBufferLen;
+ bool mRequireHTMLsuffix;
+
+ nsCString mContentType;
+
+protected:
+ nsresult ConvertEncodedData(nsIRequest* request, const char* data,
+ uint32_t length);
+ nsCString mDecodedData; // If data are encoded this will be uncompress data.
+};
+
+#define NS_BINARYDETECTOR_CID \
+{ /* a2027ec6-ba0d-4c72-805d-148233f5f33c */ \
+ 0xa2027ec6, \
+ 0xba0d, \
+ 0x4c72, \
+ {0x80, 0x5d, 0x14, 0x82, 0x33, 0xf5, 0xf3, 0x3c} \
+}
+
+/**
+ * Class that detects whether a data stream is text or binary. This reuses
+ * most of nsUnknownDecoder except the actual content-type determination logic
+ * -- our overridden DetermineContentType simply calls LastDitchSniff and sets
+ * the type to APPLICATION_GUESS_FROM_EXT if the data is detected as binary.
+ */
+class nsBinaryDetector : public nsUnknownDecoder
+{
+protected:
+ virtual void DetermineContentType(nsIRequest* aRequest);
+};
+
+#define NS_BINARYDETECTOR_CATEGORYENTRY \
+ { NS_CONTENT_SNIFFER_CATEGORY, "Binary Detector", NS_BINARYDETECTOR_CONTRACTID }
+
+#endif /* nsUnknownDecoder_h__ */
+
diff --git a/netwerk/streamconv/converters/parse-ftp/3-guess.in b/netwerk/streamconv/converters/parse-ftp/3-guess.in
new file mode 100644
index 000000000..b5e8596c1
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/3-guess.in
@@ -0,0 +1,30 @@
+I couldn't find any SuperTCP or Chameleon/Newt FTP servers, so the
+following is based on guesswork from the mirror.pl and lynx projects.
+The first 8 are Chameleon/Newt, the remaining 16 entries are SuperTCP
+with two different date styles. The precise amount of whitespace
+between columns might not be correct, but the parser shouldn't care.
+
+. <DIR> Nov 16 1994 17:16
+.. <DIR> Nov 16 1994 17:16
+INSTALL <DIR> Nov 16 1994 17:17
+CMT <DIR> Nov 21 1994 10:17
+DESIGN1.DOC 11264 May 11 1995 14:20 A
+README.TXT 1045 May 10 1995 11:01
+WPKIT1.EXE 960338 Jun 21 1995 17:01 R
+CMT.CSV 0 Jul 06 1995 14:56 RHA
+. <DIR> 11-16-94 17:16
+.. <DIR> 11-16-94 17:16
+INSTALL <DIR> 11-16-94 17:17
+CMT <DIR> 11-21-94 10:17
+DESIGN1.DOC 11264 05-11-95 14:20
+README.TXT 1045 05-10-95 11:01
+WPKIT1.EXE 960338 06-21-95 17:01
+CMT.CSV 0 07-06-95 14:56
+. <DIR> 11/16/94 17:16
+.. <DIR> 11/16/94 17:16
+INSTALL <DIR> 11/16/94 17:17
+CMT <DIR> 11/21/94 10:17
+DESIGN1.DOC 11264 05/11/95 14:20
+README.TXT 1045 05/10/95 11:01
+WPKIT1.EXE 960338 06/21/95 17:01
+CMT.CSV 0 07/06/95 14:56
diff --git a/netwerk/streamconv/converters/parse-ftp/3-guess.out b/netwerk/streamconv/converters/parse-ftp/3-guess.out
new file mode 100644
index 000000000..30a1d0fb9
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/3-guess.out
@@ -0,0 +1,28 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+11-16-1994 17:16:00 <DIR> .
+11-16-1994 17:16:00 <DIR> ..
+11-16-1994 17:17:00 <DIR> INSTALL
+11-21-1994 10:17:00 <DIR> CMT
+05-11-1995 14:20:00 11264 DESIGN1.DOC
+05-10-1995 11:01:00 1045 README.TXT
+06-21-1995 17:01:00 960338 WPKIT1.EXE
+07-06-1995 14:56:00 0 CMT.CSV
+11-16-1994 17:16:00 <DIR> .
+11-16-1994 17:16:00 <DIR> ..
+11-16-1994 17:17:00 <DIR> INSTALL
+11-21-1994 10:17:00 <DIR> CMT
+05-11-1995 14:20:00 11264 DESIGN1.DOC
+05-10-1995 11:01:00 1045 README.TXT
+06-21-1995 17:01:00 960338 WPKIT1.EXE
+07-06-1995 14:56:00 0 CMT.CSV
+11-16-1994 17:16:00 <DIR> .
+11-16-1994 17:16:00 <DIR> ..
+11-16-1994 17:17:00 <DIR> INSTALL
+11-21-1994 10:17:00 <DIR> CMT
+05-11-1995 14:20:00 11264 DESIGN1.DOC
+05-10-1995 11:01:00 1045 README.TXT
+06-21-1995 17:01:00 960338 WPKIT1.EXE
+07-06-1995 14:56:00 0 CMT.CSV
diff --git a/netwerk/streamconv/converters/parse-ftp/C-VMold.in b/netwerk/streamconv/converters/parse-ftp/C-VMold.in
new file mode 100644
index 000000000..5453b496e
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/C-VMold.in
@@ -0,0 +1,16 @@
+This is a synthetic LISTing based on comments in mirror.pl and a
+screenshot I saw somewhere. Either way, its 'synthetic' because I
+couldn't find an FTP server that LISTed like this. Note that (as
+with other VM/CMS LISTings) filesize cannot be determined from
+the listing and (AFAIK) files/dirs not on the 'A' minidisk (see
+'Fm' field) are not RETRievable/CHDIR'able without magic.
+
+Filename FileType Fm Format Lrecl Records Blocks Date Time
+LASTING GLOBALV A1 V 41 21 1 9/16/91 15:10:32
+J43401 NETLOG A0 V 77 1 1 9/12/91 12:36:04
+PROFILE EXEC A1 V 17 3 1 9/12/91 12:39:07
+DIRUNIX SCRIPT A1 V 77 1216 17 1/04/93 20:30:47
+MAIL PROFILE A2 F 80 1 1 10/14/92 16:12:27
+ABADY2K DATE A0 V 1 1 1 1/03/100 10:11:12
+BBADY2K DATE A0 V 1 1 1 11/03/100 10:11:12
+AUTHORS A1 DIR - - - 9/20/99 10:31:11
diff --git a/netwerk/streamconv/converters/parse-ftp/C-VMold.out b/netwerk/streamconv/converters/parse-ftp/C-VMold.out
new file mode 100644
index 000000000..0c9c016f6
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/C-VMold.out
@@ -0,0 +1,12 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+09-16-1991 15:10:32 LASTING.GLOBALV
+09-12-1991 12:36:04 J43401.NETLOG
+09-12-1991 12:39:07 PROFILE.EXEC
+01-04-1993 20:30:47 DIRUNIX.SCRIPT
+10-14-1992 16:12:27 MAIL.PROFILE
+01-03-2000 10:11:12 ABADY2K.DATE
+11-03-2000 10:11:12 BBADY2K.DATE
+09-20-1999 10:31:11 <DIR> AUTHORS
diff --git a/netwerk/streamconv/converters/parse-ftp/C-zVM.in b/netwerk/streamconv/converters/parse-ftp/C-zVM.in
new file mode 100644
index 000000000..bd63f631f
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/C-zVM.in
@@ -0,0 +1,61 @@
+ftp> open vm.marist.edu
+220-Welcome to FTP.Marist.edu
+220-
+220-All usage logged. Usage restricted.
+220-FTPSERVE IBM VM Level 420 at VM.MARIST.EDU, 05:06:00 EDT WEDNESDAY 2002-07-10
+220 Connection will close if idle for more than 5 minutes.
+Name (vm.marist.edu:cyp):
+230-
+230-
+230-Listserv logs for certain lists are available via CD ACADEM:listname.
+230-
+230-Lists that they are available for are:
+230-
+230-ADSM-L ftp://vm.marist.edu/academ:adsm-l./
+230-CLINTON ftp://vm.marist.edu/academ:clinton./
+230-CMSPIP-L ftp://vm.marist.edu/academ:cmspip-l./
+230-CONCORD ftp://vm.marist.edu/academ:concord./
+230-REPUB-L ftp://vm.marist.edu/academ:repub-l./
+230-SAS-L ftp://vm.marist.edu/academ:sas-l./
+230-VM-UTIL ftp://vm.marist.edu/academ:vm-util./
+230-LINUX-VM ftp://vm.marist.edu/academ:linux-vm./
+230-
+230-For example: (Note the trailing .)
+230-
+230-CD ACADEM:ADSM-L.
+230-
+230-Due to limitations of Netscape, you may need to append ";type=a"
+230-to the end of a URL when obtaining a file.
+230-
+230-CMS Pipelines RLD available as
+230-
+230- ftp://vm.marist.edu/academ:pipeline/eweb./
+230-
+230 ANONYMOU logged in; working directory = ACADEM:ANONYMOU.
+Remote system type is z/VM.
+ftp> ls
+200 Port request OK.
+125 List started OK
+README ANONYMOU V 71 26 1 1997-04-02 12:33:20 TCP291
+README ANONYOLD V 71 15 1 1995-08-25 16:04:27 TCP291
+AUTHORS DIR - - - 1999-09-20 10:31:11 -
+HARRINGTON DIR - - - 1997-02-12 15:33:28 -
+PICS DIR - - - 2000-10-12 15:43:23 -
+SYSFILE DIR - - - 2000-07-20 17:48:01 -
+WELCNVT EXEC V 72 9 1 1999-09-20 17:16:18 -
+WELCOME EREADME F 80 21 1 1999-12-27 16:19:00 -
+WELCOME README V 82 21 1 1999-12-27 16:19:04 -
+PROJECT PDF V 984 10 3 1997-06-15 11:15:02 -
+CAMPUS TIF V 8192 3172 3606 2000-10-06 17:20:37 -
+ROTUNDA TIF V 8192 5745 8750 2000-10-06 17:28:25 -
+STUDENT TIF V 8192 5017 8557 2000-10-06 17:31:26 -
+CHILDREN TXT V 280 310 20 1993-08-06 14:20:00 -
+SYSFILE VMARC F 80 2001 40 2000-07-20 17:47:35 -
+250 List completed successfully.
+ftp> syst
+215-z/VM Version 4 Release 2.0, service level 0101 (32-bit)
+ VM/CMS Level 18, Service Level 101
+215 VM is the operating system of this server.
+ftp> close
+221 Quit command received. Goodbye.
+ftp>
diff --git a/netwerk/streamconv/converters/parse-ftp/C-zVM.out b/netwerk/streamconv/converters/parse-ftp/C-zVM.out
new file mode 100644
index 000000000..04511ebc7
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/C-zVM.out
@@ -0,0 +1,19 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+04-02-1997 12:33:20 README.ANONYMOU
+08-25-1995 16:04:27 README.ANONYOLD
+09-20-1999 10:31:11 <DIR> AUTHORS
+02-12-1997 15:33:28 <DIR> HARRINGTON
+10-12-2000 15:43:23 <DIR> PICS
+07-20-2000 17:48:01 <DIR> SYSFILE
+09-20-1999 17:16:18 WELCNVT.EXEC
+12-27-1999 16:19:00 WELCOME.EREADME
+12-27-1999 16:19:04 WELCOME.README
+06-15-1997 11:15:02 PROJECT.PDF
+10-06-2000 17:20:37 CAMPUS.TIF
+10-06-2000 17:28:25 ROTUNDA.TIF
+10-06-2000 17:31:26 STUDENT.TIF
+08-06-1993 14:20:00 CHILDREN.TXT
+07-20-2000 17:47:35 SYSFILE.VMARC
diff --git a/netwerk/streamconv/converters/parse-ftp/D-WinNT.in b/netwerk/streamconv/converters/parse-ftp/D-WinNT.in
new file mode 100644
index 000000000..e5b5297f4
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/D-WinNT.in
@@ -0,0 +1,60 @@
+ftp> open ftp.microsoft.com
+220 Microsoft FTP Service
+Name (ftp.microsoft.com:cyp):
+331 Anonymous access allowed, send identity (e-mail name) as password.
+230-This is FTP.Microsoft.Com
+230 Anonymous user logged in.
+Remote system type is Windows_NT.
+ftp> quote dirstyle
+200 MSDOS-like directory output is on
+ftp> ls
+200 PORT command successful.
+150 Opening ASCII mode data connection for /bin/ls.
+02-05-01 05:52PM <DIR> 20Year
+09-26-00 03:20PM <DIR> AccessFoxPro
+12-21-00 02:39PM <DIR> AlbGrp
+05-31-01 11:16AM <DIR> Alexandra
+01-19-01 09:36AM <DIR> anna
+04-06-00 12:53PM <DIR> anz
+05-10-00 01:37PM <DIR> Chase Bobko2
+03-29-00 02:43PM <DIR> cnn
+11-21-00 11:21AM <DIR> Darin
+03-09-00 05:55PM <DIR> digitalchicago
+09-06-00 11:38AM <DIR> Dublin
+01-30-01 07:15PM <DIR> eleanorf
+04-26-01 11:04AM <DIR> girvin
+04-26-00 09:28PM <DIR> Hires
+08-15-00 05:03PM <DIR> HR
+10-24-99 01:29AM 4368384 IMG00022.PCD
+05-18-01 07:52AM <DIR> jacubowsky
+10-12-00 10:55AM <DIR> JFalvey
+03-28-01 02:38PM <DIR> johnci
+07-14-00 08:59AM <DIR> Karin
+09-07-00 05:48PM <DIR> Kjung
+09-28-00 08:59AM <DIR> LarryE
+08-17-00 06:06PM <DIR> Larson
+09-12-00 05:22PM <DIR> marion
+08-09-00 12:30PM <DIR> ms25
+11-16-00 03:58PM <DIR> MS25Brochure
+03-29-00 12:07PM <DIR> MShistory
+09-05-00 10:35AM <DIR> Neils
+08-02-00 06:25PM <DIR> NLM
+09-06-00 03:04PM <DIR> PageOne
+06-27-00 06:00PM <DIR> pccomputing
+05-09-01 01:27PM <DIR> pictures
+07-21-00 04:23PM <DIR> pranks
+08-22-00 10:36AM <DIR> Sean
+08-10-00 01:54PM <DIR> SLeong
+09-07-00 05:46PM <DIR> svr
+07-21-00 07:22AM <JUNCTION> a_junction_sample
+10-23-00 01:27PM <JUNCTION> b_junction_sample => foo
+06-15-00 07:37AM <JUNCTION> c_junction_sample -> bar too
+07-14-00 01:35PM 2094926 canprankdesk.tif
+07-21-00 01:19PM 95077 Jon Kauffman Enjoys the Good Life.jpg
+07-21-00 01:19PM 52275 Name Plate.jpg
+07-14-00 01:38PM 2250540 Valentineoffprank-HiRes.jpg
+226 Transfer complete.
+ftp> close
+221 Thank-You For Using Microsoft Products!
+ftp>
+
diff --git a/netwerk/streamconv/converters/parse-ftp/D-WinNT.out b/netwerk/streamconv/converters/parse-ftp/D-WinNT.out
new file mode 100644
index 000000000..a6e8e74d1
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/D-WinNT.out
@@ -0,0 +1,47 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+02-05-2001 17:52:00 <DIR> 20Year
+09-26-2000 15:20:00 <DIR> AccessFoxPro
+12-21-2000 14:39:00 <DIR> AlbGrp
+05-31-2001 11:16:00 <DIR> Alexandra
+01-19-2001 09:36:00 <DIR> anna
+04-06-2000 12:53:00 <DIR> anz
+05-10-2000 13:37:00 <DIR> Chase Bobko2
+03-29-2000 14:43:00 <DIR> cnn
+11-21-2000 11:21:00 <DIR> Darin
+03-09-2000 17:55:00 <DIR> digitalchicago
+09-06-2000 11:38:00 <DIR> Dublin
+01-30-2001 19:15:00 <DIR> eleanorf
+04-26-2001 11:04:00 <DIR> girvin
+04-26-2000 21:28:00 <DIR> Hires
+08-15-2000 17:03:00 <DIR> HR
+10-24-1999 01:29:00 4368384 IMG00022.PCD
+05-18-2001 07:52:00 <DIR> jacubowsky
+10-12-2000 10:55:00 <DIR> JFalvey
+03-28-2001 14:38:00 <DIR> johnci
+07-14-2000 08:59:00 <DIR> Karin
+09-07-2000 17:48:00 <DIR> Kjung
+09-28-2000 08:59:00 <DIR> LarryE
+08-17-2000 18:06:00 <DIR> Larson
+09-12-2000 17:22:00 <DIR> marion
+08-09-2000 12:30:00 <DIR> ms25
+11-16-2000 15:58:00 <DIR> MS25Brochure
+03-29-2000 12:07:00 <DIR> MShistory
+09-05-2000 10:35:00 <DIR> Neils
+08-02-2000 18:25:00 <DIR> NLM
+09-06-2000 15:04:00 <DIR> PageOne
+06-27-2000 18:00:00 <DIR> pccomputing
+05-09-2001 13:27:00 <DIR> pictures
+07-21-2000 16:23:00 <DIR> pranks
+08-22-2000 10:36:00 <DIR> Sean
+08-10-2000 13:54:00 <DIR> SLeong
+09-07-2000 17:46:00 <DIR> svr
+07-21-2000 07:22:00 <JUNCTION> a_junction_sample
+10-23-2000 13:27:00 <JUNCTION> b_junction_sample -> foo
+06-15-2000 07:37:00 <JUNCTION> c_junction_sample -> bar too
+07-14-2000 13:35:00 2094926 canprankdesk.tif
+07-21-2000 13:19:00 95077 Jon Kauffman Enjoys the Good Life.jpg
+07-21-2000 13:19:00 52275 Name Plate.jpg
+07-14-2000 13:38:00 2250540 Valentineoffprank-HiRes.jpg
diff --git a/netwerk/streamconv/converters/parse-ftp/E-EPLF.in b/netwerk/streamconv/converters/parse-ftp/E-EPLF.in
new file mode 100644
index 000000000..3798ea0a9
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/E-EPLF.in
@@ -0,0 +1,189 @@
+ftp> open cr.yp.to
+Connected to cr.yp.to.
+220 Features: a p .
+Name (cr.yp.to:cyp):
+230 Hi. No need to log in; I'm an anonymous ftp server.
+Remote system type is UNIX.
+Using binary mode to transfer files.
+ftp> ls
+200 Okay.
+150 Making transfer connection...
++i0.307427,m979205905,/, tmp
++i0.631874,m951789705,/, 1998-100
++i0.236492,m977690646,r,s1172, mirrors.html
++i0.718174,m951789707,/, 1999-275
++i0.236496,m957763516,r,s933, 1999-275.html
++i0.236247,m957763626,r,s322, 1998-401.html
++i0.689416,m951789707,/, 1998-401
++i0.714380,m951789705,/, 1997-275
++i0.236426,m957763705,r,s277, 1998-515.html
++i0.236324,m957764203,r,s325, 2000-436.html
++i0.553153,m977554031,/, checkpwd
++i0.73117,m1025804866,/, bib
++i0.2012,m951789707,/, 1999-541
++i0.134494,m988426955,/, 2001-260
++i0.457327,m1019068075,/, 2002-501
++i0.11567,m991428977,/, 1995-514
++i0.716165,m951789705,/, 1999-180
++i0.236327,m991363463,r,s475, 2000-515.html
++i0.687522,m951789707,/, 1998-515
++i0.412995,m951789707,/, 2000-515
++i0.213334,m958117573,/, zpfft
++i0.295901,m1004187614,/, psibound
++i0.236429,m951789711,r,s398, anonftpd.html
++i0.326793,m1014690862,/, nistp224
++i0.587605,m997428440,/, cdb
++i0.516884,m1020211107,/, talks
++i0.255382,m977607275,/, ftpparse
++i0.103809,m947569810,/, clockspeed
++i0.236433,m951789712,r,s1350, clockspeed.html
++i0.530322,m1013028754,/, slashdoc
++i0.10002,m1023465640,/, export
++i0.105740,m995334516,/, daemontools
++i0.236425,m994972628,r,s2187, daemontools.html
++i0.236437,m999204676,r,s175, data.html
++i0.236435,m1009503157,r,s1901, crypto.html
++i0.236430,m1005435923,r,s739, arith.html
++i0.236297,m1007092089,r,s2733, cdb.html
++i0.236475,m1005436262,r,s344, floatasm.html
++i0.126821,m977433956,/, djbfft
++i0.236440,m951789712,r,s1319, djbfft.html
++i0.149876,m963163007,/, dnscache
++i0.236441,m962665064,r,s4016, dnscache.html
++i0.674064,m994734982,/, docs
++i0.236442,m951789712,r,s293, docs.html
++i0.236443,m951789712,r,s952, dot-forward.html
++i0.76895,m947569811,/, etc-mta
++i0.236444,m951789712,r,s3174, etc-mta.html
++i0.236445,m951789712,r,s2990, ezmlm.html
++i0.142082,m977433956,/, ftp
++i0.78826,m951789709,/, im
++i0.236446,m951789712,r,s1823, fastforward.html
++i0.236447,m951789712,r,s1707, ftp.html
++i0.21212,m981944230,/, freebugtraq
++i0.117314,m1022981965,/, hardware
++i0.236326,m991364255,r,s610, 1995-514.html
++i0.63463,m977433957,/, hash127
++i0.236450,m958703342,r,s4835, hash127.html
++i0.236451,m951789712,r,s1515, im.html
++i0.82651,m1013546406,/, immhf
++i0.236299,m988235329,r,s2902, immhf.html
++i0.147915,m980402316,/, lib
++i0.591514,m991784750,/, libtai
++i0.236454,m963255256,r,s2120, libtai.html
++i0.236427,m1006883560,r,s14460, qmail.html
++i0.236452,m999204683,r,s2153, mail.html
++i0.236457,m951789712,r,s108, maildir.html
++i0.71192,m951789710,/, maildisasters
++i0.236458,m951789712,r,s873, maildisasters.html
++i0.236459,m951789712,r,s1688, mess822.html
++i0.13517,m1014605247,/, mirror
++i0.236431,m1009400552,r,s581, ntheory.html
++i0.629891,m1023118587,/, papers
++i0.176720,m1021999815,/, postpropter
++i0.67332,m947569812,/, postings
++i0.101902,m947569812,/, primegen
++i0.236453,m999204693,r,s415, precompiled.html
++i0.236463,m951789712,r,s1121, primegen.html
++i0.574160,m1020562675,/, proto
++i0.236464,m951789712,r,s452, proto.html
++i0.113471,m994717073,/, publicfile
++i0.236295,m1007092757,r,s5651, publicfile.html
++i0.236455,m999204697,r,s409, qlist.html
++i0.15552,m1017725145,/, qmail
++i0.236292,m1012629148,r,s7549, lists.html
++i0.236468,m951789712,r,s1166, qmailanalog.html
++i0.236456,m999204699,r,s1434, qmsmac.html
++i0.236470,m952925886,r,s465, rblsmtpd.html
++i0.236471,m951789712,r,s1225, rights.html
++i0.691333,m947569813,/, sarcasm
++i0.236465,m1000434854,r,s1058, unix.html
++i0.236472,m951789713,r,s1568, serialmail.html
++i0.236473,m970514024,r,s840, sigs.html
++i0.80743,m1021999808,/, smtp
++i0.236300,m988300727,r,s1723, smtp.html
++i0.693264,m977433963,/, software
++i0.236476,m951789713,r,s3671, softwarelaw.html
++i0.710487,m947569813,/, sortedsums
++i0.236477,m951789713,r,s2735, sortedsums.html
++i0.23149,m1014689198,/, speed
++i0.236478,m962664017,r,s572, surveydns.html
++i0.589555,m1002157171,/, surveys
++i0.236278,m1002156396,r,s3503, surveys.html
++i0.96135,m973835888,/, syncookies
++i0.236479,m1012529017,r,s7918, syncookies.html
++i0.236460,m999204703,r,s1115, tcpcontrol.html
++i0.236461,m1016453307,r,s589, tcpip.html
++i0.236483,m951789713,r,s906, thoughts.html
++i0.136514,m996502689,/, threecubes
++i0.236462,m1000430758,r,s525, time.html
++i0.121107,m1022041265,/, ucspi-tcp
++i0.236484,m1011915691,r,s4086, ucspi-tcp.html
++i0.236285,m999204710,r,s732, web.html
++i0.236323,m1025804868,/, www
++i0.236467,m1000430768,r,s2717, y2k.html
++i0.94216,m981624489,/, dnsroot
++i0.236280,m988005697,r,s2745, 2001-260.html
++i0.236489,m951789713,r,s291, zeroseek.html
++i0.90373,m951789713,/, zmodexp
++i0.236490,m958703347,r,s1513, zmodexp.html
++i0.65452,m965092134,/, zmult
++i0.236491,m965093093,r,s669, zmult.html
++i0.236432,m977552387,r,s1097, checkpwd.html
++i0.236480,m1009824436,r,s2077, focus.html
++i0.236493,m964048291,r,s3842, im2000.html
++i0.5981,m1025804863,/, slashcommand
++i0.192219,m1025804864,/, slashpackage
++i0.236277,m995235879,r,s602, slashpackage.html
++i0.236302,m1020384933,r,s23874, talks.html
++i0.236495,m957763499,r,s566, 1997-275.html
++i0.236494,m957763864,r,s313, 1998-100.html
++i0.543361,m951789707,/, 2000-436
++i0.236424,m957764246,r,s660, 1997-494.html
++i0.236428,m957764441,r,s730, 1999-541.html
++i0.236497,m968828938,r,s2367, psibound.html
++i0.236500,m961639740,r,s1866, smallfactors.html
++i0.413016,m960514519,/, smallfactors
++i0.75096,m962492119,/, conferences
++i0.557013,m1022046749,/, djbdns
++i0.236282,m995342458,r,s2712, djbdns.html
++i0.236502,m963796539,r,s216, zpfft.html
++i0.537820,m966797797,/, fastnewton
++i0.236503,m966797851,r,s333, fastnewton.html
++i0.510806,m967833231,/, patents
++i0.236448,m977607617,r,s1748, ftpparse.html
++i0.236281,m1005436670,r,s3261, slash.html
++i0.236279,m979753810,r,s2663, slashdoc.html
++i0.236283,m1016442275,r,s2344, dnsroot.html
++i0.236284,m1009400580,r,s3238, software.html
++i0.236287,m1000434873,r,s3481, compatibility.html
++i0.236291,m1020223834,r,s5525, distributors.html
++i0.236293,m983072943,r,s212, freebugtraq.html
++i0.236294,m1017547190,r,s806, hardware.html
++i0.236296,m986022918,r,s121, securesoftware.html
++i0.236301,m1022035196,r,s10950, conferences.html
++i0.378623,m1007142710,/, 2001-275
++i0.236303,m991095307,r,s459, rwb100.html
++i0.236325,m1002087642,r,s863, nistp224.html
++i0.236436,m996502546,r,s778, threecubes.html
++i0.236298,m1023118336,r,s27125, papers.html
++i0.236439,m1006311069,r,s379, bib.html
++i0.236438,m1007142093,r,s3791, 2001-275.html
++i0.236474,m1002046139,r,s169, dh224.html
++i0.236434,m1016258736,r,s1126, courses.html
++i0.236466,m999469348,r,s355, slashcommand.html
++i0.236449,m1017264022,r,s1199, patents.html
++i0.236469,m1005247635,r,s640, mailcopyright.html
++i0.236286,m1022974070,r,s1257, djb.html
++i0.236481,m1010383954,r,s301, 2002-501.html
++i0.236482,m1020220905,r,s1655, export.html
++i0.236276,m1016966459,r,s6446, index.html
++i0.236485,m1023740653, donations.html
++i0.236486,m1016258948,r,s570, 2005-590.html
++i0.236487,m1016258749,r,s800, 2004-494.html
++i0.236488,m1023740407, thanks.html
++i0.236498,m1022974139,r,s4459, positions.html
++i0.236499,m1022972131,r,s466, contact.html
+226 Success.
+ftp> close
+ftp> \ No newline at end of file
diff --git a/netwerk/streamconv/converters/parse-ftp/E-EPLF.out b/netwerk/streamconv/converters/parse-ftp/E-EPLF.out
new file mode 100644
index 000000000..e72a79353
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/E-EPLF.out
@@ -0,0 +1,174 @@
+01-11-2001 10:38:25 <DIR> tmp
+02-29-2000 03:01:45 <DIR> 1998-100
+12-24-2000 21:44:06 1172 mirrors.html
+02-29-2000 03:01:47 <DIR> 1999-275
+05-08-2000 07:25:16 933 1999-275.html
+05-08-2000 07:27:06 322 1998-401.html
+02-29-2000 03:01:47 <DIR> 1998-401
+02-29-2000 03:01:45 <DIR> 1997-275
+05-08-2000 07:28:25 277 1998-515.html
+05-08-2000 07:36:43 325 2000-436.html
+12-23-2000 07:47:11 <DIR> checkpwd
+07-04-2002 19:47:46 <DIR> bib
+02-29-2000 03:01:47 <DIR> 1999-541
+04-28-2001 05:02:35 <DIR> 2001-260
+04-17-2002 20:27:55 <DIR> 2002-501
+06-01-2001 22:56:17 <DIR> 1995-514
+02-29-2000 03:01:45 <DIR> 1999-180
+06-01-2001 04:44:23 475 2000-515.html
+02-29-2000 03:01:47 <DIR> 1998-515
+02-29-2000 03:01:47 <DIR> 2000-515
+05-12-2000 09:46:13 <DIR> zpfft
+10-27-2001 15:00:14 <DIR> psibound
+02-29-2000 03:01:51 398 anonftpd.html
+02-26-2002 03:34:22 <DIR> nistp224
+08-10-2001 09:27:20 <DIR> cdb
+05-01-2002 01:58:27 <DIR> talks
+12-23-2000 22:34:35 <DIR> ftpparse
+01-11-2000 06:50:10 <DIR> clockspeed
+02-29-2000 03:01:52 1350 clockspeed.html
+02-06-2002 21:52:34 <DIR> slashdoc
+06-07-2002 18:00:40 <DIR> export
+07-17-2001 03:48:36 <DIR> daemontools
+07-12-2001 23:17:08 2187 daemontools.html
+08-30-2001 22:51:16 175 data.html
+12-28-2001 02:32:37 1901 crypto.html
+11-11-2001 00:45:23 739 arith.html
+11-30-2001 04:48:09 2733 cdb.html
+11-11-2001 00:51:02 344 floatasm.html
+12-21-2000 22:25:56 <DIR> djbfft
+02-29-2000 03:01:52 1319 djbfft.html
+07-09-2000 19:16:47 <DIR> dnscache
+07-04-2000 00:57:44 4016 dnscache.html
+07-10-2001 05:16:22 <DIR> docs
+02-29-2000 03:01:52 293 docs.html
+02-29-2000 03:01:52 952 dot-forward.html
+01-11-2000 06:50:11 <DIR> etc-mta
+02-29-2000 03:01:52 3174 etc-mta.html
+02-29-2000 03:01:52 2990 ezmlm.html
+12-21-2000 22:25:56 <DIR> ftp
+02-29-2000 03:01:49 <DIR> im
+02-29-2000 03:01:52 1823 fastforward.html
+02-29-2000 03:01:52 1707 ftp.html
+02-12-2001 03:17:10 <DIR> freebugtraq
+06-02-2002 03:39:25 <DIR> hardware
+06-01-2001 04:57:35 610 1995-514.html
+12-21-2000 22:25:57 <DIR> hash127
+05-19-2000 04:29:02 4835 hash127.html
+02-29-2000 03:01:52 1515 im.html
+02-12-2002 21:40:06 <DIR> immhf
+04-25-2001 23:48:49 2902 immhf.html
+01-25-2001 06:58:36 <DIR> lib
+06-06-2001 01:45:50 <DIR> libtai
+07-10-2000 20:54:16 2120 libtai.html
+11-27-2001 18:52:40 14460 qmail.html
+08-30-2001 22:51:23 2153 mail.html
+02-29-2000 03:01:52 108 maildir.html
+02-29-2000 03:01:50 <DIR> maildisasters
+02-29-2000 03:01:52 873 maildisasters.html
+02-29-2000 03:01:52 1688 mess822.html
+02-25-2002 03:47:27 <DIR> mirror
+12-26-2001 22:02:32 581 ntheory.html
+06-03-2002 17:36:27 <DIR> papers
+05-21-2002 18:50:15 <DIR> postpropter
+01-11-2000 06:50:12 <DIR> postings
+01-11-2000 06:50:12 <DIR> primegen
+08-30-2001 22:51:33 415 precompiled.html
+02-29-2000 03:01:52 1121 primegen.html
+05-05-2002 03:37:55 <DIR> proto
+02-29-2000 03:01:52 452 proto.html
+07-10-2001 00:17:53 <DIR> publicfile
+11-30-2001 04:59:17 5651 publicfile.html
+08-30-2001 22:51:37 409 qlist.html
+04-02-2002 06:25:45 <DIR> qmail
+02-02-2002 06:52:28 7549 lists.html
+02-29-2000 03:01:52 1166 qmailanalog.html
+08-30-2001 22:51:39 1434 qmsmac.html
+03-13-2000 06:38:06 465 rblsmtpd.html
+02-29-2000 03:01:52 1225 rights.html
+01-11-2000 06:50:13 <DIR> sarcasm
+09-14-2001 04:34:14 1058 unix.html
+02-29-2000 03:01:53 1568 serialmail.html
+10-02-2000 21:13:44 840 sigs.html
+05-21-2002 18:50:08 <DIR> smtp
+04-26-2001 17:58:47 1723 smtp.html
+12-21-2000 22:26:03 <DIR> software
+02-29-2000 03:01:53 3671 softwarelaw.html
+01-11-2000 06:50:13 <DIR> sortedsums
+02-29-2000 03:01:53 2735 sortedsums.html
+02-26-2002 03:06:38 <DIR> speed
+07-04-2000 00:40:17 572 surveydns.html
+10-04-2001 02:59:31 <DIR> surveys
+10-04-2001 02:46:36 3503 surveys.html
+11-10-2000 06:58:08 <DIR> syncookies
+02-01-2002 03:03:37 7918 syncookies.html
+08-30-2001 22:51:43 1115 tcpcontrol.html
+03-18-2002 13:08:27 589 tcpip.html
+02-29-2000 03:01:53 906 thoughts.html
+07-30-2001 16:18:09 <DIR> threecubes
+09-14-2001 03:25:58 525 time.html
+05-22-2002 06:21:05 <DIR> ucspi-tcp
+01-25-2002 00:41:31 4086 ucspi-tcp.html
+08-30-2001 22:51:50 732 web.html
+07-04-2002 19:47:48 <DIR> www
+09-14-2001 03:26:08 2717 y2k.html
+02-08-2001 10:28:09 <DIR> dnsroot
+04-23-2001 08:01:37 2745 2001-260.html
+02-29-2000 03:01:53 291 zeroseek.html
+02-29-2000 03:01:53 <DIR> zmodexp
+05-19-2000 04:29:07 1513 zmodexp.html
+08-01-2000 03:08:54 <DIR> zmult
+08-01-2000 03:24:53 669 zmult.html
+12-23-2000 07:19:47 1097 checkpwd.html
+12-31-2001 19:47:16 2077 focus.html
+07-20-2000 01:11:31 3842 im2000.html
+07-04-2002 19:47:43 <DIR> slashcommand
+07-04-2002 19:47:44 <DIR> slashpackage
+07-16-2001 00:24:39 602 slashpackage.html
+05-03-2002 02:15:33 23874 talks.html
+05-08-2000 07:24:59 566 1997-275.html
+05-08-2000 07:31:04 313 1998-100.html
+02-29-2000 03:01:47 <DIR> 2000-436
+05-08-2000 07:37:26 660 1997-494.html
+05-08-2000 07:40:41 730 1999-541.html
+09-13-2000 09:08:58 2367 psibound.html
+06-22-2000 04:09:00 1866 smallfactors.html
+06-09-2000 03:35:19 <DIR> smallfactors
+07-02-2000 00:55:19 <DIR> conferences
+05-22-2002 07:52:29 <DIR> djbdns
+07-17-2001 06:00:58 2712 djbdns.html
+07-17-2000 03:15:39 216 zpfft.html
+08-20-2000 20:56:37 <DIR> fastnewton
+08-20-2000 20:57:31 333 fastnewton.html
+09-01-2000 20:33:51 <DIR> patents
+12-23-2000 22:40:17 1748 ftpparse.html
+11-11-2001 00:57:50 3261 slash.html
+01-17-2001 18:50:10 2663 slashdoc.html
+03-18-2002 10:04:35 2344 dnsroot.html
+12-26-2001 22:03:00 3238 software.html
+09-14-2001 04:34:33 3481 compatibility.html
+05-01-2002 05:30:34 5525 distributors.html
+02-25-2001 04:49:03 212 freebugtraq.html
+03-31-2002 04:59:50 806 hardware.html
+03-31-2001 08:15:18 121 securesoftware.html
+05-22-2002 04:39:56 10950 conferences.html
+11-30-2001 18:51:50 <DIR> 2001-275
+05-29-2001 02:15:07 459 rwb100.html
+10-03-2001 07:40:42 863 nistp224.html
+07-30-2001 16:15:46 778 threecubes.html
+06-03-2002 17:32:16 27125 papers.html
+11-21-2001 03:51:09 379 bib.html
+11-30-2001 18:41:33 3791 2001-275.html
+10-02-2001 20:08:59 169 dh224.html
+03-16-2002 07:05:36 1126 courses.html
+09-03-2001 00:22:28 355 slashcommand.html
+03-27-2002 22:20:22 1199 patents.html
+11-08-2001 20:27:15 640 mailcopyright.html
+06-02-2002 01:27:50 1257 djb.html
+01-07-2002 07:12:34 301 2002-501.html
+05-01-2002 04:41:45 1655 export.html
+03-24-2002 11:40:59 6446 index.html
+03-16-2002 07:09:08 570 2005-590.html
+03-16-2002 07:05:49 800 2004-494.html
+06-02-2002 01:28:59 4459 positions.html
+06-02-2002 00:55:31 466 contact.html
diff --git a/netwerk/streamconv/converters/parse-ftp/O-guess.in b/netwerk/streamconv/converters/parse-ftp/O-guess.in
new file mode 100644
index 000000000..4477a9d76
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/O-guess.in
@@ -0,0 +1,19 @@
+220 server IBM TCP/IP for OS/2 - FTP Server ver 23:04:36 on Jan 15 1997
+
+This listing is just a guess because I couldn't find an FTP server that
+LISTs like this. This guess is based on comments in Perl mirror project.
+I'm particularly unsure of the contents of cols 19-34.
+
+ 1 2 3 4 5 6
+0123456789012345678901234567890123456789012345678901234567890123456789
+----- size -------| ?????????????? MM-DD-YY| HH:MM| nnnnnnnnn....
+
+ 0 DIR 04-11-95 16:26 .
+ 0 DIR 04-11-95 16:26 ..
+ 0 DIR 04-11-95 16:26 ADDRESS
+ 612 A 07-28-95 16:45 air_tra1.bag
+ 195 A 08-09-95 10:23 Alfa1.bag
+ 0 DIR 04-11-95 16:26 ATTACH
+ 372 A 08-09-95 10:26 Aussie_1.bag
+ 310992 06-28-94 09:56 INSTALL.EXE
+ 12345 H 10-19-00 15:10 ADOE ADIR MOZILLA.FAKEOUT
diff --git a/netwerk/streamconv/converters/parse-ftp/O-guess.out b/netwerk/streamconv/converters/parse-ftp/O-guess.out
new file mode 100644
index 000000000..402f77b5b
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/O-guess.out
@@ -0,0 +1,13 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+04-11-1995 16:26:00 <DIR> .
+04-11-1995 16:26:00 <DIR> ..
+04-11-1995 16:26:00 <DIR> ADDRESS
+07-28-1995 16:45:00 612 air_tra1.bag
+08-09-1995 10:23:00 195 Alfa1.bag
+04-11-1995 16:26:00 <DIR> ATTACH
+08-09-1995 10:26:00 372 Aussie_1.bag
+06-28-1994 09:56:00 310992 INSTALL.EXE
+10-19-2000 15:10:00 12345 ADOE ADIR MOZILLA.FAKEOUT
diff --git a/netwerk/streamconv/converters/parse-ftp/R-dls.in b/netwerk/streamconv/converters/parse-ftp/R-dls.in
new file mode 100644
index 000000000..b472a00bc
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/R-dls.in
@@ -0,0 +1,23 @@
+README 763 Information about this server
+bin/ -
+etc/ =
+ls-lR 0
+ls-lR.Z 3
+pub/ = Public area
+usr/ -
+morgan 14 -> ../real/morgan
+TIMIT.mostlikely.Z
+ 79215
+README 763 Feb 3 18:21 Information about this server
+bin/ - Apr 28 1994
+etc/ = 11 Jul 21:04
+ls-lR 0 6 Aug 17:14
+ls-lR.Z 3 05 Sep 1994
+pub/ = Jul 11 21:04 Public area
+usr/ - Sep 7 09:39
+morgan 14 Apr 18 9:39 -> ../real/morgan
+TIMIT.mostlikely.Z
+ 79215 Jan 4 6:45
+
+*** CAUTION while editing this sample LISTing -
+*** Lines contain trailing whitespace and/or '\r's
diff --git a/netwerk/streamconv/converters/parse-ftp/R-dls.out b/netwerk/streamconv/converters/parse-ftp/R-dls.out
new file mode 100644
index 000000000..414f0320c
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/R-dls.out
@@ -0,0 +1,22 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+00-00-0000 00:00:00 763 README
+00-00-0000 00:00:00 <DIR> bin
+00-00-0000 00:00:00 <DIR> etc
+00-00-0000 00:00:00 0 ls-lR
+00-00-0000 00:00:00 3 ls-lR.Z
+00-00-0000 00:00:00 <DIR> pub
+00-00-0000 00:00:00 <DIR> usr
+00-00-0000 00:00:00 <JUNCTION> morgan -> ../real/morgan
+00-00-0000 00:00:00 79215 TIMIT.mostlikely.Z
+02-03-2002 18:21:00 763 README
+04-28-1994 00:00:00 <DIR> bin
+07-11-2002 21:04:00 <DIR> etc
+08-06-2001 17:14:00 0 ls-lR
+09-05-1994 00:00:00 3 ls-lR.Z
+07-11-2002 21:04:00 <DIR> pub
+09-07-2001 09:39:00 <DIR> usr
+04-18-2002 09:39:00 <JUNCTION> morgan -> ../real/morgan
+01-04-2002 06:45:00 79215 TIMIT.mostlikely.Z
diff --git a/netwerk/streamconv/converters/parse-ftp/README b/netwerk/streamconv/converters/parse-ftp/README
new file mode 100644
index 000000000..c49e28c70
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/README
@@ -0,0 +1,28 @@
+Testcases for the following:
+
+- VMS (MultiNet, UCX, and CMU) LIST format (including multi-line format)
+- IBM VM/CMS, VM/ESA LIST format (two known variants)
+- Windows NT's default "DOS-dirstyle"
+- OS/2 basic server format LIST format
+- SuperTCP FTP Server
+- NetManage Chameleon (NEWT)
+- EPLF (Easily Parsable List Format)
+- '/bin/dls' (two known variants, plus multi-line) LIST format
+- '/bin/ls -l' and all variants (even if they are not SYST UNIX)
+ including
+ - Hellsoft FTP for NetWare (non-unix perm-bits)
+ - Hethmon Brothers FTP for OS/2 (all '-' perm bits)
+ - NetPresenz (SYST is "MACOS")
+ - "NETWARE" (Hellsoft-style perms, no linkcount, no UID/GID)
+ - OpenBSD FTPD (numeric UID/GID)
+ - Open Group's FTP servers (no GID)
+ - Novonyx [Netscape/Novell] (fields not in columns)
+ - wuFTPd and other BSD-based ftpd that exec "ls -l"
+ - Windows NT server (internal "ls -l" compatible)
+ - Netmanage ProFTPD for Win32 (internal "ls -l" compatible)
+ - SurgeFTPd for Win32 (internal "ls -l" compatible)
+ - WarFTPd for Win32 (internal "ls -l" compatible)
+ - WebStarFTP for MacOS (internal "ls -l" compatible)
+ - MurkWorks FTP for NetWare (internal "ls -l" compatible)
+ - NcFTPd for Unix (internal "ls -l" compatible).
+
diff --git a/netwerk/streamconv/converters/parse-ftp/U-HellSoft.in b/netwerk/streamconv/converters/parse-ftp/U-HellSoft.in
new file mode 100644
index 000000000..50f03d664
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-HellSoft.in
@@ -0,0 +1,25 @@
+ftp> open pandora.anglistik.uni-mainz.de
+220 pandora FTP Server for NW 3.1x, 4.xx (v1.10), (c) 1994 HellSoft.
+Name (pandora.anglistik.uni-mainz.de:cyp):
+331 Password required.
+230-User Logged.
+230 Home Directory: /SYS/USER/FTP
+ftp> ls
+200 Command Accepted.
+150 Opening ASCII data connection.
+d[RWCEMFA] 1 cyp 512 Jul 01 11:49 htdocs
+d[RWCEMFA] 1 cyp 512 Jul 02 08:56 config
+d[RWCEMFA] 1 cyp 512 Jun 20 11:23 other
+d[RWCEMFA] 1 cyp 512 Jun 20 11:23 mail
+d[RWCEMFA] 1 cyp 512 Jun 20 14:35 news
+d[RWCEMFA] 1 cyp 512 Jun 30 08:48 download
+-[RWCEMFA] 1 *unknown 13312 May 27 1997 19calit.doc
+-[RWCEMFA] 1 *unknown 237 Feb 21 1997 forfile.bat
+-[RWCEMFA] 1 *unknown 1401 Mar 03 1997 intertex.txt
+d[RWCEMFA] 1 cyp 512 May 15 08:55 d1
+d[RWCEMFA] 1 cyp 512 May 06 10:57 drivers
+d[RWCEMFA] 1 cyp 512 Mar 28 12:05 --moved-
+226 Transfer complete.
+ftp> close
+221 Goodbye.
+ftp> \ No newline at end of file
diff --git a/netwerk/streamconv/converters/parse-ftp/U-HellSoft.out b/netwerk/streamconv/converters/parse-ftp/U-HellSoft.out
new file mode 100644
index 000000000..a42b16315
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-HellSoft.out
@@ -0,0 +1,16 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+07-01-2002 11:49:00 <DIR> htdocs
+07-02-2002 08:56:00 <DIR> config
+06-20-2002 11:23:00 <DIR> other
+06-20-2002 11:23:00 <DIR> mail
+06-20-2002 14:35:00 <DIR> news
+06-30-2002 08:48:00 <DIR> download
+05-27-1997 00:00:00 13312 19calit.doc
+02-21-1997 00:00:00 237 forfile.bat
+03-03-1997 00:00:00 1401 intertex.txt
+05-15-2002 08:55:00 <DIR> d1
+05-06-2002 10:57:00 <DIR> drivers
+03-28-2002 12:05:00 <DIR> --moved-
diff --git a/netwerk/streamconv/converters/parse-ftp/U-NetPresenz.in b/netwerk/streamconv/converters/parse-ftp/U-NetPresenz.in
new file mode 100644
index 000000000..1114ffe4b
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-NetPresenz.in
@@ -0,0 +1,31 @@
+ftp> open gean5.pfmb.uni-mb.si
+Connected to gean5.pfmb.uni-mb.si.
+220 NetPresenz v4.1 (Unregistered) awaits your command.
+Name (gean5.pfmb.uni-mb.si:cyp):
+331 Guest log in, send Email address (user@host) as password.
+230-This file must be in the Startup Messages folder in either the same
+ folder as NetPresenz or in the NetPresenz Preferences folder in the
+ Preferences folder, and will be displayed to guests user when they log
+ in. Guest users log in by using the username "ftp" or "anonymous".
+230 Anonymous login to 1 volumes. Access restrictions apply. "/Eng Dept web pages/MariborEnglishClub".
+Remote system type is MACOS.
+ftp> ls
+200 PORT command successful.
+150 ASCII transfer started.
+-------r-- 0 2166 2166 Mar 22 09:21 default.htm
+-------r-- 0 16504 16504 Mar 21 14:32 FAQs.htm
+drwxr-xr-x folder 5 Mar 22 10:06 FAQs_files
+-------r-- 0 250 250 Mar 22 09:22 filelist.xml
+-------r-- 0 1575 1575 Mar 21 14:22 image001.gif
+-------r-- 0 631827 631827 Mar 21 14:22 image002.jpg
+-------r-- 0 34318 34318 Mar 21 14:22 image003.jpg
+-------r-- 0 9121 9121 Mar 22 09:30 MariborEnglishClubHomepage.htm
+-------r-- 0 6710 6710 Mar 21 14:30 Photos.htm
+drwxr-xr-x folder 5 Mar 22 10:06 Photos_files
+-------r-- 0 5995 5995 Mar 22 09:23 TOCFrame.htm
+-------r-- 0 7226 7226 Mar 21 14:27 Upcoming Events.htm
+drwxr-xr-x folder 3 Mar 22 10:06 Upcoming Events_files
+226 Transfer complete.
+ftp>ftp> close
+221 Nice chatting with you.
+ftp> \ No newline at end of file
diff --git a/netwerk/streamconv/converters/parse-ftp/U-NetPresenz.out b/netwerk/streamconv/converters/parse-ftp/U-NetPresenz.out
new file mode 100644
index 000000000..754e0e3ca
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-NetPresenz.out
@@ -0,0 +1,17 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+03-22-2002 09:21:00 2166 default.htm
+03-21-2002 14:32:00 16504 FAQs.htm
+03-22-2002 10:06:00 <DIR> FAQs_files
+03-22-2002 09:22:00 250 filelist.xml
+03-21-2002 14:22:00 1575 image001.gif
+03-21-2002 14:22:00 631827 image002.jpg
+03-21-2002 14:22:00 34318 image003.jpg
+03-22-2002 09:30:00 9121 MariborEnglishClubHomepage.htm
+03-21-2002 14:30:00 6710 Photos.htm
+03-22-2002 10:06:00 <DIR> Photos_files
+03-22-2002 09:23:00 5995 TOCFrame.htm
+03-21-2002 14:27:00 7226 Upcoming Events.htm
+03-22-2002 10:06:00 <DIR> Upcoming Events_files
diff --git a/netwerk/streamconv/converters/parse-ftp/U-NetWare.in b/netwerk/streamconv/converters/parse-ftp/U-NetWare.in
new file mode 100644
index 000000000..c7252569e
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-NetWare.in
@@ -0,0 +1,51 @@
+ftp> open netlab2.usu.edu
+Connected to netlab2.usu.edu.
+220 Service Ready for new User
+Name (netlab2.usu.edu:cyp):
+331 Enter E-Mail id as Password
+230 User anonymous Logged in Successfully
+Remote system type is NETWARE.
+ftp> syst
+215 NETWARE Type : L8
+ftp> ls
+200 PORT Command OK
+150 Opening data connection
+total 0
+- [RWCEAFMS] NFAUUser 192 Apr 27 15:21 HEADER.html
+d [RWCEAFMS] jrd 512 Jul 11 03:01 allupdates
+d [RWCEAFMS] jrd 512 Dec 05 2001 apps
+d [RWCEAFMS] jrd 512 Oct 21 2001 bsuk00
+d [RWCEAFMS] jrd 512 Oct 21 2001 bsuk2001
+d [RWCEAFMS] jrd 512 Oct 21 2001 bsuk99
+d [RWCEAFMS] jrd 512 Oct 21 2001 bsus2000
+d [RWCEAFMS] jrd 512 Oct 21 2001 bsus2001
+d [RWCEAFMS] jrd 512 Mar 27 20:23 bsus2002
+d [RWCEAFMS] jrd 512 Oct 21 2001 bsus99
+d [RWCEAFMS] jrd 512 Oct 21 2001 drivers
+d [RWCEAFMS] jrd 512 Oct 24 2001 freebird
+d [RWCEAFMS] jrd 512 Apr 30 13:56 kermit
+d [RWCEAFMS] jrd 512 Oct 21 2001 macipx
+d [RWCEAFMS] jrd 512 Jun 13 01:45 misc
+d [RWCEAFMS] jrd 512 Oct 21 2001 netwatch
+d [RWCEAFMS] jrd 512 Oct 21 2001 netwire
+d [RWCEAFMS] jrd 512 Oct 21 2001 odi
+d [RWCEAFMS] jrd 512 Oct 21 2001 pktdrvr
+d [RWCEAFMS] jrd 512 Mar 02 20:23 rfc
+d [RWCEAFMS] jrd 512 Oct 30 2001 UnixWare
+d [RWCEAFMS] jrd 512 Oct 21 2001 updates
+- [RWCEAFMS] jrd 666258 Oct 30 1992 ENCAPS10.PS
+- [RWCEAFMS] jrd 25085 Oct 28 1992 ENCAPS10.TXT
+- [RWCEAFMS] jrd 611989 Jan 13 1993 ENCAPS11.PS
+- [RWCEAFMS] jrd 27134 Jan 12 1993 ENCAPS11.TXT
+- [RWCEAFMS] jrd 372 Jan 13 1993 README.TXT
+226 Transfer Complete
+ftp> site help
+214-Only DOS and LONG site commands are supported for Anonymous Users
+ DOS :
+ The DOS command shows the file/directory permissions in DOS format.
+ LONG :
+ The LONG command shows the file/directory permissions in LONG format.
+214 End of Help
+ftp> close
+221 Closing Session
+ftp> \ No newline at end of file
diff --git a/netwerk/streamconv/converters/parse-ftp/U-NetWare.out b/netwerk/streamconv/converters/parse-ftp/U-NetWare.out
new file mode 100644
index 000000000..6cf23ffb3
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-NetWare.out
@@ -0,0 +1,31 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+04-27-2002 15:21:00 192 HEADER.html
+07-11-2002 03:01:00 <DIR> allupdates
+12-05-2001 00:00:00 <DIR> apps
+10-21-2001 00:00:00 <DIR> bsuk00
+10-21-2001 00:00:00 <DIR> bsuk2001
+10-21-2001 00:00:00 <DIR> bsuk99
+10-21-2001 00:00:00 <DIR> bsus2000
+10-21-2001 00:00:00 <DIR> bsus2001
+03-27-2002 20:23:00 <DIR> bsus2002
+10-21-2001 00:00:00 <DIR> bsus99
+10-21-2001 00:00:00 <DIR> drivers
+10-24-2001 00:00:00 <DIR> freebird
+04-30-2002 13:56:00 <DIR> kermit
+10-21-2001 00:00:00 <DIR> macipx
+06-13-2002 01:45:00 <DIR> misc
+10-21-2001 00:00:00 <DIR> netwatch
+10-21-2001 00:00:00 <DIR> netwire
+10-21-2001 00:00:00 <DIR> odi
+10-21-2001 00:00:00 <DIR> pktdrvr
+03-02-2002 20:23:00 <DIR> rfc
+10-30-2001 00:00:00 <DIR> UnixWare
+10-21-2001 00:00:00 <DIR> updates
+10-30-1992 00:00:00 666258 ENCAPS10.PS
+10-28-1992 00:00:00 25085 ENCAPS10.TXT
+01-13-1993 00:00:00 611989 ENCAPS11.PS
+01-12-1993 00:00:00 27134 ENCAPS11.TXT
+01-13-1993 00:00:00 372 README.TXT
diff --git a/netwerk/streamconv/converters/parse-ftp/U-Novonyx.in b/netwerk/streamconv/converters/parse-ftp/U-Novonyx.in
new file mode 100644
index 000000000..e3de9474d
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-Novonyx.in
@@ -0,0 +1,92 @@
+ftp> open pandora.anglistik.uni-mainz.de
+220- Novonyx FTP Server for NetWare, v0.51 (9-16-98)
+220 Service Ready
+Name (pandora.anglistik.uni-mainz.de:cyp):
+331 User name okay, need password
+230 User logged in, proceed
+Remote system type is UNIX.
+Using binary mode to transfer files.
+ftp> cd login
+250 Directory successfully changed
+ftp> ls
+200 PORT Command OK
+150 File status OK, about to open data connection
+total 123
+-rw-rw-rw- 1 root sysadmin 25775 Sep 29 19:45 NOD$UPD.BAT
+-r--r--r-- 1 root sysadmin 2860 Feb 6 22:03 AX_RUN.OVL
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 B5DV_AIO.OVL
+-r--r--r-- 1 root sysadmin 7843 Feb 6 22:03 B5DV_RUN.OVL
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 B5ET_AIO.OVL
+-r--r--r-- 1 root sysadmin 5589 Feb 6 22:03 B5ET_RUN.OVL
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 B5KC_AIO.OVL
+-r--r--r-- 1 root sysadmin 5042 Feb 6 22:03 B5KC_RUN.OVL
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 BIG5_AIO.OVL
+-r--r--r-- 1 root sysadmin 3710 Feb 6 22:03 BIG5_RUN.OVL
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 CMPQ_AIO.OVL
+-r--r--r-- 1 root sysadmin 2815 Feb 6 22:03 CMPQ_RUN.OVL
+-r-xr-xr-x 1 root sysadmin 210009 Feb 6 22:03 CX.EXE
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 DOSV_AIO.OVL
+-r--r--r-- 1 root sysadmin 3825 Feb 6 22:03 DOSV_RUN.OVL
+-r--r--r-- 1 root sysadmin 16264 Feb 6 22:03 ETHER.RPL
+-r--r--r-- 1 root sysadmin 12133 Feb 6 22:03 F1ETH.RPL
+-r--r--r-- 1 root sysadmin 5141 Feb 6 22:03 FMR_AIO.OVL
+-r--r--r-- 1 root sysadmin 4747 Feb 6 22:03 FMR_RUN.OVL
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 GBCD_AIO.OVL
+-r--r--r-- 1 root sysadmin 3857 Feb 6 22:03 GBCD_RUN.OVL
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 GBET_AIO.OVL
+-r--r--r-- 1 root sysadmin 5545 Feb 6 22:03 GBET_RUN.OVL
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 GBLX_AIO.OVL
+-r--r--r-- 1 root sysadmin 3913 Feb 6 22:03 GBLX_RUN.OVL
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 GBPD_AIO.OVL
+-r--r--r-- 1 root sysadmin 8019 Feb 6 22:03 GBPD_RUN.OVL
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 GBSP_AIO.OVL
+-r--r--r-- 1 root sysadmin 8141 Feb 6 22:03 GBSP_RUN.OVL
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 GBTW_AIO.OVL
+-r--r--r-- 1 root sysadmin 4152 Feb 6 22:03 GBTW_RUN.OVL
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 GBUC_AIO.OVL
+-r--r--r-- 1 root sysadmin 4033 Feb 6 22:03 GBUC_RUN.OVL
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 GBWM_AIO.OVL
+-r--r--r-- 1 root sysadmin 3710 Feb 6 22:03 GBWM_RUN.OVL
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 GBXJ_AIO.OVL
+-r--r--r-- 1 root sysadmin 3848 Feb 6 22:03 GBXJ_RUN.OVL
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 GB_AIO.OVL
+-r--r--r-- 1 root sysadmin 3710 Feb 6 22:03 GB_RUN.OVL
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 IBM_AIO.OVL
+-r--r--r-- 1 root sysadmin 2815 Feb 6 22:03 IBM_RUN.OVL
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 J31_AIO.OVL
+-r--r--r-- 1 root sysadmin 5240 Feb 6 22:03 J31_RUN.OVL
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 KOR_AIO.OVL
+-r--r--r-- 1 root sysadmin 3710 Feb 6 22:03 KOR_RUN.OVL
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 KSC_AIO.OVL
+-r--r--r-- 1 root sysadmin 3710 Feb 6 22:03 KSC_RUN.OVL
+-r-xr-xr-x 1 root sysadmin 311171 Apr 4 14:19 LOGIN.EXE
+-r--r--r-- 1 root sysadmin 5167 Feb 6 22:03 PC98_AIO.OVL
+-r--r--r-- 1 root sysadmin 7152 Feb 6 22:03 PC98_RUN.OVL
+-r--r--r-- 1 root sysadmin 10991 Feb 6 22:03 PCN2L.RPL
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 PS55_AIO.OVL
+-r--r--r-- 1 root sysadmin 3616 Feb 6 22:03 PS55_RUN.OVL
+-r--r--r-- 1 root sysadmin 8074 Feb 6 22:03 RBOOT.RPL
+-r--r--r-- 1 root sysadmin 9170 Feb 6 22:03 TEXTUTIL.IDX
+-r--r--r-- 1 root sysadmin 18433 Feb 6 22:03 TOKEN.RPL
+-r-xr-xr-x 1 root sysadmin 43549 Feb 6 22:03 TYPEMSG.EXE
+-r--r--r-- 1 root sysadmin 27 Feb 6 22:03 ATTACH.BAT
+-rwxrwxrwx 1 root sysadmin 439913 Feb 6 23:33 NLIST.EXE
+-r--r--r-- 1 root sysadmin 307 Feb 6 22:03 MENU_X.BAT
+-rwxrwxrwx 1 root sysadmin 269247 Feb 6 23:33 MAP.EXE
+-r--r--r-- 1 root sysadmin 4965 Feb 6 22:03 AX_AIO.OVL
+-r-xr-xr-x 1 root sysadmin 111663 Apr 16 12:20 LOGIN3X.EXE
+-rw-rw-rw- 1 root sysadmin 38 Apr 18 15:19 login.nb
+-r-xr-xr-x 1 root sysadmin 392528 Apr 20 04:02 NPRINTER.EXE
+-r-xr-xr-x 1 root sysadmin 311171 Feb 9 16:29 LOGIN4X.EXE
+-rw-rw-rw- 1 root sysadmin 2102 Feb 8 13:18 lpt$cap.bat
+-rw-rw-rw- 1 root sysadmin 20614 Mar 13 13:42 nod$log.bat
+-rw-rw-rw- 1 root sysadmin 20450 Mar 12 10:36 nod$log.~ba
+drwxrwxrwx 1 root sysadmin 0 Mar 8 13:30 NLS
+drwxrwxrwx 1 root sysadmin 0 Mar 8 13:30 OS2
+drwxrwxrwx 1 root sysadmin 0 Apr 9 16:37 NOD$LOG.DRV
+drwxrwxrwx 1 root sysadmin 0 Apr 9 16:36 LOCAL
+drwxrwxrwx 1 root sysadmin 0 Mar 16 14:25 local.nt4
+226 Requested file action okay, completed
+ftp> close
+221 Service closing connection, user logged out
+ftp>
diff --git a/netwerk/streamconv/converters/parse-ftp/U-Novonyx.out b/netwerk/streamconv/converters/parse-ftp/U-Novonyx.out
new file mode 100644
index 000000000..8755d5fa7
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-Novonyx.out
@@ -0,0 +1,78 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+09-29-2001 19:45:00 25775 NOD$UPD.BAT
+02-06-2002 22:03:00 2860 AX_RUN.OVL
+02-06-2002 22:03:00 4965 B5DV_AIO.OVL
+02-06-2002 22:03:00 7843 B5DV_RUN.OVL
+02-06-2002 22:03:00 4965 B5ET_AIO.OVL
+02-06-2002 22:03:00 5589 B5ET_RUN.OVL
+02-06-2002 22:03:00 4965 B5KC_AIO.OVL
+02-06-2002 22:03:00 5042 B5KC_RUN.OVL
+02-06-2002 22:03:00 4965 BIG5_AIO.OVL
+02-06-2002 22:03:00 3710 BIG5_RUN.OVL
+02-06-2002 22:03:00 4965 CMPQ_AIO.OVL
+02-06-2002 22:03:00 2815 CMPQ_RUN.OVL
+02-06-2002 22:03:00 210009 CX.EXE
+02-06-2002 22:03:00 4965 DOSV_AIO.OVL
+02-06-2002 22:03:00 3825 DOSV_RUN.OVL
+02-06-2002 22:03:00 16264 ETHER.RPL
+02-06-2002 22:03:00 12133 F1ETH.RPL
+02-06-2002 22:03:00 5141 FMR_AIO.OVL
+02-06-2002 22:03:00 4747 FMR_RUN.OVL
+02-06-2002 22:03:00 4965 GBCD_AIO.OVL
+02-06-2002 22:03:00 3857 GBCD_RUN.OVL
+02-06-2002 22:03:00 4965 GBET_AIO.OVL
+02-06-2002 22:03:00 5545 GBET_RUN.OVL
+02-06-2002 22:03:00 4965 GBLX_AIO.OVL
+02-06-2002 22:03:00 3913 GBLX_RUN.OVL
+02-06-2002 22:03:00 4965 GBPD_AIO.OVL
+02-06-2002 22:03:00 8019 GBPD_RUN.OVL
+02-06-2002 22:03:00 4965 GBSP_AIO.OVL
+02-06-2002 22:03:00 8141 GBSP_RUN.OVL
+02-06-2002 22:03:00 4965 GBTW_AIO.OVL
+02-06-2002 22:03:00 4152 GBTW_RUN.OVL
+02-06-2002 22:03:00 4965 GBUC_AIO.OVL
+02-06-2002 22:03:00 4033 GBUC_RUN.OVL
+02-06-2002 22:03:00 4965 GBWM_AIO.OVL
+02-06-2002 22:03:00 3710 GBWM_RUN.OVL
+02-06-2002 22:03:00 4965 GBXJ_AIO.OVL
+02-06-2002 22:03:00 3848 GBXJ_RUN.OVL
+02-06-2002 22:03:00 4965 GB_AIO.OVL
+02-06-2002 22:03:00 3710 GB_RUN.OVL
+02-06-2002 22:03:00 4965 IBM_AIO.OVL
+02-06-2002 22:03:00 2815 IBM_RUN.OVL
+02-06-2002 22:03:00 4965 J31_AIO.OVL
+02-06-2002 22:03:00 5240 J31_RUN.OVL
+02-06-2002 22:03:00 4965 KOR_AIO.OVL
+02-06-2002 22:03:00 3710 KOR_RUN.OVL
+02-06-2002 22:03:00 4965 KSC_AIO.OVL
+02-06-2002 22:03:00 3710 KSC_RUN.OVL
+04-04-2002 14:19:00 311171 LOGIN.EXE
+02-06-2002 22:03:00 5167 PC98_AIO.OVL
+02-06-2002 22:03:00 7152 PC98_RUN.OVL
+02-06-2002 22:03:00 10991 PCN2L.RPL
+02-06-2002 22:03:00 4965 PS55_AIO.OVL
+02-06-2002 22:03:00 3616 PS55_RUN.OVL
+02-06-2002 22:03:00 8074 RBOOT.RPL
+02-06-2002 22:03:00 9170 TEXTUTIL.IDX
+02-06-2002 22:03:00 18433 TOKEN.RPL
+02-06-2002 22:03:00 43549 TYPEMSG.EXE
+02-06-2002 22:03:00 27 ATTACH.BAT
+02-06-2002 23:33:00 439913 NLIST.EXE
+02-06-2002 22:03:00 307 MENU_X.BAT
+02-06-2002 23:33:00 269247 MAP.EXE
+02-06-2002 22:03:00 4965 AX_AIO.OVL
+04-16-2002 12:20:00 111663 LOGIN3X.EXE
+04-18-2002 15:19:00 38 login.nb
+04-20-2002 04:02:00 392528 NPRINTER.EXE
+02-09-2002 16:29:00 311171 LOGIN4X.EXE
+02-08-2002 13:18:00 2102 lpt$cap.bat
+03-13-2002 13:42:00 20614 nod$log.bat
+03-12-2002 10:36:00 20450 nod$log.~ba
+03-08-2002 13:30:00 <DIR> NLS
+03-08-2002 13:30:00 <DIR> OS2
+04-09-2002 16:37:00 <DIR> NOD$LOG.DRV
+04-09-2002 16:36:00 <DIR> LOCAL
+03-16-2002 14:25:00 <DIR> local.nt4
diff --git a/netwerk/streamconv/converters/parse-ftp/U-Surge.in b/netwerk/streamconv/converters/parse-ftp/U-Surge.in
new file mode 100644
index 000000000..f1e096368
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-Surge.in
@@ -0,0 +1,66 @@
+ftp> open netwinsite.com
+Connected to netwinsite.com.
+220 SurgeFTP netwin1 (Version 2.1e)
+Name (netwinsite.com:cyp): 331 Guest login ok, send your complete e-mail address as password.
+230- Alias Real path Access
+230- / /disk2/ftp read
+230 User anonymous logged in.
+Remote system type is UNIX.
+Using binary mode to transfer files.
+ftp> cd pub
+250 CWD command successful now (/pub)
+ftp> ls
+200 PORT command successful.
+150 Opening ASCII mode data connection for file list. (/pub)
+drwxr-xr-x 2 jesseftp netwin 4096 Jul 7 21:37 cgimail
+drwxr-xr-x 4 dnewsftp netwin 4096 May 2 17:38 dbabble
+drwxr-xr-x 2 netwin netwin 4096 Jul 1 2001 dek_temp
+drwxr-xr-x 2 netwin netwin 4096 Jul 1 2001 deye
+drwxr-xr-x 2 jesseftp root 4096 Feb 18 17:50 dfree
+drwxr-xr-x 2 netwin netwin 4096 Jul 1 2001 dgate
+drwxr-xr-x 4 root root 4096 Jan 31 15:18 discontinued
+drwxr-xr-x 4 dmailftp netwin 8192 Jul 7 21:28 dmail
+drwxr-xr-x 4 pnftp netwin 4096 Jun 30 17:56 dmailweb
+drwxr-xr-x 8 dnewsftp netwin 8192 Jul 10 1:40 dnews
+drwxr-xr-x 3 netwin netwin 4096 Jul 1 2001 dnewsweb
+drwxr-xr-x 3 pnftp root 4096 Sep 4 2001 dnotice
+drwxr-xr-x 2 root root 4096 May 6 16:58 fengate
+drwxr-xr-x 2 pnftp root 4096 May 28 19:01 ferngate
+drwxr-xr-x 3 netwin netwin 4096 Jul 1 2001 jeeves
+drwxr-xr-x 2 netwin netwin 4096 Jun 27 20:10 misc
+drwxr-xr-x 3 pnftp bin 4096 Jul 4 21:13 netauth
+drwxr-xr-x 2 pnftp bin 4096 Feb 8 1999 poppassd
+drwxr-xr-x 2 jesseftp netwin 4096 Jul 9 1:39 surgeftp
+drwxr-xr-x 2 surgemail root 4096 Jul 3 0:00 surgemail
+drwxr-xr-x 2 surgemail root 4096 Jul 3 0:01 surgemail-enterprise
+drwxr-xr-x 2 surgemail root 4096 Jul 3 0:01 surgemail-home
+drwxr-xr-x 2 surgemail root 4096 Jul 3 0:01 surgemail-isp
+drwxr-xr-x 2 surgemail root 4096 Jul 3 0:01 surgemail-workplace
+drwxr-xr-x 3 netwin bin 4096 Jul 4 2001 watchdog
+drwxr-xr-x 3 pnftp bin 4096 Mar 21 2001 webimap
+drwxr-xr-x 3 pnftp root 4096 Apr 28 21:30 webmail
+drwxr-xr-x 3 pnftp bin 4096 Jun 30 18:23 webnews
+drwxr-xr-x 2 pnftp root 4096 Jan 30 20:31 webshareit
+drwxr-xr-x 2 netwin bin 4096 Sep 20 1999 webtwin
+drwxr-xr-x 4 pnftp root 4096 Jul 8 17:07 beta
+lrwxrwxrwx 1 pnftp pnftp 12 Mar 18 15:48 wmail.exe -> wmail30h.exe
+-rw-r--r-- 1 pnftp pnftp 2312192 Feb 19 15:33 wmail30h.exe
+-rw-r--r-- 1 pnftp pnftp 3360893 Feb 21 19:24 wmail30h_aix4.tar.Z
+-rw-r--r-- 1 pnftp pnftp 3508885 Mar 18 15:47 wmail30h_bsdi4.tar.Z
+-rw-r--r-- 1 pnftp pnftp 2693234 Feb 19 15:47 wmail30h_freebsd.tar.Z
+-rw-r--r-- 1 pnftp pnftp 2640047 Feb 19 15:38 wmail30h_freebsd3.tar.Z
+-rw-r--r-- 1 pnftp pnftp 2654381 Feb 19 15:43 wmail30h_freebsd4.tar.Z
+-rw-r--r-- 1 pnftp pnftp 3005333 Mar 18 18:21 wmail30h_hpux.tar.Z
+-rw-r--r-- 1 pnftp pnftp 2779942 Feb 19 15:52 wmail30h_linux.tar.Z
+-rw-r--r-- 1 pnftp pnftp 2782353 Feb 19 15:58 wmail30h_linuxlibc6.tar.Z
+-rw-r--r-- 1 pnftp pnftp 1783391 Feb 19 16:01 wmail30h_linuxppc.tar.gz
+-rw-r--r-- 1 pnftp pnftp 2758233 Mar 18 15:47 wmail30h_macosx_aqua.tar.Z
+-rw-r--r-- 1 pnftp pnftp 3113365 Mar 18 15:47 wmail30h_osf.tar.Z
+-rw-r--r-- 1 pnftp pnftp 1779720 Apr 28 21:30 wmail30h_raq3.tar.gz
+-rw-r--r-- 1 pnftp pnftp 1789173 Mar 11 16:38 wmail30h_raq4.tar.gz
+-rw-r--r-- 1 pnftp pnftp 2846045 Feb 19 16:06 wmail30h_solaris.tar.Z
+-rw-r--r-- 1 pnftp pnftp 2858946 Feb 19 16:11 wmail30h_solarisx86.tar.Z
+226 Transfer complete.
+ftp> close
+221 Closing connection - goodbye!
+ftp> \ No newline at end of file
diff --git a/netwerk/streamconv/converters/parse-ftp/U-Surge.out b/netwerk/streamconv/converters/parse-ftp/U-Surge.out
new file mode 100644
index 000000000..e6b652710
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-Surge.out
@@ -0,0 +1,52 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+07-07-2002 21:37:00 <DIR> cgimail
+05-02-2002 17:38:00 <DIR> dbabble
+07-01-2001 00:00:00 <DIR> dek_temp
+07-01-2001 00:00:00 <DIR> deye
+02-18-2002 17:50:00 <DIR> dfree
+07-01-2001 00:00:00 <DIR> dgate
+01-31-2002 15:18:00 <DIR> discontinued
+07-07-2002 21:28:00 <DIR> dmail
+06-30-2002 17:56:00 <DIR> dmailweb
+07-10-2002 01:40:00 <DIR> dnews
+07-01-2001 00:00:00 <DIR> dnewsweb
+09-04-2001 00:00:00 <DIR> dnotice
+05-06-2002 16:58:00 <DIR> fengate
+05-28-2002 19:01:00 <DIR> ferngate
+07-01-2001 00:00:00 <DIR> jeeves
+06-27-2002 20:10:00 <DIR> misc
+07-04-2002 21:13:00 <DIR> netauth
+02-08-1999 00:00:00 <DIR> poppassd
+07-09-2002 01:39:00 <DIR> surgeftp
+07-03-2002 00:00:00 <DIR> surgemail
+07-03-2002 00:01:00 <DIR> surgemail-enterprise
+07-03-2002 00:01:00 <DIR> surgemail-home
+07-03-2002 00:01:00 <DIR> surgemail-isp
+07-03-2002 00:01:00 <DIR> surgemail-workplace
+07-04-2001 00:00:00 <DIR> watchdog
+03-21-2001 00:00:00 <DIR> webimap
+04-28-2002 21:30:00 <DIR> webmail
+06-30-2002 18:23:00 <DIR> webnews
+01-30-2002 20:31:00 <DIR> webshareit
+09-20-1999 00:00:00 <DIR> webtwin
+07-08-2002 17:07:00 <DIR> beta
+03-18-2002 15:48:00 <JUNCTION> wmail.exe -> wmail30h.exe
+02-19-2002 15:33:00 2312192 wmail30h.exe
+02-21-2002 19:24:00 3360893 wmail30h_aix4.tar.Z
+03-18-2002 15:47:00 3508885 wmail30h_bsdi4.tar.Z
+02-19-2002 15:47:00 2693234 wmail30h_freebsd.tar.Z
+02-19-2002 15:38:00 2640047 wmail30h_freebsd3.tar.Z
+02-19-2002 15:43:00 2654381 wmail30h_freebsd4.tar.Z
+03-18-2002 18:21:00 3005333 wmail30h_hpux.tar.Z
+02-19-2002 15:52:00 2779942 wmail30h_linux.tar.Z
+02-19-2002 15:58:00 2782353 wmail30h_linuxlibc6.tar.Z
+02-19-2002 16:01:00 1783391 wmail30h_linuxppc.tar.gz
+03-18-2002 15:47:00 2758233 wmail30h_macosx_aqua.tar.Z
+03-18-2002 15:47:00 3113365 wmail30h_osf.tar.Z
+04-28-2002 21:30:00 1779720 wmail30h_raq3.tar.gz
+03-11-2002 16:38:00 1789173 wmail30h_raq4.tar.gz
+02-19-2002 16:06:00 2846045 wmail30h_solaris.tar.Z
+02-19-2002 16:11:00 2858946 wmail30h_solarisx86.tar.Z
diff --git a/netwerk/streamconv/converters/parse-ftp/U-WarFTPd.in b/netwerk/streamconv/converters/parse-ftp/U-WarFTPd.in
new file mode 100644
index 000000000..244c08709
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-WarFTPd.in
@@ -0,0 +1,38 @@
+ftp> open ftp.jgaa.com
+Connected to ftp.jgaa.com.
+220-Jgaa's official FTP server
+ WarFTPd 1.81.00 (Mar 3 2002) Ready
+ (C)opyright 1996 - 2002 by Jarle (jgaa) Aase - all rights reserved.
+220 Please enter your user name.
+Name (ftp.jgaa.com:cyp):
+230 User logged in.
+Remote system type is UNIX.
+Using binary mode to transfer files.
+ftp> passive
+Passive mode on.
+ftp> ls
+227 Entering Passive Mode (80,239,13,229,14,199)
+125 Using existing ASCII mode data connection for /bin/ls (1220 bytes).
+total 5127
+dr-xr--r-- 1 root root 0 Apr 22 2009 .
+dr-xr--r-- 1 root root 0 Apr 22 2009 ..
+-r-xr--r-- 1 root root 359807 Mar 13 2000 adns-0.6-win32-01.zip
+-r-xr--r-- 1 root root 77 Oct 17 2000 adns-0.6-win32-01.zip.md5
+-r-xr--r-- 1 root root 218767 Nov 11 2000 cfs-1.3.3-8bit-fix.r2.tgz
+-r-xr--r-- 1 root root 1606 Jun 13 2000 cfs-1.3.3-eight-bit-fix.diff.tar.gz
+-r-xr--r-- 1 root root 3327 Oct 19 2000 chkmailspool-1.0.tgz
+-r-xr--r-- 1 root root 9356 Oct 21 2000 chkmailspool-1.1.tgz
+-r-xr--r-- 1 root root 32742 Feb 1 2000 iisstat-1.2.zip
+-r-xr--r-- 1 root root 71 Oct 17 2000 iisstat-1.2.zip.md5
+-r-xr--r-- 1 root root 27531 Aug 14 1999 inshtml.zip
+-r-xr--r-- 1 root root 67 Oct 17 2000 inshtml.zip.md5
+-r-xr--r-- 1 root root 23780 Aug 14 1999 netcps.zip
+-r-xr--r-- 1 root root 66 Oct 17 2000 netcps.zip.md5
+-r-xr--r-- 1 root root 1057919 Nov 3 2001 openssl-0.9.6b-win32.zip
+-r-xr--r-- 1 root root 56823 Jan 28 2001 passgen-2.0.zip
+-r-xr--r-- 1 root root 826880 May 25 1997 warftpd-version2-public-source.zip
+-r-xr--r-- 1 root root 90 Oct 17 2000 warftpd-version2-public-source.zip.md5
+226 Transfer complete. 1220 bytes in 0.01 sec. (119.141 Kb/s)
+ftp> close
+221 Goodbye. Control connection closed.
+ftp> \ No newline at end of file
diff --git a/netwerk/streamconv/converters/parse-ftp/U-WarFTPd.out b/netwerk/streamconv/converters/parse-ftp/U-WarFTPd.out
new file mode 100644
index 000000000..b0a0bab43
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-WarFTPd.out
@@ -0,0 +1,22 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+04-22-2009 00:00:00 <DIR> .
+04-22-2009 00:00:00 <DIR> ..
+03-13-2000 00:00:00 359807 adns-0.6-win32-01.zip
+10-17-2000 00:00:00 77 adns-0.6-win32-01.zip.md5
+11-11-2000 00:00:00 218767 cfs-1.3.3-8bit-fix.r2.tgz
+06-13-2000 00:00:00 1606 cfs-1.3.3-eight-bit-fix.diff.tar.gz
+10-19-2000 00:00:00 3327 chkmailspool-1.0.tgz
+10-21-2000 00:00:00 9356 chkmailspool-1.1.tgz
+02-01-2000 00:00:00 32742 iisstat-1.2.zip
+10-17-2000 00:00:00 71 iisstat-1.2.zip.md5
+08-14-1999 00:00:00 27531 inshtml.zip
+10-17-2000 00:00:00 67 inshtml.zip.md5
+08-14-1999 00:00:00 23780 netcps.zip
+10-17-2000 00:00:00 66 netcps.zip.md5
+11-03-2001 00:00:00 1057919 openssl-0.9.6b-win32.zip
+01-28-2001 00:00:00 56823 passgen-2.0.zip
+05-25-1997 00:00:00 826880 warftpd-version2-public-source.zip
+10-17-2000 00:00:00 90 warftpd-version2-public-source.zip.md5
diff --git a/netwerk/streamconv/converters/parse-ftp/U-WebStar.in b/netwerk/streamconv/converters/parse-ftp/U-WebStar.in
new file mode 100644
index 000000000..4010d462e
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-WebStar.in
@@ -0,0 +1,41 @@
+ftp> open ftp.webstar.com
+Connected to ftp.webstar.com.
+220 FTP server ready.
+Name (ftp.webstar.com:cyp):
+331 Anonymous login OK, send login as password.
+230 User logged in.
+Remote system type is UNIX.
+ftp> pwd
+257 "/" is the current directory.
+ftp> syst
+215 UNIX WebSTAR FTP.
+ftp> cd products
+250 CWD OK, "/products".
+ftp> cd WebStar
+250 CWD OK, "/products/WebStar".
+ftp> cd Updates
+250 CWD OK, "/products/WebStar/Updates".
+ftp> ls
+200 PORT OK, IP address 134.93.247.34 port 49247
+150 Opening data connection.
+drwx------ 0 owner group 1 Jan 30 17:16 bundleup
+drwx------ 0 owner group 2 Nov 08 2001 docs
+drwx------ 0 owner group 12 Nov 08 2001 extending_webstar
+drwx------ 0 owner group 2 Apr 25 09:40 Products
+drwx------ 0 owner group 1 Jan 30 16:20 updates
+drwx------ 0 owner group 11 Jan 30 17:16 webstar_dev
+drwx------ 0 owner group 2 May 01 15:46 WebSTAR
+drwx------ 0 owner group 15 May 13 09:54 Installers
+drwx------ 0 owner group 8 Apr 25 09:59 Updates
+drwx------ 0 owner group 7 Apr 25 10:00 Plug-ins
+drwx------ 0 owner group 2 Apr 06 2001 SSL
+-rwx------ 0 owner group 1605421 Mar 30 2001 webstar1.3.2_updater.sea.hqx
+-rwx------ 0 owner group 6883859 Mar 30 2001 WebSTAR211installer.sea.hqx
+-rwx------ 0 owner group 7366223 Mar 30 2001 WebSTAR211updater.sea.hqx
+-rwx------ 0 owner group 13415184 Mar 30 2001 WebSTAR302updater.sea.hqx
+drwx------ 0 owner group 4 Apr 05 2001 WebSTAR_44
+drwx------ 0 owner group 2 Apr 25 10:00 WebSTAR_V
+226 Transfer complete.
+ftp> close
+221 Goodbye.
+ftp> \ No newline at end of file
diff --git a/netwerk/streamconv/converters/parse-ftp/U-WebStar.out b/netwerk/streamconv/converters/parse-ftp/U-WebStar.out
new file mode 100644
index 000000000..3a6720727
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-WebStar.out
@@ -0,0 +1,21 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+01-30-2002 17:16:00 <DIR> bundleup
+11-08-2001 00:00:00 <DIR> docs
+11-08-2001 00:00:00 <DIR> extending_webstar
+04-25-2002 09:40:00 <DIR> Products
+01-30-2002 16:20:00 <DIR> updates
+01-30-2002 17:16:00 <DIR> webstar_dev
+05-01-2002 15:46:00 <DIR> WebSTAR
+05-13-2002 09:54:00 <DIR> Installers
+04-25-2002 09:59:00 <DIR> Updates
+04-25-2002 10:00:00 <DIR> Plug-ins
+04-06-2001 00:00:00 <DIR> SSL
+03-30-2001 00:00:00 1605421 webstar1.3.2_updater.sea.hqx
+03-30-2001 00:00:00 6883859 WebSTAR211installer.sea.hqx
+03-30-2001 00:00:00 7366223 WebSTAR211updater.sea.hqx
+03-30-2001 00:00:00 13415184 WebSTAR302updater.sea.hqx
+04-05-2001 00:00:00 <DIR> WebSTAR_44
+04-25-2002 10:00:00 <DIR> WebSTAR_V
diff --git a/netwerk/streamconv/converters/parse-ftp/U-WinNT.in b/netwerk/streamconv/converters/parse-ftp/U-WinNT.in
new file mode 100644
index 000000000..a883fe0aa
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-WinNT.in
@@ -0,0 +1,68 @@
+ftp> open ftp.microsoft.com
+220 Microsoft FTP Service
+Name (ftp.microsoft.com:cyp):
+331 Anonymous access allowed, send identity (e-mail name) as password.
+230-This is FTP.Microsoft.Com
+230 Anonymous user logged in.
+Remote system type is Windows_NT.
+ftp> quote dirstyle
+200 MSDOS-like directory output is on
+ftp> quote dirstyle
+200 MSDOS-like directory output is off
+ftp> ls
+200 PORT command successful.
+150 Opening ASCII mode data connection for /bin/ls.
+dr-xr-xr-x 1 owner group 0 Feb 25 2000 channel
+dr-xr-xr-x 1 owner group 0 Feb 25 2000 Education
+dr-xr-xr-x 1 owner group 0 Feb 25 2000 enterprise
+dr-xr-xr-x 1 owner group 0 Jun 20 2001 ISN
+dr-xr-xr-x 1 owner group 0 May 31 2001 Museum
+dr-xr-xr-x 1 owner group 0 Feb 14 2001 TechNet
+dr-xr-xr-x 1 owner group 0 Oct 24 2001 whql
+dr-xr-xr-x 1 owner group 0 Feb 5 2001 20Year
+dr-xr-xr-x 1 owner group 0 Sep 26 2000 AccessFoxPro
+dr-xr-xr-x 1 owner group 0 Dec 21 2000 AlbGrp
+dr-xr-xr-x 1 owner group 0 May 31 2001 Alexandra
+dr-xr-xr-x 1 owner group 0 Jan 19 2001 anna
+dr-xr-xr-x 1 owner group 0 Apr 6 2000 anz
+dr-xr-xr-x 1 owner group 0 May 10 2000 Chase Bobko2
+dr-xr-xr-x 1 owner group 0 Mar 29 2000 cnn
+dr-xr-xr-x 1 owner group 0 Nov 21 2000 Darin
+dr-xr-xr-x 1 owner group 0 Mar 9 2000 digitalchicago
+dr-xr-xr-x 1 owner group 0 Sep 6 2000 Dublin
+dr-xr-xr-x 1 owner group 0 Jan 30 2001 eleanorf
+dr-xr-xr-x 1 owner group 0 Apr 26 2001 girvin
+dr-xr-xr-x 1 owner group 0 Apr 26 2000 Hires
+dr-xr-xr-x 1 owner group 0 Aug 15 2000 HR
+-r-xr-xr-x 1 owner group 4368384 Oct 24 1999 IMG00022.PCD
+dr-xr-xr-x 1 owner group 0 May 18 2001 jacubowsky
+dr-xr-xr-x 1 owner group 0 Oct 12 2000 JFalvey
+dr-xr-xr-x 1 owner group 0 Mar 28 2001 johnci
+dr-xr-xr-x 1 owner group 0 Jul 14 2000 Karin
+dr-xr-xr-x 1 owner group 0 Sep 7 2000 Kjung
+dr-xr-xr-x 1 owner group 0 Sep 28 2000 LarryE
+dr-xr-xr-x 1 owner group 0 Aug 17 2000 Larson
+dr-xr-xr-x 1 owner group 0 Sep 12 2000 marion
+dr-xr-xr-x 1 owner group 0 Aug 9 2000 ms25
+dr-xr-xr-x 1 owner group 0 Nov 16 2000 MS25Brochure
+dr-xr-xr-x 1 owner group 0 Mar 29 2000 MShistory
+dr-xr-xr-x 1 owner group 0 Sep 5 2000 Neils
+dr-xr-xr-x 1 owner group 0 Aug 2 2000 NLM
+dr-xr-xr-x 1 owner group 0 Sep 6 2000 PageOne
+dr-xr-xr-x 1 owner group 0 Jun 27 2000 pccomputing
+dr-xr-xr-x 1 owner group 0 May 9 2001 pictures
+dr-xr-xr-x 1 owner group 0 Jul 21 2000 pranks
+dr-xr-xr-x 1 owner group 0 Aug 22 2000 Sean
+dr-xr-xr-x 1 owner group 0 Aug 10 2000 SLeong
+dr-xr-xr-x 1 owner group 0 Sep 7 2000 svr
+dr-xr-xr-x 1 owner group 0 Jul 21 2000 Transcontinental
+dr-xr-xr-x 1 owner group 0 Oct 23 2000 veronist
+dr-xr-xr-x 1 owner group 0 Jun 15 2000 zoe
+-r-xr-xr-x 1 owner group 2094926 Jul 14 2000 canprankdesk.tif
+-r-xr-xr-x 1 owner group 95077 Jul 21 2000 Jon Kauffman Enjoys the Good Life.jpg
+-r-xr-xr-x 1 owner group 52275 Jul 21 2000 Name Plate.jpg
+-r-xr-xr-x 1 owner group 2250540 Jul 14 2000 Valentineoffprank-HiRes.jpg
+226 Transfer complete.
+ftp> close
+221 Thank-You For Using Microsoft Products!
+ftp>
diff --git a/netwerk/streamconv/converters/parse-ftp/U-WinNT.out b/netwerk/streamconv/converters/parse-ftp/U-WinNT.out
new file mode 100644
index 000000000..857f80c3f
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-WinNT.out
@@ -0,0 +1,72 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+cmnt: ftp> open ftp.microsoft.com
+cmnt: Microsoft FTP Service
+cmnt: Name (ftp.microsoft.com:cyp):
+cmnt: 331 Anonymous access allowed, send identity (e-mail name) as password.
+cmnt: 230-This is FTP.Microsoft.Com
+cmnt: Anonymous user logged in.
+cmnt: Remote system type is Windows_NT.
+cmnt: ftp> quote dirstyle
+cmnt: MSDOS-like directory output is on
+cmnt: ftp> quote dirstyle
+cmnt: MSDOS-like directory output is off
+cmnt: ftp> ls
+cmnt: PORT command successful.
+cmnt: Opening ASCII mode data connection for /bin/ls.
+list: 02-25-00 00:00AM <DIR> channel
+list: 02-25-00 00:00AM <DIR> Education
+list: 02-25-00 00:00AM <DIR> enterprise
+list: 06-20-01 00:00AM <DIR> ISN
+list: 05-31-01 00:00AM <DIR> Museum
+list: 02-14-01 00:00AM <DIR> TechNet
+list: 10-24-01 00:00AM <DIR> whql
+list: 02-05-01 00:00AM <DIR> 20Year
+list: 09-26-00 00:00AM <DIR> AccessFoxPro
+list: 12-21-00 00:00AM <DIR> AlbGrp
+list: 05-31-01 00:00AM <DIR> Alexandra
+list: 01-19-01 00:00AM <DIR> anna
+list: 04-06-00 00:00AM <DIR> anz
+list: 05-10-00 00:00AM <DIR> Chase Bobko2
+list: 03-29-00 00:00AM <DIR> cnn
+list: 11-21-00 00:00AM <DIR> Darin
+list: 03-09-00 00:00AM <DIR> digitalchicago
+list: 09-06-00 00:00AM <DIR> Dublin
+list: 01-30-01 00:00AM <DIR> eleanorf
+list: 04-26-01 00:00AM <DIR> girvin
+list: 04-26-00 00:00AM <DIR> Hires
+list: 08-15-00 00:00AM <DIR> HR
+list: 10-24-99 00:00AM 4368384 IMG00022.PCD
+list: 05-18-01 00:00AM <DIR> jacubowsky
+list: 10-12-00 00:00AM <DIR> JFalvey
+list: 03-28-01 00:00AM <DIR> johnci
+list: 07-14-00 00:00AM <DIR> Karin
+list: 09-07-00 00:00AM <DIR> Kjung
+list: 09-28-00 00:00AM <DIR> LarryE
+list: 08-17-00 00:00AM <DIR> Larson
+list: 09-12-00 00:00AM <DIR> marion
+list: 08-09-00 00:00AM <DIR> ms25
+list: 11-16-00 00:00AM <DIR> MS25Brochure
+list: 03-29-00 00:00AM <DIR> MShistory
+list: 09-05-00 00:00AM <DIR> Neils
+list: 08-02-00 00:00AM <DIR> NLM
+list: 09-06-00 00:00AM <DIR> PageOne
+list: 06-27-00 00:00AM <DIR> pccomputing
+list: 05-09-01 00:00AM <DIR> pictures
+list: 07-21-00 00:00AM <DIR> pranks
+list: 08-22-00 00:00AM <DIR> Sean
+list: 08-10-00 00:00AM <DIR> SLeong
+list: 09-07-00 00:00AM <DIR> svr
+list: 07-21-00 00:00AM <DIR> Transcontinental
+list: 10-23-00 00:00AM <DIR> veronist
+list: 06-15-00 00:00AM <DIR> zoe
+list: 07-14-00 00:00AM 2094926 canprankdesk.tif
+list: 07-21-00 00:00AM 95077 Jon Kauffman Enjoys the Good Life.jpg
+list: 07-21-00 00:00AM 52275 Name Plate.jpg
+list: 07-14-00 00:00AM 2250540 Valentineoffprank-HiRes.jpg
+junk: Transfer complete.
+junk: ftp> close
+junk: Thank-You For Using Microsoft Products!
+junk: ftp>
diff --git a/netwerk/streamconv/converters/parse-ftp/U-hethmon.in b/netwerk/streamconv/converters/parse-ftp/U-hethmon.in
new file mode 100644
index 000000000..2c9887cdb
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-hethmon.in
@@ -0,0 +1,42 @@
+ftp> open ftp.hethmon.com
+Connected to ftp.hethmon.com.
+220 Hethmon Brothers FTP Server for OS/2 ** BETA 2.0 **. Ready for new user.
+Name (ftp.hethmon.com:cyp):
+331 Guest logins allowed. Email address required for anonymous.
+230 User foo@bar.com logged in.
+Remote system type is UNIX.
+ftp> cd pub
+250 Directory changed to "/pub"
+ftp> ls
+200 Port command ok
+150 Opening ASCII mode data connection.
+d--x------ 1 ftp ftp 5 Mar 21 1999 ..
+d--x------ 1 ftp ftp 0 Feb 16 2002 beta
+---------- 1 ftp ftp 35573 May 5 2000 CheckQ2.zip
+---------- 1 ftp ftp 1550521 May 5 2000 Ftpd106.zip
+---------- 1 ftp ftp 35459 Feb 7 2001 hmailbox.zip
+---------- 1 ftp ftp 55463 May 5 2000 HRxMail.zip
+---------- 1 ftp ftp 34950 May 5 2000 HRxPass.zip
+---------- 1 ftp ftp 1320184 May 5 2000 inetmail-1.2.1.pro.zip
+---------- 1 ftp ftp 1218483 May 5 2000 inetmail-1.2.1.zip
+---------- 1 ftp ftp 1615428 May 5 2000 inetmail-1.3.0.pro.zip
+---------- 1 ftp ftp 1425567 May 5 2000 inetmail-1.3.0.zip
+---------- 1 ftp ftp 1629145 Jan 9 2001 inetmail-1.3.18.zip
+---------- 1 ftp ftp 1625314 Feb 7 2001 inetmail-1.3.18a.zip
+---------- 1 ftp ftp 1407069 May 5 2000 inetmail-1.5.0.pro.zip
+---------- 1 ftp ftp 1470338 Sep 27 2000 inetmail-1.5.31.pro.zip
+---------- 1 ftp ftp 1583435 Jan 4 2001 inetmail-1.5.32.pro.zip
+---------- 1 ftp ftp 1429364 May 5 2000 inetmail-1.5.5.pro.zip
+---------- 1 ftp ftp 1471373 May 5 2000 inetmail-1.5.6.pro.zip
+d--x------ 1 ftp ftp 0 Feb 8 2001 misc
+---------- 1 ftp ftp 30913 May 5 2000 MXLookup.zip
+d--x------ 1 ftp ftp 0 May 2 2002 perseus
+d--x------ 1 ftp ftp 0 Feb 8 2001 rfcs
+d--x------ 1 ftp ftp 0 Feb 8 2001 scripts
+d--x------ 1 ftp ftp 0 Feb 8 2001 tcpip
+d--x------ 1 ftp ftp 0 May 5 2000 testcase
+d--x------ 1 ftp ftp 0 Feb 7 2001 tools
+226 Data transfer complete
+ftp> close
+221 Service closing control connection.
+ftp> \ No newline at end of file
diff --git a/netwerk/streamconv/converters/parse-ftp/U-hethmon.out b/netwerk/streamconv/converters/parse-ftp/U-hethmon.out
new file mode 100644
index 000000000..dada16879
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-hethmon.out
@@ -0,0 +1,30 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+03-21-1999 00:00:00 <DIR> ..
+02-16-2002 00:00:00 <DIR> beta
+05-05-2000 00:00:00 35573 CheckQ2.zip
+05-05-2000 00:00:00 1550521 Ftpd106.zip
+02-07-2001 00:00:00 35459 hmailbox.zip
+05-05-2000 00:00:00 55463 HRxMail.zip
+05-05-2000 00:00:00 34950 HRxPass.zip
+05-05-2000 00:00:00 1320184 inetmail-1.2.1.pro.zip
+05-05-2000 00:00:00 1218483 inetmail-1.2.1.zip
+05-05-2000 00:00:00 1615428 inetmail-1.3.0.pro.zip
+05-05-2000 00:00:00 1425567 inetmail-1.3.0.zip
+01-09-2001 00:00:00 1629145 inetmail-1.3.18.zip
+02-07-2001 00:00:00 1625314 inetmail-1.3.18a.zip
+05-05-2000 00:00:00 1407069 inetmail-1.5.0.pro.zip
+09-27-2000 00:00:00 1470338 inetmail-1.5.31.pro.zip
+01-04-2001 00:00:00 1583435 inetmail-1.5.32.pro.zip
+05-05-2000 00:00:00 1429364 inetmail-1.5.5.pro.zip
+05-05-2000 00:00:00 1471373 inetmail-1.5.6.pro.zip
+02-08-2001 00:00:00 <DIR> misc
+05-05-2000 00:00:00 30913 MXLookup.zip
+05-02-2002 00:00:00 <DIR> perseus
+02-08-2001 00:00:00 <DIR> rfcs
+02-08-2001 00:00:00 <DIR> scripts
+02-08-2001 00:00:00 <DIR> tcpip
+05-05-2000 00:00:00 <DIR> testcase
+02-07-2001 00:00:00 <DIR> tools
diff --git a/netwerk/streamconv/converters/parse-ftp/U-murksw.in b/netwerk/streamconv/converters/parse-ftp/U-murksw.in
new file mode 100644
index 000000000..0d5786cf2
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-murksw.in
@@ -0,0 +1,29 @@
+ftp> open tui.lincoln.ac.nz
+Connected to tui.lincoln.ac.nz.
+220 tui.lincoln.ac.nz Novell NetWare FTP Server (V1.80), Copyright (C) 1992-2000 MurkWorks Inc.
+Name (tui.lincoln.ac.nz:cyp): 331 Anonymous Login OK, send id as password.
+230-User logged in, Max Connect time 600 minutes (READONLY)
+230 Current Directory : /
+Remote system type is UNIX.
+Using binary mode to transfer files.
+ftp> ls
+200 Command Accepted
+150 Opening connection for ASCII transfer
+-rwx---r-- 1 anonymou other 1445 Apr 28 1994 ANON.DAT
+-rwx---r-- 1 mcnaughp other 83 Apr 18 09:39 Copy of LABSPACE.SUM
+drwx---r-x 2 anonymou other 512 Jul 11 21:04 JRBUTILS
+-rwx---r-- 1 labspace other 91 Jul 13 02:04 LABSPACE.SUM
+drwx---r-x 2 anonymou other 512 Jul 11 21:04 MAINT
+drwx---r-x 2 anonymou other 512 Jul 11 21:04 MISC
+drwx---r-x 2 anonymou other 512 Jul 11 21:04 PCOUNTER
+drwx---r-x 2 helleupp other 512 Jul 11 21:05 PEGASUS
+-rwx---r-- 1 anonymou other 13662 Aug 6 17:14 VOL$LOG.ERR
+-rwx---r-- 1 anonymou other 27945 Sep 5 1994 WHATIS.MSC
+226 Transfer complete
+ftp> pwd
+257 "/" is the current directory
+ftp> syst
+215 UNIX Type: L8 Version: NetWare MurkWorks, Inc. 1.80
+ftp> close
+221 Goodbye.
+ftp> \ No newline at end of file
diff --git a/netwerk/streamconv/converters/parse-ftp/U-murksw.out b/netwerk/streamconv/converters/parse-ftp/U-murksw.out
new file mode 100644
index 000000000..68ff9448e
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-murksw.out
@@ -0,0 +1,14 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+04-28-1994 00:00:00 1445 ANON.DAT
+04-18-2002 09:39:00 83 Copy of LABSPACE.SUM
+07-11-2002 21:04:00 <DIR> JRBUTILS
+07-13-2002 02:04:00 91 LABSPACE.SUM
+07-11-2002 21:04:00 <DIR> MAINT
+07-11-2002 21:04:00 <DIR> MISC
+07-11-2002 21:04:00 <DIR> PCOUNTER
+07-11-2002 21:05:00 <DIR> PEGASUS
+08-06-2001 17:14:00 13662 VOL$LOG.ERR
+09-05-1994 00:00:00 27945 WHATIS.MSC
diff --git a/netwerk/streamconv/converters/parse-ftp/U-ncFTPd.in b/netwerk/streamconv/converters/parse-ftp/U-ncFTPd.in
new file mode 100644
index 000000000..635f55642
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-ncFTPd.in
@@ -0,0 +1,1411 @@
+ftp> ftp ftp.novell.com
+Connected to kmpec.provo.novell.com.
+220 ftp.novell.com NcFTPd Server (licensed copy) ready.
+Name (ftp.novell.com:cyp):
+331 Guest login ok, send your complete e-mail address as password.
+230-You are user #18 of 400 simultaneous users allowed.
+230-
+230-This content is also available via HTTP at http://ftp.novell.com
+230-
+230-Other FTP mirror sites of ftp.novell.com are:
+230-ftp2.novell.com (United States)
+230-ftp3.novell.com (United States)
+230-ftp.novell.com.au (Australia)
+230-ftp.novell.de (Germany)
+230-ftp.novell.co.jp (Japan)
+230-ftp.novell.nl (Netherlands)
+230-
+230-World Wide Web Novell Support sites:
+230-http://support.novell.com (United States)
+230-http://support.novell.com.au (Australia)
+230-http://support.novell.de (Germany)
+230-http://support.novell.co.jp (Japan)
+230-
+230-webmaster@novell.com
+230-
+230 Logged in anonymously.
+Remote system type is UNIX.
+Using binary mode to transfer files.
+ftp> syst
+215 UNIX Type: L8
+ftp> ls
+200 PORT command successful.
+150 Opening ASCII mode data connection for /bin/ls.
+-rw-r--r-- 1 ftpuser ftpusers 2419 Jan 1 1997 Readme
+drwxrwxrwx 2 ftpuser ftpusers 8192 Jul 10 11:03 incoming
+drwxr-x--x 2 ftpuser ftpusers 4096 Jul 10 10:18 outgoing
+drwxr-xr-x 2 ftpuser ftpusers 4096 May 10 10:16 priv
+drwxr-xr-x 5 ftpuser ftpusers 4096 Jul 10 08:12 pub
+drwxr-xr-x 2 ftpuser ftpusers 28672 Jul 8 19:20 allupdates
+drwxr-xr-x 4 ftpuser ftpusers 4096 Jan 1 1997 netwire
+drwxr-xr-x 2 ftpuser ftpusers 4096 Jul 9 19:20 support
+lrwxrwxrwx 1 ftpuser ftpusers 10 Jan 10 2002 updates -> allupdates
+-rw-r--r-- 1 ftpuser ftpusers 19448 Jul 27 1999 0dsb.exe
+-rw-r--r-- 1 ftpuser ftpusers 49351 Sep 17 1993 215mir.exe
+-rw-r--r-- 1 ftpuser ftpusers 32586 Sep 17 1993 215sec.exe
+-rw-r--r-- 1 ftpuser ftpusers 136344 Sep 17 1993 21fix.exe
+-rw-r--r-- 1 ftpuser ftpusers 57276 Sep 17 1993 223200.exe
+-rw-r--r-- 1 ftpuser ftpusers 119616 Nov 1 1995 22bkup.exe
+-rw-r--r-- 1 ftpuser ftpusers 19820 Oct 13 1995 22dos5.exe
+-rw-r--r-- 1 ftpuser ftpusers 32980 Nov 1 1995 22nd2f.exe
+-rw-r--r-- 1 ftpuser ftpusers 92151 May 9 11:30 236779.exe
+-rw-r--r-- 1 ftpuser ftpusers 273958 Jan 17 2001 242234.exe
+-rw-r--r-- 1 ftpuser ftpusers 283462 Jul 10 2001 243798.exe
+-rw-r--r-- 1 ftpuser ftpusers 160893 Dec 18 2001 251000.exe
+-rw-r--r-- 1 ftpuser ftpusers 205531 Dec 18 2001 252143.exe
+-rw-r--r-- 1 ftpuser ftpusers 183262 Dec 18 2001 253720.exe
+-rw-r--r-- 1 ftpuser ftpusers 231638 Nov 6 2001 260624.exe
+-rw-r--r-- 1 ftpuser ftpusers 250545 Jun 21 2001 264837.exe
+-rw-r--r-- 1 ftpuser ftpusers 589722 Feb 21 16:33 265058a.exe
+-rw-r--r-- 1 ftpuser ftpusers 336586 Nov 7 2001 269308.exe
+-rw-r--r-- 1 ftpuser ftpusers 345275 Nov 6 2001 270050.exe
+-rw-r--r-- 1 ftpuser ftpusers 103027 Nov 6 2001 270410.exe
+-rw-r--r-- 1 ftpuser ftpusers 341460 May 9 07:13 275382.exe
+-rw-r--r-- 1 ftpuser ftpusers 365835 May 9 11:23 275436.exe
+-rw-r--r-- 1 ftpuser ftpusers 230063 Oct 9 2001 275520.exe
+-rw-r--r-- 1 ftpuser ftpusers 285953 Oct 2 2001 275820.exe
+-rw-r--r-- 1 ftpuser ftpusers 156517 Nov 16 2001 277412.exe
+-rw-r--r-- 1 ftpuser ftpusers 839272 Dec 19 2001 278415.exe
+-rw-r--r-- 1 ftpuser ftpusers 130983 Dec 19 2001 282848.exe
+-rw-r--r-- 1 ftpuser ftpusers 61891 Sep 17 1993 286dwn.exe
+-rw-r--r-- 1 ftpuser ftpusers 136529 May 9 07:18 290254.exe
+-rw-r--r-- 1 ftpuser ftpusers 96694 Apr 12 17:07 290261.exe
+-rw-r--r-- 1 ftpuser ftpusers 230377 May 9 07:22 291158.exe
+-rw-r--r-- 1 ftpuser ftpusers 114329 Jun 27 12:20 295137.exe
+-rw-r--r-- 1 ftpuser ftpusers 84885 Sep 17 1993 2xto3x.exe
+-rw-r--r-- 1 ftpuser ftpusers 60861 Sep 17 1993 300pt1.exe
+-rw-r--r-- 1 ftpuser ftpusers 180279 Sep 17 1993 310pt1.exe
+-rw-r--r-- 1 ftpuser ftpusers 178076 Nov 11 1996 311ptg.exe
+-rw-r--r-- 1 ftpuser ftpusers 188572 Apr 29 1996 312du1.exe
+-rw-r--r-- 1 ftpuser ftpusers 168258 Mar 18 1998 312ptd.exe
+-rw-r--r-- 1 ftpuser ftpusers 436629 Aug 25 1999 312y2kp2.exe
+-rw-r--r-- 1 ftpuser ftpusers 2365264 Jun 29 2001 33sp3.exe
+-rw-r--r-- 1 ftpuser ftpusers 28881 Sep 17 1993 386dcb.exe
+-rw-r--r-- 1 ftpuser ftpusers 33111 Sep 17 1993 3cboot.exe
+-rw-r--r-- 1 ftpuser ftpusers 27583 Nov 10 1995 400pt1.exe
+-rw-r--r-- 1 ftpuser ftpusers 79295 Oct 23 1995 401pt6.exe
+-rw-r--r-- 1 ftpuser ftpusers 42873 Aug 26 1994 402pa1.exe
+-rw-r--r-- 1 ftpuser ftpusers 50737 Mar 28 1995 402pt1.exe
+-rw-r--r-- 1 ftpuser ftpusers 548398 Jun 8 1998 410pt8b.exe
+-rw-r--r-- 1 ftpuser ftpusers 285471 Aug 25 1999 410y2kp2.exe
+-rw-r--r-- 1 ftpuser ftpusers 538544 Jul 23 1999 411y2kp2.exe
+-rw-r--r-- 1 ftpuser ftpusers 370469 Apr 29 1996 41filr.exe
+-rw-r--r-- 1 ftpuser ftpusers 58965 Jan 2 1997 41migutl.exe
+-rw-r--r-- 1 ftpuser ftpusers 173978 Aug 29 1995 41ndir.exe
+-rw-r--r-- 1 ftpuser ftpusers 42101 Nov 24 1997 41rem1.exe
+-rw-r--r-- 1 ftpuser ftpusers 855292 Jul 9 1996 41rtr2.exe
+-rw-r--r-- 1 ftpuser ftpusers 212785 Jul 23 1999 42y2kp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 3043701 Jul 3 2001 48sp3.exe
+-rw-r--r-- 1 ftpuser ftpusers 308856 May 22 2001 4pent.exe
+-rw-r--r-- 1 ftpuser ftpusers 1072023 Apr 6 1998 4xmigr2.exe
+-rw-r--r-- 1 ftpuser ftpusers 125457 Nov 17 1995 4xrep1.exe
+-rw-r--r-- 1 ftpuser ftpusers 29001 Jul 6 1994 50z70.exe
+-rw-r--r-- 1 ftpuser ftpusers 23248 Nov 1 1995 55sx60.exe
+-rw-r--r-- 1 ftpuser ftpusers 647818 Dec 4 1998 95220p1.exe
+-rw-r--r-- 1 ftpuser ftpusers 905243 Mar 25 1999 95250p2.exe
+-rw-r--r-- 1 ftpuser ftpusers 694344 Jun 21 1999 9530p1.exe
+-rw-r--r-- 1 ftpuser ftpusers 794454 Jun 13 2000 9531pt2.exe
+-rw-r--r-- 1 ftpuser ftpusers 4380134 Oct 3 1999 9531sp2.exe
+-rw-r--r-- 1 ftpuser ftpusers 1306298 Nov 16 2000 95321pt5.exe
+-rw-r--r-- 1 ftpuser ftpusers 494394 Jun 13 2000 9532pt3.exe
+-rw-r--r-- 1 ftpuser ftpusers 483405 Nov 6 2001 95331pt1.exe
+-rw-r--r-- 1 ftpuser ftpusers 19588899 Jun 2 2000 a526aix.z
+-rw-r--r-- 1 ftpuser ftpusers 17196628 Jun 2 2000 a526hp.z
+-rw-r--r-- 1 ftpuser ftpusers 14813432 Jun 2 2000 a526sol.z
+-rw-r--r-- 1 ftpuser ftpusers 238005 Jul 9 1999 accupg1b.exe
+-rw-r--r-- 1 ftpuser ftpusers 19472 Sep 17 1993 aceclp.exe
+-rw-r--r-- 1 ftpuser ftpusers 2061142 Jun 19 2001 acmgtcl.exe
+-rw-r--r-- 1 ftpuser ftpusers 52792 Dec 17 1996 actkey.exe
+-rw-r--r-- 1 ftpuser ftpusers 1026928 Nov 8 1996 adde1.exe
+-rw-r--r-- 1 ftpuser ftpusers 476094 Sep 10 1997 adm32_22.exe
+-rw-r--r-- 1 ftpuser ftpusers 4204451 Jan 10 1997 adm4113x.exe
+-rw-r--r-- 1 ftpuser ftpusers 3813257 Jan 10 1997 adm41195.exe
+-rw-r--r-- 1 ftpuser ftpusers 5377426 Jan 10 1997 adm411nt.exe
+-rw-r--r-- 1 ftpuser ftpusers 130826 May 23 2001 admattrs.exe
+-rw-r--r-- 1 ftpuser ftpusers 3291925 May 23 2001 admn519f.exe
+-rw-r--r-- 1 ftpuser ftpusers 273404 Jul 15 1997 adtus3.exe
+-rw-r--r-- 1 ftpuser ftpusers 25475 Sep 17 1993 afix1.exe
+-rw-r--r-- 1 ftpuser ftpusers 25929 Sep 17 1993 afix2.exe
+-rw-r--r-- 1 ftpuser ftpusers 26184 Sep 17 1993 afix4.exe
+-rw-r--r-- 1 ftpuser ftpusers 116034 Apr 10 2001 afnwcgi1.exe
+-rw-r--r-- 1 ftpuser ftpusers 175949 Jan 28 13:43 afp100j.exe
+-rw-r--r-- 1 ftpuser ftpusers 90415 Jul 12 1999 afp11.exe
+-rw-r--r-- 1 ftpuser ftpusers 513677 Nov 1 1995 aiodrv.exe
+-rw-r--r-- 1 ftpuser ftpusers 26752 Aug 12 1995 aiotrm.exe
+-rw-r--r-- 1 ftpuser ftpusers 113328 Feb 8 2000 alx311cm.exe
+-rw-r--r-- 1 ftpuser ftpusers 202594 Dec 11 2001 am210pt2.exe
+-rw-r--r-- 1 ftpuser ftpusers 1126900 Dec 10 2001 am210snp.exe
+-rw-r--r-- 1 ftpuser ftpusers 267218 Dec 11 2001 amsammg.exe
+-rw-r--r-- 1 ftpuser ftpusers 4394406 Nov 29 2001 amw2ksp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 34959 Nov 6 1996 anlmde.exe
+-rw-r--r-- 1 ftpuser ftpusers 70315 Nov 20 1996 antde.exe
+-rw-r--r-- 1 ftpuser ftpusers 2778036 Dec 10 1997 apinlm.exe
+-rw-r--r-- 1 ftpuser ftpusers 47772 Apr 5 1994 apinst.exe
+-rw-r--r-- 1 ftpuser ftpusers 3367826 Dec 10 1997 apios2.exe
+-rw-r--r-- 1 ftpuser ftpusers 44662 Sep 17 1993 apsvap.exe
+-rw-r--r-- 1 ftpuser ftpusers 1507519 Oct 5 1998 async1.exe
+-rw-r--r-- 1 ftpuser ftpusers 431852 Jul 25 1995 asyq4a.exe
+-rw-r--r-- 1 ftpuser ftpusers 68700 Sep 17 1993 atalk.exe
+-rw-r--r-- 1 ftpuser ftpusers 22944 Sep 17 1993 atdisk.exe
+-rw-r--r-- 1 ftpuser ftpusers 222222 Jan 29 1996 atk307.exe
+-rw-r--r-- 1 ftpuser ftpusers 259359 Sep 24 1999 atmdrv04.exe
+-rw-r--r-- 1 ftpuser ftpusers 22012 Jun 14 1996 atok31.exe
+-rw-r--r-- 1 ftpuser ftpusers 25152 Sep 17 1993 atps1.exe
+-rw-r--r-- 1 ftpuser ftpusers 25812 Sep 17 1993 atps2.exe
+-rw-r--r-- 1 ftpuser ftpusers 206226 Sep 17 1993 atsup.exe
+-rw-r--r-- 1 ftpuser ftpusers 249262 Sep 15 1997 audit410.exe
+-rw-r--r-- 1 ftpuser ftpusers 27058 Jul 25 1995 autoda.exe
+-rw-r--r-- 1 ftpuser ftpusers 53955568 Mar 28 2001 azfd3sp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 1267891 Mar 30 2000 bacl105.exe
+-rw-r--r-- 1 ftpuser ftpusers 564407 Apr 24 1998 bm21y2k.exe
+-rw-r--r-- 1 ftpuser ftpusers 64354 Dec 9 1999 bm2ncs2.exe
+-rw-r--r-- 1 ftpuser ftpusers 5025837 Nov 13 2000 bm30sp3.exe
+-rw-r--r-- 1 ftpuser ftpusers 118425 Mar 27 10:48 bm35adm6.exe
+-rw-r--r-- 1 ftpuser ftpusers 8950758 Sep 25 2001 bm35sp3.exe
+-rw-r--r-- 1 ftpuser ftpusers 1560521 May 31 15:43 bm36c02.exe
+-rw-r--r-- 1 ftpuser ftpusers 1995053 Nov 6 2001 bm36nsp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 4187534 Jan 30 13:44 bm36sp1a.exe
+-rw-r--r-- 1 ftpuser ftpusers 146884 Apr 19 13:52 bm37flt.exe
+-rw-r--r-- 1 ftpuser ftpusers 3958423 Apr 19 13:54 bm37vpn1.exe
+-rw-r--r-- 1 ftpuser ftpusers 2192048 Jun 16 2000 bm3cp3.exe
+-rw-r--r-- 1 ftpuser ftpusers 521873 Mar 27 2000 bm3licfx.exe
+-rw-r--r-- 1 ftpuser ftpusers 550905 Jan 21 1999 bm3netad.exe
+-rw-r--r-- 1 ftpuser ftpusers 28435 Oct 8 1999 bm3pcfg.exe
+-rw-r--r-- 1 ftpuser ftpusers 30429 Oct 20 1999 bm3rmv3.exe
+-rw-r--r-- 1 ftpuser ftpusers 4865777 Sep 2 1999 bm3sp2.exe
+-rw-r--r-- 1 ftpuser ftpusers 3934644 Jan 11 2000 bm3sp2j.exe
+-rw-r--r-- 1 ftpuser ftpusers 105579 Jan 16 2001 bm3sso2.exe
+-rw-r--r-- 1 ftpuser ftpusers 114564 Nov 23 1998 bmas203.exe
+-rw-r--r-- 1 ftpuser ftpusers 185953 Jul 27 2000 bmas204.exe
+-rw-r--r-- 1 ftpuser ftpusers 227934 May 29 2001 bmas3x01.exe
+-rw-r--r-- 1 ftpuser ftpusers 2409166 Apr 14 1998 bmnwntb.exe
+-rw-r--r-- 1 ftpuser ftpusers 235512 Oct 7 1999 bmp114.exe
+-rw-r--r-- 1 ftpuser ftpusers 114828 Aug 25 2000 bmsamp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 7822377 Feb 5 2001 bmsp2d.exe
+-rw-r--r-- 1 ftpuser ftpusers 177276 May 9 2001 bmvpn3y.exe
+-rw-r--r-- 1 ftpuser ftpusers 57666 Jul 16 1997 bndfx4.exe
+-rw-r--r-- 1 ftpuser ftpusers 22178 Sep 26 1997 brdrem1.exe
+-rw-r--r-- 1 ftpuser ftpusers 140225 Sep 17 1993 brgcom.exe
+-rw-r--r-- 1 ftpuser ftpusers 64130 Mar 17 1998 bwcc.exe
+-rw-r--r-- 1 ftpuser ftpusers 106576 May 10 2000 c112brj.exe
+-rw-r--r-- 1 ftpuser ftpusers 107820 May 9 2000 c112crcj.exe
+-rw-r--r-- 1 ftpuser ftpusers 106834 May 10 2000 c112crj.exe
+-rw-r--r-- 1 ftpuser ftpusers 35687507 Mar 5 13:14 c1_132.exe
+-rw-r--r-- 1 ftpuser ftpusers 188379 Feb 27 2001 c1unx85a.exe
+-rw-r--r-- 1 ftpuser ftpusers 24246977 Jun 2 2000 c526aix.z
+-rw-r--r-- 1 ftpuser ftpusers 39823205 Jun 2 2000 c526hp.z
+-rw-r--r-- 1 ftpuser ftpusers 31630789 Jun 2 2000 c526sol.z
+-rw-r--r-- 1 ftpuser ftpusers 39967 Dec 4 1996 ccmdll.exe
+-rw-r--r-- 1 ftpuser ftpusers 3532557 Jun 21 1999 ccmln1.exe
+-rw-r--r-- 1 ftpuser ftpusers 3610648 Apr 21 2000 ccmln2.exe
+-rw-r--r-- 1 ftpuser ftpusers 7242383 Oct 30 1998 ccmlo1.exe
+-rw-r--r-- 1 ftpuser ftpusers 71189 Mar 6 1997 cdisc.exe
+-rw-r--r-- 1 ftpuser ftpusers 298109 Aug 19 1998 cdup5a.exe
+-rw-r--r-- 1 ftpuser ftpusers 1554357 Oct 14 1998 cfgrd6b.exe
+-rw-r--r-- 1 ftpuser ftpusers 30799 Sep 17 1993 chk375.exe
+-rw-r--r-- 1 ftpuser ftpusers 85538 Jun 16 1997 chtree1.exe
+-rw-r--r-- 1 ftpuser ftpusers 28171 Dec 8 1999 clibaux1.exe
+-rw-r--r-- 1 ftpuser ftpusers 2819 Sep 8 2000 clients.txt
+-rw-r--r-- 1 ftpuser ftpusers 16820824 Sep 11 2000 clntaot.exe
+-rw-r--r-- 1 ftpuser ftpusers 7269162 Jan 5 1999 clos2d1.exe
+-rw-r--r-- 1 ftpuser ftpusers 2960384 Jun 24 1996 clt511.bin
+-rw-r--r-- 1 ftpuser ftpusers 195429 Mar 24 1999 clty2kp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 76117 Nov 22 1993 comchk.exe
+-rw-r--r-- 1 ftpuser ftpusers 76738 Nov 1 1995 comsub.exe
+-rw-r--r-- 1 ftpuser ftpusers 74759 Aug 16 1996 comx.exe
+-rw-r--r-- 1 ftpuser ftpusers 102496 Feb 22 2001 comx218.exe
+-rw-r--r-- 1 ftpuser ftpusers 117584 Dec 5 2000 confg9.exe
+-rw-r--r-- 1 ftpuser ftpusers 27438 Sep 17 1993 conlog.exe
+-rw-r--r-- 1 ftpuser ftpusers 20051 Sep 17 1993 cpuchk.exe
+-rw-r--r-- 1 ftpuser ftpusers 96755 Jan 7 2000 cron5.exe
+-rw-r--r-- 1 ftpuser ftpusers 22439431 Jul 21 2001 cs1sp2.exe
+-rw-r--r-- 1 ftpuser ftpusers 12643202 Feb 19 16:08 cs1sp3.exe
+-rw-r--r-- 1 ftpuser ftpusers 2395980 Feb 28 2001 cs2ep2.exe
+-rw-r--r-- 1 ftpuser ftpusers 97982 Feb 17 2000 csatpxy2.exe
+-rw-r--r-- 1 ftpuser ftpusers 888262 Jan 30 1997 csserv.exe
+-rw-r--r-- 1 ftpuser ftpusers 888092 Jan 30 1997 ctserv.exe
+-rw-r--r-- 1 ftpuser ftpusers 1195718 Sep 20 1999 ctsv20_1.pdf
+-rw-r--r-- 1 ftpuser ftpusers 97050 Aug 30 2000 cvsbind.exe
+-rw-r--r-- 1 ftpuser ftpusers 1040603 Jan 5 1996 d70f15.exe
+-rw-r--r-- 1 ftpuser ftpusers 1046550 Jan 5 1996 d70g15.exe
+-rw-r--r-- 1 ftpuser ftpusers 1041138 Jan 5 1996 d70i15.exe
+-rw-r--r-- 1 ftpuser ftpusers 1042404 Jan 5 1996 d70s15.exe
+-rw-r--r-- 1 ftpuser ftpusers 1031373 Jan 5 1996 d70u15.exe
+-rw-r--r-- 1 ftpuser ftpusers 309903 Oct 31 1995 d72pnw.exe
+-rw-r--r-- 1 ftpuser ftpusers 26322 Aug 17 1995 daishm.exe
+-rw-r--r-- 1 ftpuser ftpusers 92347 Jan 17 09:55 decrenfx.exe
+-rw-r--r-- 1 ftpuser ftpusers 32573 Nov 24 1997 devmon.exe
+-rw-r--r-- 1 ftpuser ftpusers 225697 Nov 23 1999 dhcp21r.exe
+-rw-r--r-- 1 ftpuser ftpusers 65667 Jul 27 1994 diag.exe
+-rw-r--r-- 1 ftpuser ftpusers 776679 Jul 3 1996 dialr1.exe
+-rw-r--r-- 1 ftpuser ftpusers 1307891 Jul 3 1996 dialr2.exe
+-rw-r--r-- 1 ftpuser ftpusers 1330220 Jul 3 1996 dialr3.exe
+-rw-r--r-- 1 ftpuser ftpusers 62202 Sep 17 1993 distst.exe
+-rw-r--r-- 1 ftpuser ftpusers 133345 Feb 8 2001 dlttape.exe
+-rw-r--r-- 1 ftpuser ftpusers 174566 Dec 13 1995 dr6tid.exe
+-rw-r--r-- 1 ftpuser ftpusers 188110 May 15 15:23 dradpt1a.exe
+-rw-r--r-- 1 ftpuser ftpusers 12654872 Apr 11 10:37 drdt10.exe
+-rw-r--r-- 1 ftpuser ftpusers 7991951 Apr 11 10:50 drnt10.exe
+-rw-r--r-- 1 ftpuser ftpusers 259966 Dec 9 1993 drv2x.exe
+-rw-r--r-- 1 ftpuser ftpusers 366568 Sep 17 1993 drvkit.exe
+-rw-r--r-- 1 ftpuser ftpusers 28773 Dec 2 1998 drvspc.exe
+-rw-r--r-- 1 ftpuser ftpusers 242836 Jul 12 1994 ds310.exe
+-rw-r--r-- 1 ftpuser ftpusers 739008 Dec 13 1999 ds410q.exe
+-rw-r--r-- 1 ftpuser ftpusers 683746 Jun 11 18:01 ds616.exe
+-rw-r--r-- 1 ftpuser ftpusers 1237908 Jul 3 19:58 ds760a.exe
+-rw-r--r-- 1 ftpuser ftpusers 3084809 Jun 12 13:47 ds880d_a.exe
+-rw-r--r-- 1 ftpuser ftpusers 2366484 Jun 7 2000 ds8c.exe
+-rw-r--r-- 1 ftpuser ftpusers 300572 May 31 2000 dsbrowse.exe
+-rw-r--r-- 1 ftpuser ftpusers 425220 Nov 10 1998 dsdiag1.exe
+-rw-r--r-- 1 ftpuser ftpusers 766525 Apr 15 1998 dskdrv.exe
+-rw-r--r-- 1 ftpuser ftpusers 201308 May 2 1997 dsright2.exe
+-rw-r--r-- 1 ftpuser ftpusers 6620 Feb 4 14:26 dsrmenu5.tgz
+-rw-r--r-- 1 ftpuser ftpusers 32671 Jan 11 12:06 dsx86upg.tgz
+-rw-r--r-- 1 ftpuser ftpusers 438327 Nov 22 1999 duprid.exe
+-rw-r--r-- 1 ftpuser ftpusers 366231 Nov 30 1999 dw271i1.exe
+-rw-r--r-- 1 ftpuser ftpusers 6444327 Oct 31 2001 dx1patch.exe
+-rw-r--r-- 1 ftpuser ftpusers 764705 Dec 11 2001 dxjdbc1a.exe
+-rw-r--r-- 1 ftpuser ftpusers 369669 Jul 31 2001 dxnotp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 325977 Jan 11 17:32 dxntp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 6446882 Jan 11 17:11 dxnwp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 27292445 Jan 15 18:08 dxx10a.tgz
+-rw-r--r-- 1 ftpuser ftpusers 420838 Sep 18 1993 e2isa.exe
+-rw-r--r-- 1 ftpuser ftpusers 299227554 May 15 09:35 edir851.exe
+-rw-r--r-- 1 ftpuser ftpusers 13752049 Jun 19 22:20 edir8527.exe
+-rw-r--r-- 1 ftpuser ftpusers 8909701 Jun 18 17:22 edir8527.tgz
+-rw-r--r-- 1 ftpuser ftpusers 35256093 May 23 12:35 edir862.exe
+-rw-r--r-- 1 ftpuser ftpusers 30290896 Mar 7 13:22 edir862.tgz
+-rw-r--r-- 1 ftpuser ftpusers 12405810 Jun 20 11:12 edir862sp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 7623982 Jun 20 11:07 edir862sp1a.tgz
+-rw-r--r-- 1 ftpuser ftpusers 178010922 Jun 19 23:26 edirw8527.exe
+-rw-r--r-- 1 ftpuser ftpusers 739976 Aug 1 1995 edvwin.exe
+-rw-r--r-- 1 ftpuser ftpusers 270433 Apr 12 15:32 egdpvr02.exe
+-rw-r--r-- 1 ftpuser ftpusers 6660863 Jan 15 10:28 einstall.exe
+-rw-r--r-- 1 ftpuser ftpusers 19547 Sep 18 1993 els2dt.exe
+-rw-r--r-- 1 ftpuser ftpusers 46872 Sep 18 1993 elsupd.exe
+-rw-r--r-- 1 ftpuser ftpusers 44481 Sep 18 1993 emshdl.exe
+-rw-r--r-- 1 ftpuser ftpusers 171889 Nov 30 2001 es7000.exe
+-rw-r--r-- 1 ftpuser ftpusers 395219 Sep 18 1993 escsi.exe
+-rw-r--r-- 1 ftpuser ftpusers 50164 Nov 1 1995 esdidr.exe
+-rw-r--r-- 1 ftpuser ftpusers 22207 Sep 18 1993 esdifx.exe
+-rw-r--r-- 1 ftpuser ftpusers 162763 Apr 16 2001 etbox7.exe
+-rw-r--r-- 1 ftpuser ftpusers 28262 Sep 18 1993 ethrlk.exe
+-rw-r--r-- 1 ftpuser ftpusers 21776 Sep 18 1993 ethsh.exe
+-rw-r--r-- 1 ftpuser ftpusers 3111638 Oct 13 1999 exchnt2.exe
+-rw-r--r-- 1 ftpuser ftpusers 32615 Mar 20 1995 exprul.exe
+-rw-r--r-- 1 ftpuser ftpusers 19910 Jul 18 1995 facwin.exe
+-rw-r--r-- 1 ftpuser ftpusers 193689 Sep 18 1993 faxdoc.exe
+-rw-r--r-- 1 ftpuser ftpusers 103299 Jul 18 1995 faxsv.exe
+-rw-r--r-- 1 ftpuser ftpusers 566087 Jul 20 1998 fbm21y2k.exe
+-rw-r--r-- 1 ftpuser ftpusers 263164 Jul 27 2000 ffwnt1a.exe
+-rw-r--r-- 1 ftpuser ftpusers 9564485 Jun 5 2000 fgwep1ad.exe
+-rw-r--r-- 1 ftpuser ftpusers 158446 Nov 10 1993 fil376.exe
+-rw-r--r-- 1 ftpuser ftpusers 35376 Sep 18 1993 filehd.exe
+-rw-r--r-- 1 ftpuser ftpusers 64924 Jan 28 1999 filt01a.exe
+-rw-r--r-- 1 ftpuser ftpusers 38027 Sep 18 1993 flgdir.exe
+-rw-r--r-- 1 ftpuser ftpusers 891667 Jun 25 10:26 flsysft7.exe
+-rw-r--r-- 1 ftpuser ftpusers 210958 Jul 20 1994 flx196.exe
+-rw-r--r-- 1 ftpuser ftpusers 23948 Sep 18 1993 fmtps2.exe
+-rw-r--r-- 1 ftpuser ftpusers 265642 Jun 1 1995 fmwin1.exe
+-rw-r--r-- 1 ftpuser ftpusers 44110 Jun 18 1997 fnasi21b.exe
+-rw-r--r-- 1 ftpuser ftpusers 35133 Apr 29 1997 fnwcrns.exe
+-rw-r--r-- 1 ftpuser ftpusers 64944 Jun 18 1997 fnwcss.exe
+-rw-r--r-- 1 ftpuser ftpusers 38169 Jun 18 1997 fnwcx25.exe
+-rw-r--r-- 1 ftpuser ftpusers 18985686 Feb 26 2001 fp3023a.exe
+-rw-r--r-- 1 ftpuser ftpusers 19034903 Feb 26 2001 fp3023s.exe
+-rw-r--r-- 1 ftpuser ftpusers 41401158 Jun 22 2001 fpa353.exe
+-rw-r--r-- 1 ftpuser ftpusers 40072174 Jun 22 2001 fps353.exe
+-rw-r--r-- 1 ftpuser ftpusers 40680 Aug 2 1996 frebld.exe
+-rw-r--r-- 1 ftpuser ftpusers 156117 Jan 30 15:36 ftpservk.exe
+-rw-r--r-- 1 ftpuser ftpusers 1427341 Jun 20 2001 fzd2abnd.exe
+-rw-r--r-- 1 ftpuser ftpusers 121436 May 22 2001 fzd2nal.exe
+-rw-r--r-- 1 ftpuser ftpusers 293122 May 22 2001 fzd2nal1.exe
+-rw-r--r-- 1 ftpuser ftpusers 333581 Dec 18 2001 fzd2nal2.exe
+-rw-r--r-- 1 ftpuser ftpusers 250445 May 23 2001 fzd2zapp.exe
+-rw-r--r-- 1 ftpuser ftpusers 2619032 Oct 10 2001 g32ep3b.exe
+-rw-r--r-- 1 ftpuser ftpusers 26193920 Nov 23 1998 g41c5a41.tar
+-rw-r--r-- 1 ftpuser ftpusers 25907200 Nov 23 1998 g41c5a43.tar
+-rw-r--r-- 1 ftpuser ftpusers 25190400 Nov 23 1998 g41c5dg.tar
+-rw-r--r-- 1 ftpuser ftpusers 27494400 Nov 23 1998 g41c5hp.tar
+-rw-r--r-- 1 ftpuser ftpusers 29337600 Nov 23 1998 g41c5ncr.tar
+-rw-r--r-- 1 ftpuser ftpusers 27146240 Nov 23 1998 g41c5sc5.tar
+-rw-r--r-- 1 ftpuser ftpusers 26982400 Nov 23 1998 g41c5sl5.tar
+-rw-r--r-- 1 ftpuser ftpusers 26961920 Nov 23 1998 g41c5sl6.tar
+-rw-r--r-- 1 ftpuser ftpusers 32808960 Nov 23 1998 g41c5sun.tar
+-rw-r--r-- 1 ftpuser ftpusers 3614720 Nov 23 1998 g41m5a41.tar
+-rw-r--r-- 1 ftpuser ftpusers 3604480 Nov 23 1998 g41m5a43.tar
+-rw-r--r-- 1 ftpuser ftpusers 3481600 Nov 23 1998 g41m5dg.tar
+-rw-r--r-- 1 ftpuser ftpusers 4280320 Nov 23 1998 g41m5hp.tar
+-rw-r--r-- 1 ftpuser ftpusers 4495360 Nov 23 1998 g41m5ncr.tar
+-rw-r--r-- 1 ftpuser ftpusers 5263360 Nov 23 1998 g41m5sc5.tar
+-rw-r--r-- 1 ftpuser ftpusers 4116480 Nov 23 1998 g41m5sl5.tar
+-rw-r--r-- 1 ftpuser ftpusers 4106240 Nov 23 1998 g41m5sl6.tar
+-rw-r--r-- 1 ftpuser ftpusers 5939200 Nov 20 1998 g41m5sun.tar
+-rw-r--r-- 1 ftpuser ftpusers 93137892 Jun 2 2000 g526east.exe
+-rw-r--r-- 1 ftpuser ftpusers 84011178 Jun 2 2000 g526kcc.exe
+-rw-r--r-- 1 ftpuser ftpusers 106015153 Jun 2 2000 g526mult.exe
+-rw-r--r-- 1 ftpuser ftpusers 92474943 Jun 2 2000 g526scan.exe
+-rw-r--r-- 1 ftpuser ftpusers 74449657 Jun 2 2000 g526us.exe
+-rw-r--r-- 1 ftpuser ftpusers 80161031 Jun 2 2000 g526usde.exe
+-rw-r--r-- 1 ftpuser ftpusers 77052636 Jun 2 2000 g526usjp.exe
+-rw-r--r-- 1 ftpuser ftpusers 20712319 Dec 18 1997 g52a1aix.z
+-rw-r--r-- 1 ftpuser ftpusers 17069171 Dec 18 1997 g52a1hp.z
+-rw-r--r-- 1 ftpuser ftpusers 14703356 Dec 18 1997 g52a1sol.z
+-rw-r--r-- 1 ftpuser ftpusers 7595802 Jun 2 2000 g554ar.exe
+-rw-r--r-- 1 ftpuser ftpusers 39304570 Jun 2 2000 g554en.exe
+-rw-r--r-- 1 ftpuser ftpusers 13651283 Jun 2 2000 g554est.exe
+-rw-r--r-- 1 ftpuser ftpusers 7587459 Jun 2 2000 g554he.exe
+-rw-r--r-- 1 ftpuser ftpusers 23317212 Jun 2 2000 g554jp.exe
+-rw-r--r-- 1 ftpuser ftpusers 22871590 Jun 2 2000 g554kcc.exe
+-rw-r--r-- 1 ftpuser ftpusers 30379240 Jun 2 2000 g554mlt.exe
+-rw-r--r-- 1 ftpuser ftpusers 30469595 Jun 2 2000 g554scn.exe
+-rw-r--r-- 1 ftpuser ftpusers 3252251 Aug 31 2000 g5notmb1.exe
+-rw-r--r-- 1 ftpuser ftpusers 1983381 Aug 8 1995 gam10.exe
+-rw-r--r-- 1 ftpuser ftpusers 565411 Jul 20 1998 gbm21y2k.exe
+-rw-r--r-- 1 ftpuser ftpusers 547498 Nov 19 1996 gdsmtp.exe
+-rw-r--r-- 1 ftpuser ftpusers 26760 Oct 21 1996 gdusc1.exe
+-rw-r--r-- 1 ftpuser ftpusers 32876 Sep 18 1993 genbio.exe
+-rw-r--r-- 1 ftpuser ftpusers 4589470 Oct 3 2001 gep3beng.exe
+-rw-r--r-- 1 ftpuser ftpusers 12570112 Aug 16 1999 gm527aen.bin
+-rw-r--r-- 1 ftpuser ftpusers 12556928 Jun 14 2000 gm528aen.bin
+-rw-r--r-- 1 ftpuser ftpusers 12558720 Jun 19 2000 gm528ben.bin
+-rw-r--r-- 1 ftpuser ftpusers 6081664 Dec 21 1996 gmcec3.hqx
+-rw-r--r-- 1 ftpuser ftpusers 6086656 Dec 21 1996 gmcfc3.hqx
+-rw-r--r-- 1 ftpuser ftpusers 6089856 Dec 24 1996 gmesc3.hqx
+-rw-r--r-- 1 ftpuser ftpusers 6087552 Dec 20 1996 gmfrc3.hqx
+-rw-r--r-- 1 ftpuser ftpusers 6084480 Dec 24 1996 gmitc3.hqx
+-rw-r--r-- 1 ftpuser ftpusers 6079872 Dec 19 1996 gmozc3.hqx
+-rw-r--r-- 1 ftpuser ftpusers 6081792 Dec 19 1996 gmukc3.hqx
+-rw-r--r-- 1 ftpuser ftpusers 6079872 Dec 11 1996 gmusc3.hqx
+-rw-r--r-- 1 ftpuser ftpusers 26557 Sep 18 1993 gpierr.exe
+-rw-r--r-- 1 ftpuser ftpusers 189508 Aug 28 1996 gpwrdk.exe
+-rw-r--r-- 1 ftpuser ftpusers 114332 Aug 28 1996 gpwrnl.exe
+-rw-r--r-- 1 ftpuser ftpusers 99491 Sep 3 1996 gpwrru.exe
+-rw-r--r-- 1 ftpuser ftpusers 131835 Aug 28 1996 gpwrsu.exe
+-rw-r--r-- 1 ftpuser ftpusers 170183 Aug 22 1996 gpwrsv.exe
+-rw-r--r-- 1 ftpuser ftpusers 74740 Feb 25 1998 gpwsbr.exe
+-rw-r--r-- 1 ftpuser ftpusers 44964 Feb 25 1998 gpwsde.exe
+-rw-r--r-- 1 ftpuser ftpusers 40264 Feb 25 1998 gpwsfr.exe
+-rw-r--r-- 1 ftpuser ftpusers 39224 Feb 25 1998 gpwsit.exe
+-rw-r--r-- 1 ftpuser ftpusers 47842 Jul 22 1999 groupfix.exe
+-rw-r--r-- 1 ftpuser ftpusers 207875 Oct 19 1995 gsc41.exe
+-rw-r--r-- 1 ftpuser ftpusers 811983 Dec 15 1997 gsc51.exe
+-rw-r--r-- 1 ftpuser ftpusers 9805824 Jun 8 1995 gusmtp.tar
+-rw-r--r-- 1 ftpuser ftpusers 4658880 Jul 28 1999 gw41api.exe
+-rw-r--r-- 1 ftpuser ftpusers 1307103 Nov 17 1999 gw41api2.exe
+-rw-r--r-- 1 ftpuser ftpusers 30983798 Jul 29 1999 gw41aus.exe
+-rw-r--r-- 1 ftpuser ftpusers 86653 Feb 28 1996 gw41qa.exe
+-rw-r--r-- 1 ftpuser ftpusers 20978 Dec 10 1998 gw41sp5.txt
+-rw-r--r-- 1 ftpuser ftpusers 18251583 Jan 8 1998 gw51sp2a.exe
+-rw-r--r-- 1 ftpuser ftpusers 3483616 Mar 10 1998 gw51w16a.exe
+-rw-r--r-- 1 ftpuser ftpusers 1931948 Jan 9 2001 gw52ch6.exe
+-rw-r--r-- 1 ftpuser ftpusers 479758 Jun 26 2000 gw52sp6.exe
+-rw-r--r-- 1 ftpuser ftpusers 35836761 Feb 28 16:19 gw555cck.exe
+-rw-r--r-- 1 ftpuser ftpusers 26614908 Feb 28 16:34 gw555ee.exe
+-rw-r--r-- 1 ftpuser ftpusers 372421 May 31 2000 gw55bk.exe
+-rw-r--r-- 1 ftpuser ftpusers 109887 Feb 3 2000 gw55bp.exe
+-rw-r--r-- 1 ftpuser ftpusers 847939 Jun 19 2000 gw55dutl.exe
+-rw-r--r-- 1 ftpuser ftpusers 58548675 Aug 14 2001 gw55ep3a.exe
+-rw-r--r-- 1 ftpuser ftpusers 2497895 Jun 25 1999 gw55inst.exe
+-rw-r--r-- 1 ftpuser ftpusers 3742457 Jun 27 2000 gw55ol2.exe
+-rw-r--r-- 1 ftpuser ftpusers 219963 Apr 18 2001 gw55puma.exe
+-rw-r--r-- 1 ftpuser ftpusers 19376 Mar 1 1999 gw55rc.exe
+-rw-r--r-- 1 ftpuser ftpusers 45201 Dec 18 1998 gw55sp1u.exe
+-rw-r--r-- 1 ftpuser ftpusers 21311033 Feb 28 16:08 gw55sp5a.exe
+-rw-r--r-- 1 ftpuser ftpusers 52764291 Feb 19 17:56 gw55sp5e.exe
+-rw-r--r-- 1 ftpuser ftpusers 21300984 Feb 28 16:13 gw55sp5h.exe
+-rw-r--r-- 1 ftpuser ftpusers 43933605 Feb 19 18:03 gw55sp5m.exe
+-rw-r--r-- 1 ftpuser ftpusers 44001516 Feb 28 16:03 gw55sp5s.exe
+-rw-r--r-- 1 ftpuser ftpusers 5867520 Mar 9 1999 gw55uagb.tar
+-rw-r--r-- 1 ftpuser ftpusers 20446033 Apr 23 1997 gw5img.exe
+-rw-r--r-- 1 ftpuser ftpusers 313843533 Nov 21 2001 gw6sp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 313466368 Nov 20 2001 gw6sp1fr.exe
+-rw-r--r-- 1 ftpuser ftpusers 26705047 Mar 13 18:35 gw6tomcat_nt.exe
+-rw-r--r-- 1 ftpuser ftpusers 318278 Oct 15 2001 gw6wasf.exe
+-rw-r--r-- 1 ftpuser ftpusers 493803 Jan 22 1997 gwadm.exe
+-rw-r--r-- 1 ftpuser ftpusers 1900719 Jul 26 2000 gwafe510.exe
+-rw-r--r-- 1 ftpuser ftpusers 469618 Nov 2 1999 gwanlzr1.exe
+-rw-r--r-- 1 ftpuser ftpusers 479013 Jun 19 2000 gwata417.exe
+-rw-r--r-- 1 ftpuser ftpusers 1731751 Jun 19 2000 gwata517.exe
+-rw-r--r-- 1 ftpuser ftpusers 168008 Aug 12 1996 gwbr41.exe
+-rw-r--r-- 1 ftpuser ftpusers 17881984 Aug 31 1998 gwbrc5.exe
+-rw-r--r-- 1 ftpuser ftpusers 194213 Aug 26 1997 gwbupaus.exe
+-rw-r--r-- 1 ftpuser ftpusers 885247 Jun 15 2000 gwca55.exe
+-rw-r--r-- 1 ftpuser ftpusers 902786 Jun 29 2000 gwca55us.exe
+-rw-r--r-- 1 ftpuser ftpusers 2398720 Aug 17 1999 gwccarch.exe
+-rw-r--r-- 1 ftpuser ftpusers 19751754 Aug 27 1998 gwcec5.exe
+-rw-r--r-- 1 ftpuser ftpusers 18095569 Dec 1 1998 gwcfc5a.exe
+-rw-r--r-- 1 ftpuser ftpusers 499022 Jan 22 1997 gwclint.exe
+-rw-r--r-- 1 ftpuser ftpusers 274618 Jun 19 2000 gwclust.exe
+-rw-r--r-- 1 ftpuser ftpusers 18704283 Aug 31 1998 gwczc5.exe
+-rw-r--r-- 1 ftpuser ftpusers 18602662 Aug 28 1998 gwdec5.exe
+-rw-r--r-- 1 ftpuser ftpusers 577392 Jan 22 1997 gwdirsnc.exe
+-rw-r--r-- 1 ftpuser ftpusers 18044524 Aug 31 1998 gwdkc5.exe
+-rw-r--r-- 1 ftpuser ftpusers 2064976 Aug 16 2001 gwe2mlfx.exe
+-rw-r--r-- 1 ftpuser ftpusers 220287 Apr 18 2001 gweppuma.exe
+-rw-r--r-- 1 ftpuser ftpusers 106411074 Feb 19 17:38 gwepsp4e.exe
+-rw-r--r-- 1 ftpuser ftpusers 105412358 Feb 19 17:48 gwepsp4m.exe
+-rw-r--r-- 1 ftpuser ftpusers 211359 Oct 15 2001 gwepwasf.exe
+-rw-r--r-- 1 ftpuser ftpusers 18156006 Aug 31 1998 gwesc5.exe
+-rw-r--r-- 1 ftpuser ftpusers 2278400 Aug 20 1999 gwexarch.exe
+-rw-r--r-- 1 ftpuser ftpusers 18094284 Sep 2 1998 gwfrc5.exe
+-rw-r--r-- 1 ftpuser ftpusers 14809111 Feb 5 12:22 gwia6sp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 47599 Dec 24 1998 gwip.exe
+-rw-r--r-- 1 ftpuser ftpusers 2103744 Jun 26 2000 gwiru55.exe
+-rw-r--r-- 1 ftpuser ftpusers 18176506 Aug 31 1998 gwitc5.exe
+-rw-r--r-- 1 ftpuser ftpusers 1643991 May 20 1997 gwjpc3.exe
+-rw-r--r-- 1 ftpuser ftpusers 2689024 Aug 24 1999 gwlnarch.exe
+-rw-r--r-- 1 ftpuser ftpusers 18450385 Aug 31 1998 gwmac5.exe
+-rw-r--r-- 1 ftpuser ftpusers 104256 Jun 19 2001 gwmacvew.exe
+-rw-r--r-- 1 ftpuser ftpusers 521879 Jan 22 1997 gwmigrat.exe
+-rw-r--r-- 1 ftpuser ftpusers 2387456 Aug 18 1999 gwmsarch.exe
+-rw-r--r-- 1 ftpuser ftpusers 18442250 Aug 31 1998 gwnlc5.exe
+-rw-r--r-- 1 ftpuser ftpusers 18496070 Aug 31 1998 gwnoc5.exe
+-rw-r--r-- 1 ftpuser ftpusers 18436940 Aug 27 1998 gwozc5.exe
+-rw-r--r-- 1 ftpuser ftpusers 735542 Aug 29 2001 gwpdchk.exe
+-rw-r--r-- 1 ftpuser ftpusers 29521018 Aug 28 2001 gwpdlk56.exe
+-rw-r--r-- 1 ftpuser ftpusers 29520686 Aug 14 2001 gwpdlock.exe
+-rw-r--r-- 1 ftpuser ftpusers 18696898 Aug 31 1998 gwplc5.exe
+-rw-r--r-- 1 ftpuser ftpusers 1388969 Mar 5 1996 gwpoc.exe
+-rw-r--r-- 1 ftpuser ftpusers 17738497 Aug 31 1998 gwpoc5.exe
+-rw-r--r-- 1 ftpuser ftpusers 10400450 Jan 22 16:48 gwport32.exe
+-rw-r--r-- 1 ftpuser ftpusers 18492682 Aug 31 1998 gwruc5.exe
+-rw-r--r-- 1 ftpuser ftpusers 18154021 Aug 31 1998 gwsuc5.exe
+-rw-r--r-- 1 ftpuser ftpusers 17958220 Aug 31 1998 gwsvc5.exe
+-rw-r--r-- 1 ftpuser ftpusers 536848 Jan 16 09:41 gwsyclo.exe
+-rw-r--r-- 1 ftpuser ftpusers 78740 Nov 9 1999 gwtps1v2.exe
+-rw-r--r-- 1 ftpuser ftpusers 18432206 Aug 28 1998 gwukc5.exe
+-rw-r--r-- 1 ftpuser ftpusers 18544901 Aug 27 1998 gwusc5.exe
+-rw-r--r-- 1 ftpuser ftpusers 210542 Oct 18 1995 gwusr1.exe
+-rw-r--r-- 1 ftpuser ftpusers 1404401 Oct 18 1995 gwusr2.exe
+-rw-r--r-- 1 ftpuser ftpusers 2467040 Mar 28 1997 gwusr3.exe
+-rw-r--r-- 1 ftpuser ftpusers 767611 Oct 1 1997 gwwa4p1.exe
+-rw-r--r-- 1 ftpuser ftpusers 2092781 Mar 4 1998 gwwebcgi.z
+-rw-r--r-- 1 ftpuser ftpusers 345006 Aug 4 1999 gwy195.exe
+-rw-r--r-- 1 ftpuser ftpusers 102293 Oct 9 2001 hdir501c.exe
+-rw-r--r-- 1 ftpuser ftpusers 1138106 Aug 21 1998 highutl1.exe
+-rw-r--r-- 1 ftpuser ftpusers 567026 Mar 28 1995 hpt004.exe
+-rw-r--r-- 1 ftpuser ftpusers 64329 Mar 9 1995 hpt005.exe
+-rw-r--r-- 1 ftpuser ftpusers 602958 Aug 27 1996 hpt006.exe
+-rw-r--r-- 1 ftpuser ftpusers 497382 Mar 9 1995 hpt007.exe
+-rw-r--r-- 1 ftpuser ftpusers 510029 Mar 9 1995 hpt008.exe
+-rw-r--r-- 1 ftpuser ftpusers 596667 Mar 13 1995 hpt009.exe
+-rw-r--r-- 1 ftpuser ftpusers 942798 Nov 20 1995 hpt011.exe
+-rw-r--r-- 1 ftpuser ftpusers 176332 Aug 11 1995 hpt013.exe
+-rw-r--r-- 1 ftpuser ftpusers 1070543 Mar 16 1999 hstdev.exe
+-rw-r--r-- 1 ftpuser ftpusers 246782 Apr 5 14:51 httpstk1.exe
+-rw-r--r-- 1 ftpuser ftpusers 262791 Apr 19 2000 i2odrv5.exe
+-rw-r--r-- 1 ftpuser ftpusers 565749 Jul 20 1998 ibm21y2k.exe
+-rw-r--r-- 1 ftpuser ftpusers 24735 Sep 18 1993 ibmmem.exe
+-rw-r--r-- 1 ftpuser ftpusers 60883 Sep 18 1993 ibmrt.exe
+-rw-r--r-- 1 ftpuser ftpusers 2621963 Jul 11 2001 ic15fp2.exe
+-rw-r--r-- 1 ftpuser ftpusers 2905716 Feb 8 16:39 ic15fp3.exe
+-rw-r--r-- 1 ftpuser ftpusers 9581302 Apr 4 2001 ic15sp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 1585498 Dec 14 2001 ic20fp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 4520778 Jan 14 09:32 ic20fp2.exe
+-rw-r--r-- 1 ftpuser ftpusers 4777958 May 30 15:01 ic20sp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 142010 Mar 28 17:46 ichcdump.exe
+-rw-r--r-- 1 ftpuser ftpusers 36043 Sep 20 1994 ide.exe
+-rw-r--r-- 1 ftpuser ftpusers 24552 Sep 18 1993 ide286.exe
+-rw-r--r-- 1 ftpuser ftpusers 27300 Sep 18 1993 ide386.exe
+-rw-r--r-- 1 ftpuser ftpusers 105249 Jun 9 2000 ideata5a.exe
+-rw-r--r-- 1 ftpuser ftpusers 1356133 Apr 17 2000 ihp232.exe
+-rw-r--r-- 1 ftpuser ftpusers 93664 Mar 8 15:40 imspmfix.exe
+-rw-r--r-- 1 ftpuser ftpusers 7338542 Jul 23 1998 in42sp2.exe
+-rw-r--r-- 1 ftpuser ftpusers 430410 Nov 8 1995 ind41.exe
+-rw-r--r-- 1 ftpuser ftpusers 63751 Mar 20 1997 inetcs.exe
+-rw-r--r-- 1 ftpuser ftpusers 60414 Mar 20 1997 inetct.exe
+-rw-r--r-- 1 ftpuser ftpusers 69792 Apr 28 1997 inetha.exe
+-rw-r--r-- 1 ftpuser ftpusers 1094896 Oct 18 1995 inf1.exe
+-rw-r--r-- 1 ftpuser ftpusers 798379 Oct 18 1995 inff1.exe
+-rw-r--r-- 1 ftpuser ftpusers 151877 Jan 9 2002 installa.exe
+-rw-r--r-- 1 ftpuser ftpusers 836804 Jun 9 1995 instll.exe
+-rw-r--r-- 1 ftpuser ftpusers 101582 Oct 9 2000 instp5x.exe
+-rw-r--r-- 1 ftpuser ftpusers 39511 Sep 18 1993 int215.exe
+-rw-r--r-- 1 ftpuser ftpusers 19521 Sep 18 1993 intfix.exe
+-rw-r--r-- 1 ftpuser ftpusers 35521 Sep 18 1993 intrud.exe
+-rw-r--r-- 1 ftpuser ftpusers 5594188 Dec 4 1997 inwc2enh.exe
+-rw-r--r-- 1 ftpuser ftpusers 69340 Sep 18 1993 ipc212.exe
+-rw-r--r-- 1 ftpuser ftpusers 24423 Sep 18 1993 ipcfg.exe
+-rw-r--r-- 1 ftpuser ftpusers 593463 Aug 13 2001 ipcost.exe
+-rw-r--r-- 1 ftpuser ftpusers 131414 Jun 24 1999 ipg4201a.exe
+-rw-r--r-- 1 ftpuser ftpusers 617600 Jun 30 2000 ipgc07a.exe
+-rw-r--r-- 1 ftpuser ftpusers 233838 Feb 11 2000 ipgsb06.exe
+-rw-r--r-- 1 ftpuser ftpusers 107564 Oct 2 1999 ipgsn10a.exe
+-rw-r--r-- 1 ftpuser ftpusers 44888 Nov 15 1999 ipgwdoc.exe
+-rw-r--r-- 1 ftpuser ftpusers 65876 Sep 18 1993 ipt112.exe
+-rw-r--r-- 1 ftpuser ftpusers 842325 Sep 23 1998 ipx660.exe
+-rw-r--r-- 1 ftpuser ftpusers 37227 Dec 1 1995 ipxspx.exe
+-rw-r--r-- 1 ftpuser ftpusers 22904 Sep 18 1993 isa30.exe
+-rw-r--r-- 1 ftpuser ftpusers 31546 Sep 18 1993 isa311.exe
+-rw-r--r-- 1 ftpuser ftpusers 24391 Sep 18 1993 isarem.exe
+-rw-r--r-- 1 ftpuser ftpusers 49650 Apr 9 1997 iwsbp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 6073482 Nov 21 2000 jbm30sp3.exe
+-rw-r--r-- 1 ftpuser ftpusers 109173 Oct 19 1995 jcon.exe
+-rw-r--r-- 1 ftpuser ftpusers 185167 Aug 16 2001 jr08993.exe
+-rw-r--r-- 1 ftpuser ftpusers 54187 Aug 15 2001 jr10449.exe
+-rw-r--r-- 1 ftpuser ftpusers 51804 Aug 15 2001 jr10470.exe
+-rw-r--r-- 1 ftpuser ftpusers 105466 May 29 2001 jr10490.exe
+-rw-r--r-- 1 ftpuser ftpusers 17936 Oct 16 2000 jr10662.exe
+-rw-r--r-- 1 ftpuser ftpusers 51421 Oct 16 2000 jr10803.exe
+-rw-r--r-- 1 ftpuser ftpusers 884373 Aug 15 2001 jr10823.exe
+-rw-r--r-- 1 ftpuser ftpusers 1909 Aug 15 2001 jr10923.zip
+-rw-r--r-- 1 ftpuser ftpusers 53610 Oct 16 2000 jr11209.exe
+-rw-r--r-- 1 ftpuser ftpusers 272210 Oct 16 2000 jr11213.exe
+-rw-r--r-- 1 ftpuser ftpusers 32984 May 27 2001 jr11223.exe
+-rw-r--r-- 1 ftpuser ftpusers 45200 Oct 16 2000 jr11409.exe
+-rw-r--r-- 1 ftpuser ftpusers 488829 May 27 2001 jr12054.exe
+-rw-r--r-- 1 ftpuser ftpusers 17761 Aug 15 2001 jr12089.exe
+-rw-r--r-- 1 ftpuser ftpusers 245833 May 27 2001 jr12125.exe
+-rw-r--r-- 1 ftpuser ftpusers 242650 Aug 15 2001 jr12129.exe
+-rw-r--r-- 1 ftpuser ftpusers 144543 May 27 2001 jr12229.exe
+-rw-r--r-- 1 ftpuser ftpusers 23194 May 27 2001 jr12349.exe
+-rw-r--r-- 1 ftpuser ftpusers 158924 Aug 15 2001 jr12415.exe
+-rw-r--r-- 1 ftpuser ftpusers 39844 Oct 16 2000 jr12518.exe
+-rw-r--r-- 1 ftpuser ftpusers 42015 Oct 16 2000 jr12676.exe
+-rw-r--r-- 1 ftpuser ftpusers 42090 May 27 2001 jr12692.exe
+-rw-r--r-- 1 ftpuser ftpusers 41998 May 29 2001 jr12705.exe
+-rw-r--r-- 1 ftpuser ftpusers 21903 Oct 16 2000 jr12706.exe
+-rw-r--r-- 1 ftpuser ftpusers 75818 Oct 16 2000 jr12765.exe
+-rw-r--r-- 1 ftpuser ftpusers 245898 Aug 15 2001 jr12768.exe
+-rw-r--r-- 1 ftpuser ftpusers 144542 Oct 16 2000 jr12773.exe
+-rw-r--r-- 1 ftpuser ftpusers 144542 May 29 2001 jr12775.exe
+-rw-r--r-- 1 ftpuser ftpusers 144543 Aug 15 2001 jr12776.exe
+-rw-r--r-- 1 ftpuser ftpusers 44352 Oct 16 2000 jr12777.exe
+-rw-r--r-- 1 ftpuser ftpusers 44355 May 27 2001 jr12778.exe
+-rw-r--r-- 1 ftpuser ftpusers 43721 Aug 15 2001 jr12828.exe
+-rw-r--r-- 1 ftpuser ftpusers 52823 May 27 2001 jr12890.exe
+-rw-r--r-- 1 ftpuser ftpusers 52824 Oct 16 2000 jr12947.exe
+-rw-r--r-- 1 ftpuser ftpusers 74323 Oct 16 2000 jr12978.exe
+-rw-r--r-- 1 ftpuser ftpusers 74323 May 27 2001 jr12979.exe
+-rw-r--r-- 1 ftpuser ftpusers 74326 May 29 2001 jr12987.exe
+-rw-r--r-- 1 ftpuser ftpusers 16573256 May 27 2001 jr13042.exe
+-rw-r--r-- 1 ftpuser ftpusers 16586769 Aug 15 2001 jr13046.exe
+-rw-r--r-- 1 ftpuser ftpusers 170632 Aug 15 2001 jr13047.exe
+-rw-r--r-- 1 ftpuser ftpusers 55210 Aug 15 2001 jr13105.exe
+-rw-r--r-- 1 ftpuser ftpusers 124966 Aug 15 2001 jr13147.exe
+-rw-r--r-- 1 ftpuser ftpusers 43318 Oct 16 2000 jr13259.exe
+-rw-r--r-- 1 ftpuser ftpusers 33183 Oct 16 2000 jr13461.exe
+-rw-r--r-- 1 ftpuser ftpusers 84700 May 27 2001 jr13554.exe
+-rw-r--r-- 1 ftpuser ftpusers 84649 Oct 16 2000 jr13555.exe
+-rw-r--r-- 1 ftpuser ftpusers 52564 May 27 2001 jr13557.exe
+-rw-r--r-- 1 ftpuser ftpusers 52161 Oct 16 2000 jr13558.exe
+-rw-r--r-- 1 ftpuser ftpusers 52167 May 29 2001 jr13559.exe
+-rw-r--r-- 1 ftpuser ftpusers 54942 May 27 2001 jr13616.exe
+-rw-r--r-- 1 ftpuser ftpusers 54947 Oct 16 2000 jr13617.exe
+-rw-r--r-- 1 ftpuser ftpusers 56424 Aug 15 2001 jr13619.exe
+-rw-r--r-- 1 ftpuser ftpusers 71827 Sep 17 1999 jr13627.exe
+-rw-r--r-- 1 ftpuser ftpusers 83182 Oct 16 2000 jr13637.exe
+-rw-r--r-- 1 ftpuser ftpusers 108483 May 29 2001 jr13722.exe
+-rw-r--r-- 1 ftpuser ftpusers 170173 Aug 15 2001 jr13734.exe
+-rw-r--r-- 1 ftpuser ftpusers 641941 Aug 15 2001 jr13748.exe
+-rw-r--r-- 1 ftpuser ftpusers 641950 May 29 2001 jr13749.exe
+-rw-r--r-- 1 ftpuser ftpusers 579521 May 29 2001 jr13886.exe
+-rw-r--r-- 1 ftpuser ftpusers 126491 Aug 15 2001 jr13891.exe
+-rw-r--r-- 1 ftpuser ftpusers 109292 May 27 2001 jr14132.exe
+-rw-r--r-- 1 ftpuser ftpusers 109181 Aug 15 2001 jr14134.exe
+-rw-r--r-- 1 ftpuser ftpusers 39830 May 29 2001 jr14185.exe
+-rw-r--r-- 1 ftpuser ftpusers 72780 Aug 15 2001 jr14278.exe
+-rw-r--r-- 1 ftpuser ftpusers 345689 Aug 15 2001 jr14358.exe
+-rw-r--r-- 1 ftpuser ftpusers 642240 May 27 2001 jr14359.exe
+-rw-r--r-- 1 ftpuser ftpusers 642388 Oct 16 2000 jr14360.exe
+-rw-r--r-- 1 ftpuser ftpusers 313078 May 27 2001 jr14367.exe
+-rw-r--r-- 1 ftpuser ftpusers 109587 May 27 2001 jr14402.exe
+-rw-r--r-- 1 ftpuser ftpusers 71603 Aug 15 2001 jr14457.exe
+-rw-r--r-- 1 ftpuser ftpusers 567270 Aug 15 2001 jr14500.exe
+-rw-r--r-- 1 ftpuser ftpusers 157611 Aug 15 2001 jr14523.exe
+-rw-r--r-- 1 ftpuser ftpusers 161290 Aug 15 2001 jr14556.exe
+-rw-r--r-- 1 ftpuser ftpusers 161439 May 27 2001 jr14585.exe
+-rw-r--r-- 1 ftpuser ftpusers 161435 Oct 16 2000 jr14586.exe
+-rw-r--r-- 1 ftpuser ftpusers 186037 Oct 16 2000 jr14840.exe
+-rw-r--r-- 1 ftpuser ftpusers 368604 Oct 16 2000 jr14936.exe
+-rw-r--r-- 1 ftpuser ftpusers 115132 Aug 15 2001 jr15013.exe
+-rw-r--r-- 1 ftpuser ftpusers 568164 Aug 15 2001 jr15133.exe
+-rw-r--r-- 1 ftpuser ftpusers 217169 Aug 15 2001 jr15338.exe
+-rw-r--r-- 1 ftpuser ftpusers 362664 Aug 15 2001 jr15396.exe
+-rw-r--r-- 1 ftpuser ftpusers 104143 Aug 15 2001 jr15509.exe
+-rw-r--r-- 1 ftpuser ftpusers 473822 Aug 15 2001 jr15544.exe
+-rw-r--r-- 1 ftpuser ftpusers 484196 Jul 25 2001 jssl11d.exe
+-rw-r--r-- 1 ftpuser ftpusers 36251555 Jul 20 2001 jvm122.exe
+-rw-r--r-- 1 ftpuser ftpusers 49007010 Feb 28 08:06 jvm131.exe
+-rw-r--r-- 1 ftpuser ftpusers 48672254 Mar 28 2001 jzfd3sp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 66469 Jul 17 1997 killq.exe
+-rw-r--r-- 1 ftpuser ftpusers 202716 Mar 1 1994 l11f01.exe
+-rw-r--r-- 1 ftpuser ftpusers 202878 Mar 1 1994 l11g01.exe
+-rw-r--r-- 1 ftpuser ftpusers 202460 Mar 1 1994 l11i01.exe
+-rw-r--r-- 1 ftpuser ftpusers 23583 Jan 6 1994 l11p06.exe
+-rw-r--r-- 1 ftpuser ftpusers 202249 Mar 1 1994 l11s01.exe
+-rw-r--r-- 1 ftpuser ftpusers 30533 Nov 24 1993 l11u05.exe
+-rw-r--r-- 1 ftpuser ftpusers 206616 Apr 20 1999 lanchk.exe
+-rw-r--r-- 1 ftpuser ftpusers 341280 Oct 21 1996 landr9.exe
+-rw-r--r-- 1 ftpuser ftpusers 4610909 May 14 1998 landrv.exe
+-rw-r--r-- 1 ftpuser ftpusers 24799 Sep 10 1996 lanwcs.exe
+-rw-r--r-- 1 ftpuser ftpusers 37088 Sep 4 1996 lanwct.exe
+-rw-r--r-- 1 ftpuser ftpusers 42514 Sep 4 1996 lanwes.exe
+-rw-r--r-- 1 ftpuser ftpusers 42417 Sep 11 1996 lanwfr.exe
+-rw-r--r-- 1 ftpuser ftpusers 36855 Sep 10 1996 lanwha.exe
+-rw-r--r-- 1 ftpuser ftpusers 42397 Sep 4 1996 lanwit.exe
+-rw-r--r-- 1 ftpuser ftpusers 16012931 Jan 31 16:00 lanwp02.exe
+-rw-r--r-- 1 ftpuser ftpusers 342390 Dec 16 1996 lat002.exe
+-rw-r--r-- 1 ftpuser ftpusers 133326 Sep 18 1993 ld401a.exe
+-rw-r--r-- 1 ftpuser ftpusers 166765 Feb 7 2000 ldr312ft.exe
+-rw-r--r-- 1 ftpuser ftpusers 26450 Sep 18 1993 leap.exe
+-rw-r--r-- 1 ftpuser ftpusers 180540 Jun 9 1994 lg4084.exe
+-rw-r--r-- 1 ftpuser ftpusers 91840 Dec 14 1995 lg42l4.exe
+-rw-r--r-- 1 ftpuser ftpusers 72061 Oct 11 1995 li3pre.exe
+-rw-r--r-- 1 ftpuser ftpusers 258605 Jun 2 1998 lib311b.exe
+-rw-r--r-- 1 ftpuser ftpusers 273268 Sep 20 1999 lib312d.exe
+-rw-r--r-- 1 ftpuser ftpusers 977416 Feb 23 2000 libupj4.exe
+-rw-r--r-- 1 ftpuser ftpusers 111269 Jun 26 1995 lo30a2.exe
+-rw-r--r-- 1 ftpuser ftpusers 94927 Jun 26 1995 lo30t1.exe
+-rw-r--r-- 1 ftpuser ftpusers 105128 Sep 18 1993 load.exe
+-rw-r--r-- 1 ftpuser ftpusers 111722 Aug 26 1998 loaddll1.exe
+-rw-r--r-- 1 ftpuser ftpusers 20810 Sep 18 1993 locins.exe
+-rw-r--r-- 1 ftpuser ftpusers 74768 Mar 9 1995 log376.exe
+-rw-r--r-- 1 ftpuser ftpusers 269333 Sep 15 1997 log410a.exe
+-rw-r--r-- 1 ftpuser ftpusers 99524 Feb 23 2000 longnam.exe
+-rw-r--r-- 1 ftpuser ftpusers 1563061 Mar 5 1997 lpo51a.exe
+-rw-r--r-- 1 ftpuser ftpusers 115601 Mar 14 1997 lpo51b.exe
+-rw-r--r-- 1 ftpuser ftpusers 373114 Jun 12 1995 lw42w2.exe
+-rw-r--r-- 1 ftpuser ftpusers 986579 Sep 20 1996 lw50w1.exe
+-rw-r--r-- 1 ftpuser ftpusers 79276 Aug 21 1996 lwg50a.exe
+-rw-r--r-- 1 ftpuser ftpusers 115527 Aug 18 1998 lwp001.exe
+-rw-r--r-- 1 ftpuser ftpusers 54951 Aug 20 1998 lwp002.exe
+-rw-r--r-- 1 ftpuser ftpusers 447982 May 6 1996 lwp413.exe
+-rw-r--r-- 1 ftpuser ftpusers 231591 Nov 30 1994 lwp423.exe
+-rw-r--r-- 1 ftpuser ftpusers 26516 May 18 1998 lwp501.exe
+-rw-r--r-- 1 ftpuser ftpusers 27895 May 15 1998 lwp511.exe
+-rw-r--r-- 1 ftpuser ftpusers 21913 Sep 18 1993 lwpo30.exe
+-rw-r--r-- 1 ftpuser ftpusers 47334 Sep 3 1997 lwpping.exe
+-rw-r--r-- 1 ftpuser ftpusers 356846 Aug 9 1999 lzfw01c.exe
+-rw-r--r-- 1 ftpuser ftpusers 33252 Oct 18 1993 lzfwdi.exe
+-rw-r--r-- 1 ftpuser ftpusers 1083871 Jul 14 1999 lzfwlf.exe
+-rw-r--r-- 1 ftpuser ftpusers 29057 Jun 16 1995 lzfwqa.exe
+-rw-r--r-- 1 ftpuser ftpusers 26848 Sep 7 1994 lzw001.exe
+-rw-r--r-- 1 ftpuser ftpusers 29431 May 16 1995 lzw002.exe
+-rw-r--r-- 1 ftpuser ftpusers 151295 Sep 18 1993 lzw40.exe
+-rw-r--r-- 1 ftpuser ftpusers 29379 Sep 18 1993 m30pat.exe
+-rw-r--r-- 1 ftpuser ftpusers 122720 Jul 24 1996 macfil.exe
+-rw-r--r-- 1 ftpuser ftpusers 347278 Jul 10 1997 macpt3d.exe
+-rw-r--r-- 1 ftpuser ftpusers 193792 May 29 1996 mactsa.bin
+-rw-r--r-- 1 ftpuser ftpusers 232349 Jul 23 1996 mactsa.exe
+-rw-r--r-- 1 ftpuser ftpusers 210004 Feb 21 1996 mailcl.exe
+-rw-r--r-- 1 ftpuser ftpusers 48964 Mar 13 1995 map312.exe
+-rw-r--r-- 1 ftpuser ftpusers 144574 Nov 24 1997 map410b.exe
+-rw-r--r-- 1 ftpuser ftpusers 127956 Oct 10 2001 masv_sp3.exe
+-rw-r--r-- 1 ftpuser ftpusers 266084 Feb 28 2001 mbcmnup1.exe
+-rw-r--r-- 1 ftpuser ftpusers 508288 Aug 13 1998 mclupd6a.bin
+-rw-r--r-- 1 ftpuser ftpusers 22803 Sep 18 1993 mcmfm.exe
+-rw-r--r-- 1 ftpuser ftpusers 37710 Feb 11 1994 mdf178.exe
+-rw-r--r-- 1 ftpuser ftpusers 87520 Sep 18 1993 menu34.exe
+-rw-r--r-- 1 ftpuser ftpusers 20214 Nov 15 1993 menuhi.exe
+-rw-r--r-- 1 ftpuser ftpusers 91376 Sep 18 1993 menus.exe
+-rw-r--r-- 1 ftpuser ftpusers 5040875 Aug 15 2001 mgt22010.exe
+-rw-r--r-- 1 ftpuser ftpusers 683946 Nov 3 1993 mhs173.exe
+-rw-r--r-- 1 ftpuser ftpusers 656047 Feb 14 1994 mhs183.exe
+-rw-r--r-- 1 ftpuser ftpusers 664789 Feb 7 1994 mhs184.exe
+-rw-r--r-- 1 ftpuser ftpusers 85281 Nov 3 1997 mhsmcu.exe
+-rw-r--r-- 1 ftpuser ftpusers 54627 Sep 18 1993 mhsmd.exe
+-rw-r--r-- 1 ftpuser ftpusers 604103 Aug 16 1994 mhsslt.exe
+-rw-r--r-- 1 ftpuser ftpusers 132603 Jun 30 1995 mhsvr1.exe
+-rw-r--r-- 1 ftpuser ftpusers 449605 Aug 1 1996 migrat.exe
+-rw-r--r-- 1 ftpuser ftpusers 33708 Sep 18 1993 mirrem.exe
+-rw-r--r-- 1 ftpuser ftpusers 27044 Jan 5 2000 mixmod6.exe
+-rw-r--r-- 1 ftpuser ftpusers 96673 Sep 18 1993 mkuser.exe
+-rw-r--r-- 1 ftpuser ftpusers 68504 Sep 18 1995 mon176.exe
+-rw-r--r-- 1 ftpuser ftpusers 66024 May 18 1995 monsft.exe
+-rw-r--r-- 1 ftpuser ftpusers 424897 Sep 18 1993 morebk.exe
+-rw-r--r-- 1 ftpuser ftpusers 37818 Sep 18 1993 mountr.exe
+-rw-r--r-- 1 ftpuser ftpusers 19452 Sep 18 1993 mouse.exe
+-rw-r--r-- 1 ftpuser ftpusers 32801 Feb 3 1994 mpr182.exe
+-rw-r--r-- 1 ftpuser ftpusers 125166 Jul 15 1994 mpr199.exe
+-rw-r--r-- 1 ftpuser ftpusers 1066126 Jun 4 1996 mpr31a.exe
+-rw-r--r-- 1 ftpuser ftpusers 1082729 Oct 28 1996 mpr31b.exe
+-rw-r--r-- 1 ftpuser ftpusers 31245 Sep 23 1994 mprper.exe
+-rw-r--r-- 1 ftpuser ftpusers 38997 Mar 24 1995 mprul3.exe
+-rw-r--r-- 1 ftpuser ftpusers 122440 Oct 11 1995 mprx25.exe
+-rw-r--r-- 1 ftpuser ftpusers 328085 Aug 2 1996 msml21.exe
+-rw-r--r-- 1 ftpuser ftpusers 5876316 Oct 5 1998 msmlos21.exe
+-rw-r--r-- 1 ftpuser ftpusers 70822 Aug 2 1999 msmpcu.exe
+-rw-r--r-- 1 ftpuser ftpusers 6355314 May 31 2000 mw26sp3.exe
+-rw-r--r-- 1 ftpuser ftpusers 119531 Jul 31 2000 mw26trd1.exe
+-rw-r--r-- 1 ftpuser ftpusers 3054719 Nov 13 2000 mw27sp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 27173 Nov 23 1999 mw5mcal1.exe
+-rw-r--r-- 1 ftpuser ftpusers 253007 May 17 2000 mwhp01b.exe
+-rw-r--r-- 1 ftpuser ftpusers 255066 Jan 25 11:47 mwhp01c.exe
+-rw-r--r-- 1 ftpuser ftpusers 9813556 Sep 1 2000 mwinoc1k.exe
+-rw-r--r-- 1 ftpuser ftpusers 8298211 Sep 1 2000 mwinoc2k.exe
+-rw-r--r-- 1 ftpuser ftpusers 141530 Feb 20 14:35 mwipgrop.exe
+-rw-r--r-- 1 ftpuser ftpusers 566807 Oct 9 1996 mwmis01.exe
+-rw-r--r-- 1 ftpuser ftpusers 1070535 Jan 26 1999 mwnma26.exe
+-rw-r--r-- 1 ftpuser ftpusers 265545 Oct 16 1998 mwnma3a.exe
+-rw-r--r-- 1 ftpuser ftpusers 300304 Oct 16 1998 mwnma4a.exe
+-rw-r--r-- 1 ftpuser ftpusers 2180810 Apr 12 2001 mwnmaupd.exe
+-rw-r--r-- 1 ftpuser ftpusers 154598 Jan 12 2000 mwnxp26.exe
+-rw-r--r-- 1 ftpuser ftpusers 339201 Apr 9 2001 mwnxpfix.exe
+-rw-r--r-- 1 ftpuser ftpusers 1502706 Aug 20 1999 mwzen01.exe
+-rw-r--r-- 1 ftpuser ftpusers 58460632 Mar 28 2001 mzfd3sp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 2407200 May 24 2001 n51_nis1.exe
+-rw-r--r-- 1 ftpuser ftpusers 6840962 May 16 2000 n8slinux.01
+-rw-r--r-- 1 ftpuser ftpusers 217465 Feb 18 1998 na4nty2k.exe
+-rw-r--r-- 1 ftpuser ftpusers 48510 Sep 18 1993 nacs2.exe
+-rw-r--r-- 1 ftpuser ftpusers 64238 May 28 1996 nadhep.exe
+-rw-r--r-- 1 ftpuser ftpusers 1777018 Mar 23 1999 nal201p2.exe
+-rw-r--r-- 1 ftpuser ftpusers 38276 Oct 29 1996 nam312.exe
+-rw-r--r-- 1 ftpuser ftpusers 199571 Jun 6 2000 nam41d.exe
+-rw-r--r-- 1 ftpuser ftpusers 104382 May 24 15:12 nat600d.exe
+-rw-r--r-- 1 ftpuser ftpusers 322806 Sep 18 1993 nbckup.exe
+-rw-r--r-- 1 ftpuser ftpusers 21328 Jan 10 1997 nbora.exe
+-rw-r--r-- 1 ftpuser ftpusers 18843 Aug 12 1997 nc1tip.txt
+-rw-r--r-- 1 ftpuser ftpusers 838367 Jun 3 09:30 nccutl10.exe
+-rw-r--r-- 1 ftpuser ftpusers 7725859 Oct 24 2000 nce8slr1.z
+-rw-r--r-- 1 ftpuser ftpusers 77251 Sep 18 1993 nconfg.exe
+-rw-r--r-- 1 ftpuser ftpusers 19889 Oct 10 1997 ncpec.exe
+-rw-r--r-- 1 ftpuser ftpusers 144892 Sep 15 1997 ncpy410a.exe
+-rw-r--r-- 1 ftpuser ftpusers 136962 Nov 21 2000 ncs3.exe
+-rw-r--r-- 1 ftpuser ftpusers 704205 Oct 1 1996 ncv201.exe
+-rw-r--r-- 1 ftpuser ftpusers 811853 Oct 1 1996 ncv202.exe
+-rw-r--r-- 1 ftpuser ftpusers 489774 Apr 21 1998 ncv20y2k.exe
+-rw-r--r-- 1 ftpuser ftpusers 142314 Nov 12 2001 ndb410q.exe
+-rw-r--r-- 1 ftpuser ftpusers 820712 Feb 21 13:36 ndp21p3c.exe
+-rw-r--r-- 1 ftpuser ftpusers 853818 Jun 21 12:06 ndp21p4.exe
+-rw-r--r-- 1 ftpuser ftpusers 1008445 Oct 17 2001 ndp2xp7.exe
+-rw-r--r-- 1 ftpuser ftpusers 530101 Feb 21 13:53 ndpcnw6.exe
+-rw-r--r-- 1 ftpuser ftpusers 909348 Feb 21 13:48 ndpcsp3a.exe
+-rw-r--r-- 1 ftpuser ftpusers 94047 Jul 17 2001 ndpsinf.exe
+-rw-r--r-- 1 ftpuser ftpusers 11673051 Oct 4 2001 ndpsw2k.exe
+-rw-r--r-- 1 ftpuser ftpusers 59495 Sep 18 1993 ndr345.exe
+-rw-r--r-- 1 ftpuser ftpusers 112722 Feb 2 2000 nds4ntp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 507960 Aug 17 2000 nds4ntu3.exe
+-rw-r--r-- 1 ftpuser ftpusers 3437308 Oct 27 2000 nds8lnx1.gz
+-rw-r--r-- 1 ftpuser ftpusers 14133762 Jul 17 2001 ndsas3s1.exe
+-rw-r--r-- 1 ftpuser ftpusers 24182 Sep 18 1993 ndscsi.exe
+-rw-r--r-- 1 ftpuser ftpusers 41652 Sep 18 1993 ndspx.exe
+-rw-r--r-- 1 ftpuser ftpusers 6712 Jul 20 2000 ndssch.gz
+-rw-r--r-- 1 ftpuser ftpusers 20023 Sep 18 1993 ndstac.exe
+-rw-r--r-- 1 ftpuser ftpusers 211239 Sep 18 1993 ne286.exe
+-rw-r--r-- 1 ftpuser ftpusers 5894979 Oct 24 2000 ned8slr1.z
+-rw-r--r-- 1 ftpuser ftpusers 82148198 May 3 2000 nesn451a.exe
+-rw-r--r-- 1 ftpuser ftpusers 1157470 Dec 20 2000 nesn51b.exe
+-rw-r--r-- 1 ftpuser ftpusers 866140 Nov 28 2001 nesn51c.exe
+-rw-r--r-- 1 ftpuser ftpusers 865375 Mar 5 06:54 nesn51d.exe
+-rw-r--r-- 1 ftpuser ftpusers 138202 Mar 16 1999 netarng3.exe
+-rw-r--r-- 1 ftpuser ftpusers 73822 Feb 4 1998 netfr.exe
+-rw-r--r-- 1 ftpuser ftpusers 306211 Mar 12 1996 netusr.exe
+-rw-r--r-- 1 ftpuser ftpusers 74054 Feb 4 1998 netwbr.exe
+-rw-r--r-- 1 ftpuser ftpusers 56229 Feb 4 1998 netwde.exe
+-rw-r--r-- 1 ftpuser ftpusers 27699 Aug 28 1996 netwdk.exe
+-rw-r--r-- 1 ftpuser ftpusers 67776 Feb 2 1998 netwes.exe
+-rw-r--r-- 1 ftpuser ftpusers 59210 Feb 12 1998 netwit.exe
+-rw-r--r-- 1 ftpuser ftpusers 28000 Aug 28 1996 netwno.exe
+-rw-r--r-- 1 ftpuser ftpusers 53501 Sep 10 1996 netwru.exe
+-rw-r--r-- 1 ftpuser ftpusers 27741 Aug 23 1996 netwsv.exe
+-rw-r--r-- 1 ftpuser ftpusers 1539054 Mar 18 15:27 nfap1sp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 290090 Aug 22 1994 nfs193.exe
+-rw-r--r-- 1 ftpuser ftpusers 2266015 Dec 30 1997 nfs203.exe
+-rw-r--r-- 1 ftpuser ftpusers 2007873 Nov 23 1998 nfs205.exe
+-rw-r--r-- 1 ftpuser ftpusers 6472548 Jul 20 2001 nfs30sp2.exe
+-rw-r--r-- 1 ftpuser ftpusers 1310460 Mar 6 15:56 nfs30sp3a.exe
+-rw-r--r-- 1 ftpuser ftpusers 1186381 May 29 14:59 nfs3nwci.exe
+-rw-r--r-- 1 ftpuser ftpusers 5440307 Aug 28 2001 nfs3sp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 1280002 Feb 2 2001 nfsadmn2.exe
+-rw-r--r-- 1 ftpuser ftpusers 38114 Jan 20 1998 nfsmlaup.exe
+-rw-r--r-- 1 ftpuser ftpusers 35803 Aug 2 1999 nfsnam23.exe
+-rw-r--r-- 1 ftpuser ftpusers 245015 Sep 18 1993 ngm121.exe
+-rw-r--r-- 1 ftpuser ftpusers 1240500 Sep 18 1993 ngm137.exe
+-rw-r--r-- 1 ftpuser ftpusers 145298 Sep 18 1993 ngm138.exe
+-rw-r--r-- 1 ftpuser ftpusers 145010 Sep 18 1993 ngm139.exe
+-rw-r--r-- 1 ftpuser ftpusers 781292 Oct 28 1993 ngm170.exe
+-rw-r--r-- 1 ftpuser ftpusers 202093 Dec 3 1993 ngm175.exe
+-rw-r--r-- 1 ftpuser ftpusers 201248 Dec 6 1993 ngm176.exe
+-rw-r--r-- 1 ftpuser ftpusers 279862 May 26 1994 ngm192.exe
+-rw-r--r-- 1 ftpuser ftpusers 945888 Dec 20 1996 ngm211.exe
+-rw-r--r-- 1 ftpuser ftpusers 1403369 Aug 5 1995 ngwadm.exe
+-rw-r--r-- 1 ftpuser ftpusers 1810533 Aug 13 1996 ngwaup.exe
+-rw-r--r-- 1 ftpuser ftpusers 106862 Oct 31 1995 ngwmfc.exe
+-rw-r--r-- 1 ftpuser ftpusers 662953 Mar 15 1995 ngwsnc.exe
+-rw-r--r-- 1 ftpuser ftpusers 27283 Sep 18 1993 ni5010.exe
+-rw-r--r-- 1 ftpuser ftpusers 786223 Jul 10 2001 nicid157.exe
+-rw-r--r-- 1 ftpuser ftpusers 761229 Jul 10 2001 nicie157.exe
+-rw-r--r-- 1 ftpuser ftpusers 59300 Jan 15 11:38 nicimig.tgz
+-rw-r--r-- 1 ftpuser ftpusers 6802379 Jan 17 09:35 nims265.tgz
+-rw-r--r-- 1 ftpuser ftpusers 2526415 Jan 31 10:19 nims265.zip
+-rw-r--r-- 1 ftpuser ftpusers 121765 Jan 31 11:14 nims265a.zip
+-rw-r--r-- 1 ftpuser ftpusers 4894646 Jan 14 16:09 nims26l.tgz
+-rw-r--r-- 1 ftpuser ftpusers 2492982 Jan 14 16:05 nims26n.zip
+-rw-r--r-- 1 ftpuser ftpusers 5385381 Feb 27 16:49 nims26sb.z
+-rw-r--r-- 1 ftpuser ftpusers 343052 Nov 8 1999 nims2_1a.exe
+-rw-r--r-- 1 ftpuser ftpusers 12495019 Apr 15 15:54 nims303.tar.z
+-rw-r--r-- 1 ftpuser ftpusers 7563916 Apr 15 15:53 nims303.tgz
+-rw-r--r-- 1 ftpuser ftpusers 7696073 Apr 15 15:54 nims303.zip
+-rw-r--r-- 1 ftpuser ftpusers 1252720 May 23 1997 nip202.exe
+-rw-r--r-- 1 ftpuser ftpusers 1180104 Oct 23 1998 nip203.exe
+-rw-r--r-- 1 ftpuser ftpusers 6212358 Apr 19 1996 nip22b.exe
+-rw-r--r-- 1 ftpuser ftpusers 555990 Jul 9 1996 nip318.exe
+-rw-r--r-- 1 ftpuser ftpusers 69020 Jul 9 1996 nip319.exe
+-rw-r--r-- 1 ftpuser ftpusers 2489203 Nov 2 2001 nipp10a.exe
+-rw-r--r-- 1 ftpuser ftpusers 3753117 Sep 19 2000 nipt1.exe
+-rw-r--r-- 1 ftpuser ftpusers 6369467 Mar 5 1996 nipw22.exe
+-rw-r--r-- 1 ftpuser ftpusers 42316 May 29 1996 nipw2x.exe
+-rw-r--r-- 1 ftpuser ftpusers 4286209 Jun 7 2000 njcl5a.exe
+-rw-r--r-- 1 ftpuser ftpusers 102325 Jun 10 1998 nls212.exe
+-rw-r--r-- 1 ftpuser ftpusers 155414 Jul 24 2000 nlsdll.exe
+-rw-r--r-- 1 ftpuser ftpusers 16952278 May 25 2001 nlslsp6.exe
+-rw-r--r-- 1 ftpuser ftpusers 215729 Jan 4 2000 nlsty2k.exe
+-rw-r--r-- 1 ftpuser ftpusers 1462112 Nov 28 1995 nms002.exe
+-rw-r--r-- 1 ftpuser ftpusers 48618 Mar 8 1994 nmsddf.exe
+-rw-r--r-- 1 ftpuser ftpusers 434841 Nov 15 1994 nmsxp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 28499 Sep 18 1993 nnscpt.exe
+-rw-r--r-- 1 ftpuser ftpusers 88964 Sep 18 1993 nnst40.exe
+-rw-r--r-- 1 ftpuser ftpusers 89092 Sep 18 1993 nnstll.exe
+-rw-r--r-- 1 ftpuser ftpusers 32483 Jul 25 1995 not131.exe
+-rw-r--r-- 1 ftpuser ftpusers 6707094 Oct 12 1998 notes41.exe
+-rw-r--r-- 1 ftpuser ftpusers 4556171 Jun 8 2000 notes51.exe
+-rw-r--r-- 1 ftpuser ftpusers 24900 Sep 18 1993 novadf.exe
+-rw-r--r-- 1 ftpuser ftpusers 30691 Sep 18 1993 np600a.exe
+-rw-r--r-- 1 ftpuser ftpusers 17097790 Aug 2 1999 nppb_1.exe
+-rw-r--r-- 1 ftpuser ftpusers 17097771 Aug 2 1999 nppb_2.exe
+-rw-r--r-- 1 ftpuser ftpusers 633317 Mar 15 16:33 nps15dpa.exe
+-rw-r--r-- 1 ftpuser ftpusers 31183790 Jun 28 09:08 nps15sp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 8200267 Sep 10 2001 npsgad01.exe
+-rw-r--r-- 1 ftpuser ftpusers 114902 Apr 12 2001 npsnsapi.exe
+-rw-r--r-- 1 ftpuser ftpusers 615863 Feb 11 15:57 nptr95b.exe
+-rw-r--r-- 1 ftpuser ftpusers 22915 Jun 30 1997 nrsbuild.exe
+-rw-r--r-- 1 ftpuser ftpusers 793469 Jun 23 1997 nrsnt.exe
+-rw-r--r-- 1 ftpuser ftpusers 53586091 Jun 18 1998 nsbgwsp3.exe
+-rw-r--r-- 1 ftpuser ftpusers 455182 Mar 22 1994 nsd004.exe
+-rw-r--r-- 1 ftpuser ftpusers 1964329 Aug 21 1998 nsr511n.zip
+-rw-r--r-- 1 ftpuser ftpusers 1935353 Jun 24 1996 nsrtr51n.zip
+-rw-r--r-- 1 ftpuser ftpusers 93785 Feb 13 13:36 nsschk1a.exe
+-rw-r--r-- 1 ftpuser ftpusers 116845 Jul 30 1997 nsync1.exe
+-rw-r--r-- 1 ftpuser ftpusers 10933860 Sep 16 1999 nt411b.exe
+-rw-r--r-- 1 ftpuser ftpusers 1084753 Oct 26 1998 nt411p1.exe
+-rw-r--r-- 1 ftpuser ftpusers 744586 Apr 6 1999 nt430p2.exe
+-rw-r--r-- 1 ftpuser ftpusers 834534 Jun 22 1999 nt451p1.exe
+-rw-r--r-- 1 ftpuser ftpusers 920405 Mar 23 2000 nt46pt1.exe
+-rw-r--r-- 1 ftpuser ftpusers 4017917 Oct 3 1999 nt46sp2.exe
+-rw-r--r-- 1 ftpuser ftpusers 765887 Aug 11 2000 nt471pt2.exe
+-rw-r--r-- 1 ftpuser ftpusers 448015 Jun 13 2000 nt47pt3.exe
+-rw-r--r-- 1 ftpuser ftpusers 1081217 May 9 07:26 nt480pt5.exe
+-rw-r--r-- 1 ftpuser ftpusers 898400 Nov 6 2001 nt481pt1.exe
+-rw-r--r-- 1 ftpuser ftpusers 291026 Jun 14 14:07 nt483pt2.exe
+-rw-r--r-- 1 ftpuser ftpusers 150230 Nov 19 1998 ntprint.exe
+-rw-r--r-- 1 ftpuser ftpusers 114593 Jul 18 1995 ntwin.exe
+-rw-r--r-- 1 ftpuser ftpusers 28138 Sep 18 1993 nver30.exe
+-rw-r--r-- 1 ftpuser ftpusers 28798 Jan 7 1997 nw3dfs.exe
+-rw-r--r-- 1 ftpuser ftpusers 24257 Jan 7 1997 nw4dfs.exe
+-rw-r--r-- 1 ftpuser ftpusers 80377034 Nov 13 2000 nw4sp9.exe
+-rw-r--r-- 1 ftpuser ftpusers 866224 Aug 27 2001 nw4wsock.exe
+-rw-r--r-- 1 ftpuser ftpusers 158210659 Dec 20 2000 nw50sp6a.exe
+-rw-r--r-- 1 ftpuser ftpusers 490599 Jul 23 2001 nw51fs1.exe
+-rw-r--r-- 1 ftpuser ftpusers 684981 Feb 17 2000 nw51inst.exe
+-rw-r--r-- 1 ftpuser ftpusers 513640 Aug 21 2001 nw51nrm1.exe
+-rw-r--r-- 1 ftpuser ftpusers 294037836 Jul 24 2001 nw51sp3.exe
+-rw-r--r-- 1 ftpuser ftpusers 300006242 Feb 25 11:26 nw51sp4.exe
+-rw-r--r-- 1 ftpuser ftpusers 332610 Apr 27 2000 nw51upd1.exe
+-rw-r--r-- 1 ftpuser ftpusers 3250529 Jun 24 14:54 nw56up1.exe
+-rw-r--r-- 1 ftpuser ftpusers 38435 Sep 9 1999 nw5nss.exe
+-rw-r--r-- 1 ftpuser ftpusers 251511 Feb 17 2000 nw5nwip.exe
+-rw-r--r-- 1 ftpuser ftpusers 169896 May 16 2000 nw5psrv2.exe
+-rw-r--r-- 1 ftpuser ftpusers 378831 Jun 20 2000 nw5tcp.exe
+-rw-r--r-- 1 ftpuser ftpusers 1533365 Mar 22 16:33 nw6nss1a.exe
+-rw-r--r-- 1 ftpuser ftpusers 633339 Oct 22 2001 nw6sms1a.exe
+-rw-r--r-- 1 ftpuser ftpusers 237785656 Mar 6 17:15 nw6sp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 568253661 Mar 11 12:19 nw6sp1ef.exe
+-rw-r--r-- 1 ftpuser ftpusers 567439767 Mar 11 12:59 nw6sp1ef56.exe
+-rw-r--r-- 1 ftpuser ftpusers 566604272 Mar 22 12:23 nw6sp1eg.exe
+-rw-r--r-- 1 ftpuser ftpusers 566458792 Mar 22 13:02 nw6sp1ei.exe
+-rw-r--r-- 1 ftpuser ftpusers 566528467 Mar 11 10:57 nw6sp1ep.exe
+-rw-r--r-- 1 ftpuser ftpusers 567333526 Mar 22 16:05 nw6sp1er.exe
+-rw-r--r-- 1 ftpuser ftpusers 565955338 Mar 13 16:55 nw6sp1es.exe
+-rw-r--r-- 1 ftpuser ftpusers 1344552 Mar 23 1999 nwadmnp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 478371 May 10 1995 nwc001.exe
+-rw-r--r-- 1 ftpuser ftpusers 251557 Feb 24 1995 nwc002.exe
+-rw-r--r-- 1 ftpuser ftpusers 1598884 Jan 31 1996 nwc201.exe
+-rw-r--r-- 1 ftpuser ftpusers 1524102 Nov 22 1995 nwc202.exe
+-rw-r--r-- 1 ftpuser ftpusers 1328082 Jan 22 1998 nwc206.exe
+-rw-r--r-- 1 ftpuser ftpusers 1382188 Nov 18 1996 nwc207.exe
+-rw-r--r-- 1 ftpuser ftpusers 547655 Oct 24 1996 nwc208.exe
+-rw-r--r-- 1 ftpuser ftpusers 29587 Aug 12 1997 nwc2tp.txt
+-rw-r--r-- 1 ftpuser ftpusers 21386 Sep 18 1993 nwc386.exe
+-rw-r--r-- 1 ftpuser ftpusers 102446 Oct 5 1994 nwcdll.exe
+-rw-r--r-- 1 ftpuser ftpusers 33443 Feb 27 1996 nwcinf.exe
+-rw-r--r-- 1 ftpuser ftpusers 22331 Sep 11 1998 nwcmod.exe
+-rw-r--r-- 1 ftpuser ftpusers 71514 Sep 20 1995 nwcncs.exe
+-rw-r--r-- 1 ftpuser ftpusers 37424 Jul 11 1997 nwcppp.exe
+-rw-r--r-- 1 ftpuser ftpusers 36603464 Mar 13 2000 nwcssp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 170397 Mar 23 2000 nwcsupd1.exe
+-rw-r--r-- 1 ftpuser ftpusers 367734 Feb 14 1995 nwcwin.exe
+-rw-r--r-- 1 ftpuser ftpusers 367002 May 22 1998 nwcwrt.exe
+-rw-r--r-- 1 ftpuser ftpusers 77941 Dec 16 1996 nwda01.exe
+-rw-r--r-- 1 ftpuser ftpusers 147838 May 8 12:21 nwftpd6.exe
+-rw-r--r-- 1 ftpuser ftpusers 128211 Jan 29 15:30 nwipadm4.exe
+-rw-r--r-- 1 ftpuser ftpusers 571623 Nov 1 1995 nwl11e.exe
+-rw-r--r-- 1 ftpuser ftpusers 579046 Nov 1 1995 nwl11f.exe
+-rw-r--r-- 1 ftpuser ftpusers 585907 Nov 1 1995 nwl11g.exe
+-rw-r--r-- 1 ftpuser ftpusers 576676 Nov 1 1995 nwl11i.exe
+-rw-r--r-- 1 ftpuser ftpusers 579137 Nov 1 1995 nwl11s.exe
+-rw-r--r-- 1 ftpuser ftpusers 184137 Dec 13 1995 nwltid.exe
+-rw-r--r-- 1 ftpuser ftpusers 13639159 Apr 9 1999 nwmac.exe
+-rw-r--r-- 1 ftpuser ftpusers 2264037 Mar 23 1999 nwmp2.exe
+-rw-r--r-- 1 ftpuser ftpusers 16902888 Jun 15 2001 nwovly2.exe
+-rw-r--r-- 1 ftpuser ftpusers 2536221 Apr 2 1997 nwpa300.exe
+-rw-r--r-- 1 ftpuser ftpusers 155727 May 7 2001 nwpa5.exe
+-rw-r--r-- 1 ftpuser ftpusers 254835 Dec 7 2001 nwpapt2a.exe
+-rw-r--r-- 1 ftpuser ftpusers 26440 Nov 15 1993 nwparr.exe
+-rw-r--r-- 1 ftpuser ftpusers 1341903 Jun 9 1999 nwpaup1a.exe
+-rw-r--r-- 1 ftpuser ftpusers 7763041 Feb 27 1997 nws25b.exe
+-rw-r--r-- 1 ftpuser ftpusers 73306 Mar 11 1999 nwsaahpr.exe
+-rw-r--r-- 1 ftpuser ftpusers 12091868 Feb 29 2000 nwsb41wa.exe
+-rw-r--r-- 1 ftpuser ftpusers 38819 Aug 11 1999 nwsp2aai.exe
+-rw-r--r-- 1 ftpuser ftpusers 287681 Feb 4 2000 nwsso.exe
+-rw-r--r-- 1 ftpuser ftpusers 112641 Feb 24 2000 nwtape1.exe
+-rw-r--r-- 1 ftpuser ftpusers 66111 Nov 15 1993 nwtlg.exe
+-rw-r--r-- 1 ftpuser ftpusers 126883 Jun 16 1995 o31mci.exe
+-rw-r--r-- 1 ftpuser ftpusers 73911 Jul 25 1995 o4crtl.exe
+-rw-r--r-- 1 ftpuser ftpusers 4957532 Apr 27 1999 odbcbeta.exe
+-rw-r--r-- 1 ftpuser ftpusers 6488080 Nov 8 2001 odemandb.exe
+-rw-r--r-- 1 ftpuser ftpusers 671132 Jul 28 1999 odi33g.exe
+-rw-r--r-- 1 ftpuser ftpusers 409920 Jul 30 1997 odiwan1.exe
+-rw-r--r-- 1 ftpuser ftpusers 48296 Jul 18 1995 of31pt.exe
+-rw-r--r-- 1 ftpuser ftpusers 111219 Sep 18 1993 os2p1.exe
+-rw-r--r-- 1 ftpuser ftpusers 610164 Dec 18 1998 os2pt2.exe
+-rw-r--r-- 1 ftpuser ftpusers 896477 Nov 26 1996 os2u1.exe
+-rw-r--r-- 1 ftpuser ftpusers 4229434 May 30 2000 os4pt1.exe
+-rw-r--r-- 1 ftpuser ftpusers 4227811 Mar 2 2001 os5pt2a.exe
+-rw-r--r-- 1 ftpuser ftpusers 216072 Sep 18 1993 othdrv.exe
+-rw-r--r-- 1 ftpuser ftpusers 66394 Dec 4 1996 ovvmdl.exe
+-rw-r--r-- 1 ftpuser ftpusers 26153 Oct 25 1996 p1000.exe
+-rw-r--r-- 1 ftpuser ftpusers 242785 Jan 3 1995 p10g05.exe
+-rw-r--r-- 1 ftpuser ftpusers 242514 Jan 3 1995 p10i05.exe
+-rw-r--r-- 1 ftpuser ftpusers 242647 Jan 3 1995 p10s05.exe
+-rw-r--r-- 1 ftpuser ftpusers 33893 May 12 1995 p2scsi.exe
+-rw-r--r-- 1 ftpuser ftpusers 659891 May 11 1999 pager1.exe
+-rw-r--r-- 1 ftpuser ftpusers 50002 Sep 18 1993 pat301.exe
+-rw-r--r-- 1 ftpuser ftpusers 50015 Sep 18 1993 pat303.exe
+-rw-r--r-- 1 ftpuser ftpusers 49975 Sep 18 1993 pat304.exe
+-rw-r--r-- 1 ftpuser ftpusers 49878 Sep 18 1993 pat306.exe
+-rw-r--r-- 1 ftpuser ftpusers 29863 Sep 18 1993 pat311.exe
+-rw-r--r-- 1 ftpuser ftpusers 49888 Sep 18 1993 pat312.exe
+-rw-r--r-- 1 ftpuser ftpusers 49823 Sep 18 1993 pat314.exe
+-rw-r--r-- 1 ftpuser ftpusers 33034 Sep 18 1993 pat315.exe
+-rw-r--r-- 1 ftpuser ftpusers 49900 Sep 18 1993 pat317.exe
+-rw-r--r-- 1 ftpuser ftpusers 49858 Sep 18 1993 pat321.exe
+-rw-r--r-- 1 ftpuser ftpusers 49901 Sep 18 1993 pat323.exe
+-rw-r--r-- 1 ftpuser ftpusers 50232 Sep 18 1993 pat326.exe
+-rw-r--r-- 1 ftpuser ftpusers 49842 Sep 18 1993 pat334.exe
+-rw-r--r-- 1 ftpuser ftpusers 49930 Sep 18 1993 pat354.exe
+-rw-r--r-- 1 ftpuser ftpusers 30322 Sep 18 1993 patman.exe
+-rw-r--r-- 1 ftpuser ftpusers 35789 Sep 18 1993 paudfx.exe
+-rw-r--r-- 1 ftpuser ftpusers 565974 Jul 20 1998 pbm21y2k.exe
+-rw-r--r-- 1 ftpuser ftpusers 63237 Jun 15 1994 pburst.exe
+-rw-r--r-- 1 ftpuser ftpusers 35522 Sep 18 1993 pcn22x.exe
+-rw-r--r-- 1 ftpuser ftpusers 25266 Sep 18 1993 pcn23x.exe
+-rw-r--r-- 1 ftpuser ftpusers 46823 Sep 18 1993 pcn2pa.exe
+-rw-r--r-- 1 ftpuser ftpusers 30816 Sep 18 1993 pcnscs.exe
+-rw-r--r-- 1 ftpuser ftpusers 22801 Sep 18 1993 pdf.exe
+-rw-r--r-- 1 ftpuser ftpusers 38018 Sep 18 1993 pdf311.exe
+-rw-r--r-- 1 ftpuser ftpusers 8552350 Aug 27 2001 pdlckcmp.exe
+-rw-r--r-- 1 ftpuser ftpusers 699150 Jan 22 1997 perfectf.exe
+-rw-r--r-- 1 ftpuser ftpusers 214597 Jun 7 2000 pfar6.exe
+-rw-r--r-- 1 ftpuser ftpusers 26618 Sep 18 1993 pfix1.exe
+-rw-r--r-- 1 ftpuser ftpusers 26734 Sep 18 1993 pfix3.exe
+-rw-r--r-- 1 ftpuser ftpusers 23435 Jul 18 1995 pifoff.exe
+-rw-r--r-- 1 ftpuser ftpusers 70799 Aug 26 1999 pkernel.exe
+-rw-r--r-- 1 ftpuser ftpusers 252312 Aug 12 1999 pkis.pdf
+-rw-r--r-- 1 ftpuser ftpusers 772450 Feb 8 2000 pkisnmas.exe
+-rw-r--r-- 1 ftpuser ftpusers 63891 Sep 11 1995 plpd8.exe
+-rw-r--r-- 1 ftpuser ftpusers 212389 Mar 28 12:17 plpdsoc2.exe
+-rw-r--r-- 1 ftpuser ftpusers 181777 Dec 13 1995 pnwtid.exe
+-rw-r--r-- 1 ftpuser ftpusers 186437 Nov 17 1995 pnxtfx.exe
+-rw-r--r-- 1 ftpuser ftpusers 4463887 Jan 3 2001 preds8a.exe
+-rw-r--r-- 1 ftpuser ftpusers 75026 Sep 18 1993 pro10.exe
+-rw-r--r-- 1 ftpuser ftpusers 28781 Nov 1 1995 prog.exe
+-rw-r--r-- 1 ftpuser ftpusers 23802 Sep 18 1993 propth.exe
+-rw-r--r-- 1 ftpuser ftpusers 25129 Jan 29 1996 prt312.exe
+-rw-r--r-- 1 ftpuser ftpusers 31193 Sep 18 1993 prtime.exe
+-rw-r--r-- 1 ftpuser ftpusers 130827 Jul 20 1995 prupc.exe
+-rw-r--r-- 1 ftpuser ftpusers 34893 Sep 18 1993 ps110.exe
+-rw-r--r-- 1 ftpuser ftpusers 25963 Sep 18 1993 ps2286.exe
+-rw-r--r-- 1 ftpuser ftpusers 24576 Sep 18 1993 ps22is.exe
+-rw-r--r-- 1 ftpuser ftpusers 42925 Sep 18 1993 ps2311.exe
+-rw-r--r-- 1 ftpuser ftpusers 29867 Sep 18 1993 ps2386.exe
+-rw-r--r-- 1 ftpuser ftpusers 28205 Sep 18 1993 ps2cmb.exe
+-rw-r--r-- 1 ftpuser ftpusers 23372 Sep 18 1993 ps2esd.exe
+-rw-r--r-- 1 ftpuser ftpusers 24336 Sep 18 1993 ps2fx.exe
+-rw-r--r-- 1 ftpuser ftpusers 76207 Sep 18 1993 ps2isa.exe
+-rw-r--r-- 1 ftpuser ftpusers 23955 Sep 18 1993 ps2m57.exe
+-rw-r--r-- 1 ftpuser ftpusers 36351 Dec 14 1993 ps2opt.exe
+-rw-r--r-- 1 ftpuser ftpusers 162367 Jun 30 1995 ps3x02.exe
+-rw-r--r-- 1 ftpuser ftpusers 85566 Jan 23 1996 ps4x03.exe
+-rw-r--r-- 1 ftpuser ftpusers 172677 Oct 24 2001 psrvr112.exe
+-rw-r--r-- 1 ftpuser ftpusers 52324 Sep 18 1993 ptf286.exe
+-rw-r--r-- 1 ftpuser ftpusers 112633 Sep 18 1993 ptf350.exe
+-rw-r--r-- 1 ftpuser ftpusers 48074 Sep 18 1993 ptf374.exe
+-rw-r--r-- 1 ftpuser ftpusers 39025 Sep 18 1993 ptf378.exe
+-rw-r--r-- 1 ftpuser ftpusers 30600 Sep 18 1993 ptf380.exe
+-rw-r--r-- 1 ftpuser ftpusers 525519 Mar 25 1994 ptf410.exe
+-rw-r--r-- 1 ftpuser ftpusers 501986 Sep 29 1993 ptf411.exe
+-rw-r--r-- 1 ftpuser ftpusers 350294 Sep 29 1993 ptf412.exe
+-rw-r--r-- 1 ftpuser ftpusers 473981 Sep 29 1993 ptf413.exe
+-rw-r--r-- 1 ftpuser ftpusers 480777 Sep 29 1993 ptf414.exe
+-rw-r--r-- 1 ftpuser ftpusers 488223 Sep 29 1993 ptf415.exe
+-rw-r--r-- 1 ftpuser ftpusers 147005 Oct 22 1993 ptf424.exe
+-rw-r--r-- 1 ftpuser ftpusers 109320 Aug 14 1995 ptf425.exe
+-rw-r--r-- 1 ftpuser ftpusers 109064 Oct 18 1993 ptf426.exe
+-rw-r--r-- 1 ftpuser ftpusers 292097 Oct 7 1994 ptf437.exe
+-rw-r--r-- 1 ftpuser ftpusers 464842 Apr 12 1994 ptf569.exe
+-rw-r--r-- 1 ftpuser ftpusers 453054 Nov 16 1994 pu3x01.exe
+-rw-r--r-- 1 ftpuser ftpusers 553603 May 2 1995 pu4x03.exe
+-rw-r--r-- 1 ftpuser ftpusers 280505 May 29 17:29 pwdsnc1.exe
+-rw-r--r-- 1 ftpuser ftpusers 758411 May 31 11:45 pxy031.exe
+-rw-r--r-- 1 ftpuser ftpusers 785651 Aug 31 2000 pxyauth.exe
+-rw-r--r-- 1 ftpuser ftpusers 25270 Nov 1 1995 qa.exe
+-rw-r--r-- 1 ftpuser ftpusers 22674 Jul 25 1995 qaos2.exe
+-rw-r--r-- 1 ftpuser ftpusers 21421 Jul 18 1995 qkinst.exe
+-rw-r--r-- 1 ftpuser ftpusers 390862 Dec 4 1995 qlfix.exe
+-rw-r--r-- 1 ftpuser ftpusers 21028 Oct 5 1995 quest.exe
+-rw-r--r-- 1 ftpuser ftpusers 13847723 Nov 23 1998 r16524br.exe
+-rw-r--r-- 1 ftpuser ftpusers 15367885 Nov 23 1998 r16524ce.exe
+-rw-r--r-- 1 ftpuser ftpusers 13974046 Nov 23 1998 r16524cf.exe
+-rw-r--r-- 1 ftpuser ftpusers 14636368 Nov 23 1998 r16524cs.exe
+-rw-r--r-- 1 ftpuser ftpusers 14606815 Nov 23 1998 r16524ct.exe
+-rw-r--r-- 1 ftpuser ftpusers 14396472 Nov 23 1998 r16524cz.exe
+-rw-r--r-- 1 ftpuser ftpusers 14526983 Nov 23 1998 r16524de.exe
+-rw-r--r-- 1 ftpuser ftpusers 13996151 Nov 23 1998 r16524dk.exe
+-rw-r--r-- 1 ftpuser ftpusers 14083999 Nov 24 1998 r16524es.exe
+-rw-r--r-- 1 ftpuser ftpusers 14036283 Nov 24 1998 r16524fr.exe
+-rw-r--r-- 1 ftpuser ftpusers 14168496 Nov 24 1998 r16524it.exe
+-rw-r--r-- 1 ftpuser ftpusers 15194180 Nov 30 1998 r16524jp.exe
+-rw-r--r-- 1 ftpuser ftpusers 14717983 Nov 24 1998 r16524kr.exe
+-rw-r--r-- 1 ftpuser ftpusers 13957605 Nov 24 1998 r16524ma.exe
+-rw-r--r-- 1 ftpuser ftpusers 13018097 Nov 24 1998 r16524nl.exe
+-rw-r--r-- 1 ftpuser ftpusers 14282386 Nov 24 1998 r16524no.exe
+-rw-r--r-- 1 ftpuser ftpusers 14592999 Nov 24 1998 r16524oz.exe
+-rw-r--r-- 1 ftpuser ftpusers 14683051 Nov 24 1998 r16524pl.exe
+-rw-r--r-- 1 ftpuser ftpusers 13868667 Nov 24 1998 r16524ru.exe
+-rw-r--r-- 1 ftpuser ftpusers 14075816 Nov 24 1998 r16524su.exe
+-rw-r--r-- 1 ftpuser ftpusers 14090792 Nov 24 1998 r16524sv.exe
+-rw-r--r-- 1 ftpuser ftpusers 14598010 Nov 24 1998 r16524uk.exe
+-rw-r--r-- 1 ftpuser ftpusers 14633171 Nov 23 1998 r16524us.exe
+-rw-r--r-- 1 ftpuser ftpusers 13892746 Oct 8 1999 r16525br.exe
+-rw-r--r-- 1 ftpuser ftpusers 15412960 Oct 8 1999 r16525ce.exe
+-rw-r--r-- 1 ftpuser ftpusers 14019075 Oct 8 1999 r16525cf.exe
+-rw-r--r-- 1 ftpuser ftpusers 14681320 Oct 8 1999 r16525cs.exe
+-rw-r--r-- 1 ftpuser ftpusers 14651741 Oct 8 1999 r16525ct.exe
+-rw-r--r-- 1 ftpuser ftpusers 14443408 Oct 8 1999 r16525cz.exe
+-rw-r--r-- 1 ftpuser ftpusers 14572069 Aug 24 1999 r16525de.exe
+-rw-r--r-- 1 ftpuser ftpusers 14041141 Oct 8 1999 r16525dk.exe
+-rw-r--r-- 1 ftpuser ftpusers 14129003 Oct 8 1999 r16525es.exe
+-rw-r--r-- 1 ftpuser ftpusers 14081224 Oct 8 1999 r16525fr.exe
+-rw-r--r-- 1 ftpuser ftpusers 14213472 Oct 8 1999 r16525it.exe
+-rw-r--r-- 1 ftpuser ftpusers 15239217 Oct 8 1999 r16525jp.exe
+-rw-r--r-- 1 ftpuser ftpusers 14762877 Oct 8 1999 r16525kr.exe
+-rw-r--r-- 1 ftpuser ftpusers 14004580 Oct 8 1999 r16525ma.exe
+-rw-r--r-- 1 ftpuser ftpusers 14520305 Oct 8 1999 r16525nl.exe
+-rw-r--r-- 1 ftpuser ftpusers 14327373 Oct 8 1999 r16525no.exe
+-rw-r--r-- 1 ftpuser ftpusers 14638087 Oct 8 1999 r16525oz.exe
+-rw-r--r-- 1 ftpuser ftpusers 14730025 Oct 8 1999 r16525pl.exe
+-rw-r--r-- 1 ftpuser ftpusers 13915653 Oct 8 1999 r16525ru.exe
+-rw-r--r-- 1 ftpuser ftpusers 14120807 Oct 8 1999 r16525su.exe
+-rw-r--r-- 1 ftpuser ftpusers 14135776 Oct 8 1999 r16525sv.exe
+-rw-r--r-- 1 ftpuser ftpusers 14643087 Oct 8 1999 r16525uk.exe
+-rw-r--r-- 1 ftpuser ftpusers 14678258 Aug 24 1999 r16525us.exe
+-rw-r--r-- 1 ftpuser ftpusers 34195974 Nov 20 1998 r524east.exe
+-rw-r--r-- 1 ftpuser ftpusers 29934184 Nov 21 1998 r524kcc.exe
+-rw-r--r-- 1 ftpuser ftpusers 40546603 Nov 21 1998 r524mult.exe
+-rw-r--r-- 1 ftpuser ftpusers 33377124 Nov 21 1998 r524scan.exe
+-rw-r--r-- 1 ftpuser ftpusers 17133749 Nov 21 1998 r524us.exe
+-rw-r--r-- 1 ftpuser ftpusers 20919099 Nov 21 1998 r524usde.exe
+-rw-r--r-- 1 ftpuser ftpusers 21776910 Dec 21 1998 r524usjp.exe
+-rw-r--r-- 1 ftpuser ftpusers 33695357 Oct 11 1999 r525east.exe
+-rw-r--r-- 1 ftpuser ftpusers 29387389 Oct 11 1999 r525kcc.exe
+-rw-r--r-- 1 ftpuser ftpusers 39896412 Oct 11 1999 r525mult.exe
+-rw-r--r-- 1 ftpuser ftpusers 32843372 Oct 11 1999 r525scan.exe
+-rw-r--r-- 1 ftpuser ftpusers 18205814 Oct 11 1999 r525us.exe
+-rw-r--r-- 1 ftpuser ftpusers 20711743 Oct 11 1999 r525usde.exe
+-rw-r--r-- 1 ftpuser ftpusers 19744627 Oct 14 1999 r525usjp.exe
+-rw-r--r-- 1 ftpuser ftpusers 21883384 Feb 25 1999 r551en.exe
+-rw-r--r-- 1 ftpuser ftpusers 38653860 Feb 26 1999 r551mult.exe
+-rw-r--r-- 1 ftpuser ftpusers 38136537 Feb 25 1999 r551scan.exe
+-rw-r--r-- 1 ftpuser ftpusers 37890181 Oct 19 1999 r552mult.exe
+-rw-r--r-- 1 ftpuser ftpusers 37404535 Oct 19 1999 r552scan.exe
+-rw-r--r-- 1 ftpuser ftpusers 22183381 Feb 11 2000 r553aen.exe
+-rw-r--r-- 1 ftpuser ftpusers 32216751 Feb 11 2000 r553aest.exe
+-rw-r--r-- 1 ftpuser ftpusers 24925427 Feb 11 2000 r553ajp.exe
+-rw-r--r-- 1 ftpuser ftpusers 27749699 Feb 11 2000 r553akcc.exe
+-rw-r--r-- 1 ftpuser ftpusers 38006860 Feb 11 2000 r553amlt.exe
+-rw-r--r-- 1 ftpuser ftpusers 37454601 Feb 11 2000 r553ascn.exe
+-rw-r--r-- 1 ftpuser ftpusers 87518 Apr 6 1998 rad102.exe
+-rw-r--r-- 1 ftpuser ftpusers 260651 Nov 23 1998 rad104.exe
+-rw-r--r-- 1 ftpuser ftpusers 118100 Mar 4 16:09 radatr4.exe
+-rw-r--r-- 1 ftpuser ftpusers 575303 Feb 28 1997 ramac.exe
+-rw-r--r-- 1 ftpuser ftpusers 66500 Jun 7 1995 rbuild.exe
+-rw-r--r-- 1 ftpuser ftpusers 23539 Feb 27 1998 rdmsg0.exe
+-rw-r--r-- 1 ftpuser ftpusers 91403 Apr 3 2000 revfhrft.exe
+-rw-r--r-- 1 ftpuser ftpusers 138359 Jul 27 2001 rinstall.exe
+-rw-r--r-- 1 ftpuser ftpusers 211615 Nov 4 1993 ripsap.exe
+-rw-r--r-- 1 ftpuser ftpusers 192641 Sep 18 1993 rlit92.exe
+-rw-r--r-- 1 ftpuser ftpusers 155252 Sep 18 1993 rlit93.exe
+-rw-r--r-- 1 ftpuser ftpusers 780218 Jul 18 1995 rofwin.exe
+-rw-r--r-- 1 ftpuser ftpusers 36120 Sep 18 1993 routez.exe
+-rw-r--r-- 1 ftpuser ftpusers 96684 Sep 18 1993 routfx.exe
+-rw-r--r-- 1 ftpuser ftpusers 141605 Oct 5 1998 rplkt5.exe
+-rw-r--r-- 1 ftpuser ftpusers 72596 May 11 1994 rsync1.exe
+-rw-r--r-- 1 ftpuser ftpusers 23294 Sep 18 1993 rxnet.exe
+-rw-r--r-- 1 ftpuser ftpusers 48534006 Mar 28 2001 rzfd3sp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 39313 Jun 16 1994 saa005.exe
+-rw-r--r-- 1 ftpuser ftpusers 534003 Aug 16 2001 saa008.exe
+-rw-r--r-- 1 ftpuser ftpusers 80219 Aug 11 1994 saa010.exe
+-rw-r--r-- 1 ftpuser ftpusers 142620 Sep 1 1994 saa012.exe
+-rw-r--r-- 1 ftpuser ftpusers 943059 Aug 16 2001 saa023.exe
+-rw-r--r-- 1 ftpuser ftpusers 154805 Dec 24 1996 saa031.exe
+-rw-r--r-- 1 ftpuser ftpusers 4659719 Aug 16 2001 saa20040.exe
+-rw-r--r-- 1 ftpuser ftpusers 2550556 Aug 16 2001 saa21030.exe
+-rw-r--r-- 1 ftpuser ftpusers 63688405 Aug 15 2001 saa22010.exe
+-rw-r--r-- 1 ftpuser ftpusers 9396094 Aug 15 2001 saa2210e.exe
+-rw-r--r-- 1 ftpuser ftpusers 10338946 Aug 15 2001 saa30020.exe
+-rw-r--r-- 1 ftpuser ftpusers 9315931 Aug 15 2001 saa40020.exe
+-rw-r--r-- 1 ftpuser ftpusers 169062 Jun 29 2000 saa4pt1.exe
+-rw-r--r-- 1 ftpuser ftpusers 20269 Jun 27 1995 saamic.exe
+-rw-r--r-- 1 ftpuser ftpusers 1646 Jun 3 1998 saapatch.txt
+-rw-r--r-- 1 ftpuser ftpusers 32233 Nov 30 1995 saarot.exe
+-rw-r--r-- 1 ftpuser ftpusers 29347 Aug 3 1995 saaupg.exe
+-rw-r--r-- 1 ftpuser ftpusers 282396 Jun 26 1996 sback6.exe
+-rw-r--r-- 1 ftpuser ftpusers 376293 Jun 7 2001 sbcon1.exe
+-rw-r--r-- 1 ftpuser ftpusers 564045 Jul 20 1998 sbm21y2k.exe
+-rw-r--r-- 1 ftpuser ftpusers 8341393 Mar 2 2001 sbs5pt2a.exe
+-rw-r--r-- 1 ftpuser ftpusers 244604 Dec 5 1997 schcmp2.exe
+-rw-r--r-- 1 ftpuser ftpusers 151673 Aug 12 1999 scmddoc.exe
+-rw-r--r-- 1 ftpuser ftpusers 167290 May 4 2001 scmdflt.exe
+-rw-r--r-- 1 ftpuser ftpusers 40595 Sep 18 1993 sec286.exe
+-rw-r--r-- 1 ftpuser ftpusers 29661 May 25 1994 secdoc.exe
+-rw-r--r-- 1 ftpuser ftpusers 310609 Sep 18 1993 secdos.exe
+-rw-r--r-- 1 ftpuser ftpusers 7039614 May 26 2000 secexp64.01
+-rw-r--r-- 1 ftpuser ftpusers 5016153 Aug 10 2000 secexp64.z
+-rw-r--r-- 1 ftpuser ftpusers 167904 Nov 15 1993 seclog.exe
+-rw-r--r-- 1 ftpuser ftpusers 632669 Sep 18 1993 secnns.exe
+-rw-r--r-- 1 ftpuser ftpusers 449590 Sep 18 1993 secprn.exe
+-rw-r--r-- 1 ftpuser ftpusers 322007 Sep 18 1993 secsys.exe
+-rw-r--r-- 1 ftpuser ftpusers 7351040 May 26 2000 secus64.01
+-rw-r--r-- 1 ftpuser ftpusers 5457221 Aug 10 2000 secus64.z
+-rw-r--r-- 1 ftpuser ftpusers 510733 Sep 18 1993 secut1.exe
+-rw-r--r-- 1 ftpuser ftpusers 556873 Sep 18 1993 secut2.exe
+-rw-r--r-- 1 ftpuser ftpusers 431691 Sep 18 1993 secut3.exe
+-rw-r--r-- 1 ftpuser ftpusers 134525 Aug 29 2001 servinst.exe
+-rw-r--r-- 1 ftpuser ftpusers 367009 May 25 1996 setdoc.exe
+-rw-r--r-- 1 ftpuser ftpusers 24541 Sep 18 1993 setfx.exe
+-rw-r--r-- 1 ftpuser ftpusers 56904 Sep 18 1993 setupc.exe
+-rw-r--r-- 1 ftpuser ftpusers 75076 Jul 21 1997 sftpt2.exe
+-rw-r--r-- 1 ftpuser ftpusers 67817 Sep 18 1993 sftutl.exe
+-rw-r--r-- 1 ftpuser ftpusers 49345 Sep 2 1999 showenv1.exe
+-rw-r--r-- 1 ftpuser ftpusers 25774 Nov 6 1997 silent.exe
+-rw-r--r-- 1 ftpuser ftpusers 181878 Apr 23 09:38 slp107g.exe
+-rw-r--r-- 1 ftpuser ftpusers 184680 Aug 28 2001 slpinsp3.exe
+-rw-r--r-- 1 ftpuser ftpusers 59254 Sep 18 1993 smfsel.exe
+-rw-r--r-- 1 ftpuser ftpusers 2747104 Jan 31 1997 smsup6.exe
+-rw-r--r-- 1 ftpuser ftpusers 131884 Sep 25 1996 smt121.exe
+-rw-r--r-- 1 ftpuser ftpusers 105031 Nov 10 1993 smt171.exe
+-rw-r--r-- 1 ftpuser ftpusers 1764462 May 24 1996 smtos2.exe
+-rw-r--r-- 1 ftpuser ftpusers 322954 Oct 11 1996 smtp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 441783 May 19 1997 smtp2.exe
+-rw-r--r-- 1 ftpuser ftpusers 2862615 Sep 19 1997 smtp3.exe
+-rw-r--r-- 1 ftpuser ftpusers 2882529 Jul 14 1998 smtp4.exe
+-rw-r--r-- 1 ftpuser ftpusers 53164 Aug 1 1995 smtslp.exe
+-rw-r--r-- 1 ftpuser ftpusers 298148 Jun 4 1996 sna31a.exe
+-rw-r--r-- 1 ftpuser ftpusers 148302 Mar 7 10:28 snmpfix.exe
+-rw-r--r-- 1 ftpuser ftpusers 147265 Jul 20 1995 snupd2.exe
+-rw-r--r-- 1 ftpuser ftpusers 163195 Jul 20 1995 snupdu.exe
+-rw-r--r-- 1 ftpuser ftpusers 12675957 Jul 14 2000 sp1_ce.02
+-rw-r--r-- 1 ftpuser ftpusers 9547499 Apr 25 2000 sp1_edir.02
+-rw-r--r-- 1 ftpuser ftpusers 230035 Sep 20 1999 sp3to3a.exe
+-rw-r--r-- 1 ftpuser ftpusers 74372 Feb 25 1998 spanish.exe
+-rw-r--r-- 1 ftpuser ftpusers 5323860 May 23 1996 srapi.exe
+-rw-r--r-- 1 ftpuser ftpusers 38967 Nov 8 1996 srout4.exe
+-rw-r--r-- 1 ftpuser ftpusers 812158 Jul 24 2000 srvinst.exe
+-rw-r--r-- 1 ftpuser ftpusers 54912 Aug 23 1996 srvmn1.exe
+-rw-r--r-- 1 ftpuser ftpusers 38078 Jun 30 1995 stampd.exe
+-rw-r--r-- 1 ftpuser ftpusers 126042 Feb 21 11:15 strmft1.exe
+-rw-r--r-- 1 ftpuser ftpusers 250945 Aug 23 2000 strtl8a.exe
+-rw-r--r-- 1 ftpuser ftpusers 36114 Mar 8 1999 stufkey5.exe
+-rw-r--r-- 1 ftpuser ftpusers 52344 Feb 11 1998 stylbr.exe
+-rw-r--r-- 1 ftpuser ftpusers 50098 Apr 14 1997 stylct.exe
+-rw-r--r-- 1 ftpuser ftpusers 35645 Feb 11 1998 styles.exe
+-rw-r--r-- 1 ftpuser ftpusers 37446 Feb 11 1998 stylfr.exe
+-rw-r--r-- 1 ftpuser ftpusers 77671 Apr 14 1997 stylha.exe
+-rw-r--r-- 1 ftpuser ftpusers 36626 Feb 12 1998 stylit.exe
+-rw-r--r-- 1 ftpuser ftpusers 55674 Apr 16 1997 stylsc.exe
+-rw-r--r-- 1 ftpuser ftpusers 37297 Dec 12 1995 supwin.exe
+-rw-r--r-- 1 ftpuser ftpusers 186171 Sep 18 1993 sys233.exe
+-rw-r--r-- 1 ftpuser ftpusers 159178 Sep 18 1993 sys368.exe
+-rw-r--r-- 1 ftpuser ftpusers 161608 May 10 1995 sys376.exe
+-rw-r--r-- 1 ftpuser ftpusers 61914 Sep 18 1993 syschk.exe
+-rw-r--r-- 1 ftpuser ftpusers 81300 Sep 18 1993 syslod.exe
+-rw-r--r-- 1 ftpuser ftpusers 418576 Jul 14 1997 tabnd2a.exe
+-rw-r--r-- 1 ftpuser ftpusers 9831871 Jan 13 1997 tambt1.exe
+-rw-r--r-- 1 ftpuser ftpusers 172843 May 4 1998 tback3.exe
+-rw-r--r-- 1 ftpuser ftpusers 58235 Sep 1 1998 tbox7.exe
+-rw-r--r-- 1 ftpuser ftpusers 174964 May 4 1998 tcopy2.exe
+-rw-r--r-- 1 ftpuser ftpusers 781603 May 18 1998 tcp312.exe
+-rw-r--r-- 1 ftpuser ftpusers 1223056 Aug 1 2001 tcp542u.exe
+-rw-r--r-- 1 ftpuser ftpusers 1124221 Apr 10 08:49 tcp553v.exe
+-rw-r--r-- 1 ftpuser ftpusers 1221375 May 24 16:03 tcp590s.exe
+-rw-r--r-- 1 ftpuser ftpusers 315088 Apr 15 10:50 tcp604m.exe
+-rw-r--r-- 1 ftpuser ftpusers 1118361 May 7 11:27 tcp604s.exe
+-rw-r--r-- 1 ftpuser ftpusers 6902826 Feb 9 1998 tel01a.exe
+-rw-r--r-- 1 ftpuser ftpusers 97084 Jan 21 1998 tel40d.exe
+-rw-r--r-- 1 ftpuser ftpusers 33888 Sep 18 1993 tim286.exe
+-rw-r--r-- 1 ftpuser ftpusers 20453 Sep 18 1993 tim386.exe
+-rw-r--r-- 1 ftpuser ftpusers 105037 Nov 2 1998 timefx.exe
+-rw-r--r-- 1 ftpuser ftpusers 31521 Mar 29 1994 tokws.exe
+-rw-r--r-- 1 ftpuser ftpusers 123321 Jan 25 2001 trpmon.exe
+-rw-r--r-- 1 ftpuser ftpusers 26100 Sep 18 1993 trxnet.exe
+-rw-r--r-- 1 ftpuser ftpusers 88579 Aug 21 1996 tsa410.exe
+-rw-r--r-- 1 ftpuser ftpusers 724997 Jun 25 10:29 tsa5up9.exe
+-rw-r--r-- 1 ftpuser ftpusers 127632 Jan 12 2000 tsands.exe
+-rw-r--r-- 1 ftpuser ftpusers 20771 Nov 2 1999 ttsy2k.exe
+-rw-r--r-- 1 ftpuser ftpusers 19933 Sep 22 1995 ttyncs.exe
+-rw-r--r-- 1 ftpuser ftpusers 834048 Aug 3 1994 tux001.tar
+-rw-r--r-- 1 ftpuser ftpusers 845824 Aug 3 1994 tux002.tar
+-rw-r--r-- 1 ftpuser ftpusers 1034240 Aug 3 1994 tux003.tar
+-rw-r--r-- 1 ftpuser ftpusers 2764800 Aug 3 1994 tux004.tar
+-rw-r--r-- 1 ftpuser ftpusers 2836480 Aug 3 1994 tux005.tar
+-rw-r--r-- 1 ftpuser ftpusers 1252352 Aug 3 1994 tux006.tar
+-rw-r--r-- 1 ftpuser ftpusers 1355264 Aug 3 1994 tux007.tar
+-rw-r--r-- 1 ftpuser ftpusers 1710080 Aug 3 1994 tux008.tar
+-rw-r--r-- 1 ftpuser ftpusers 3502080 Aug 3 1994 tux009.tar
+-rw-r--r-- 1 ftpuser ftpusers 3573760 Aug 3 1994 tux010.tar
+-rw-r--r-- 1 ftpuser ftpusers 258236 Aug 4 1994 tux011.exe
+-rw-r--r-- 1 ftpuser ftpusers 258250 Aug 4 1994 tux012.exe
+-rw-r--r-- 1 ftpuser ftpusers 304451 Aug 4 1994 tux013.exe
+-rw-r--r-- 1 ftpuser ftpusers 602748 Aug 4 1994 tux014.exe
+-rw-r--r-- 1 ftpuser ftpusers 351070 Aug 4 1994 tux015.exe
+-rw-r--r-- 1 ftpuser ftpusers 460026 Aug 4 1994 tux016.exe
+-rw-r--r-- 1 ftpuser ftpusers 34077 Sep 18 1993 ucpy.exe
+-rw-r--r-- 1 ftpuser ftpusers 103354 Sep 18 1993 udf355.exe
+-rw-r--r-- 1 ftpuser ftpusers 6994 Feb 22 12:49 unixinf1.tgz
+-rw-r--r-- 1 ftpuser ftpusers 107260 May 8 14:56 unixins2.tgz
+-rw-r--r-- 1 ftpuser ftpusers 25508 Sep 18 1993 unld.exe
+-rw-r--r-- 1 ftpuser ftpusers 30830 Sep 18 1993 unps2.exe
+-rw-r--r-- 1 ftpuser ftpusers 34857 Sep 18 1993 up215c.exe
+-rw-r--r-- 1 ftpuser ftpusers 509794 Jan 6 1994 upd311.exe
+-rw-r--r-- 1 ftpuser ftpusers 24330 Sep 18 1993 ups.exe
+-rw-r--r-- 1 ftpuser ftpusers 20837 Sep 18 1993 ups22.exe
+-rw-r--r-- 1 ftpuser ftpusers 45537 Sep 18 1993 upsm70.exe
+-rw-r--r-- 1 ftpuser ftpusers 43743 Jul 22 1997 upsnlm.exe
+-rw-r--r-- 1 ftpuser ftpusers 28519 Oct 13 1998 userhlp.exe
+-rw-r--r-- 1 ftpuser ftpusers 134247 Sep 18 1993 ut1192.exe
+-rw-r--r-- 1 ftpuser ftpusers 1632088 Jan 14 1998 uxp203.exe
+-rw-r--r-- 1 ftpuser ftpusers 1389072 Nov 19 1998 uxp205.exe
+-rw-r--r-- 1 ftpuser ftpusers 1341347 Jun 6 2001 uxp23j.exe
+-rw-r--r-- 1 ftpuser ftpusers 1098502 Nov 2 1995 uxpsft.exe
+-rw-r--r-- 1 ftpuser ftpusers 58761 Nov 1 1995 v2014.exe
+-rw-r--r-- 1 ftpuser ftpusers 40944 Sep 18 1993 v286ol.exe
+-rw-r--r-- 1 ftpuser ftpusers 95133 Jun 8 2001 v_nfs914.exe
+-rw-r--r-- 1 ftpuser ftpusers 34278 Sep 18 1993 vapvol.exe
+-rw-r--r-- 1 ftpuser ftpusers 38035 Sep 18 1993 vgetsc.exe
+-rw-r--r-- 1 ftpuser ftpusers 52323 Sep 18 1993 volinf.exe
+-rw-r--r-- 1 ftpuser ftpusers 2444080 May 3 2001 vpn35e.exe
+-rw-r--r-- 1 ftpuser ftpusers 3838701 Feb 13 14:50 vpn36d.exe
+-rw-r--r-- 1 ftpuser ftpusers 3837285 Feb 13 14:48 vpn36e.exe
+-rw-r--r-- 1 ftpuser ftpusers 96158 Aug 31 1999 vpnbs01.exe
+-rw-r--r-- 1 ftpuser ftpusers 49835 Sep 18 1993 vrepfa.exe
+-rw-r--r-- 1 ftpuser ftpusers 86326 Sep 18 1993 vrp215.exe
+-rw-r--r-- 1 ftpuser ftpusers 59336 Jul 31 1997 vrp386.exe
+-rw-r--r-- 1 ftpuser ftpusers 43438 Jul 31 1997 vrpa286.exe
+-rw-r--r-- 1 ftpuser ftpusers 486274 Sep 18 1993 vrpels.exe
+-rw-r--r-- 1 ftpuser ftpusers 103958 Sep 18 1993 vrpps2.exe
+-rw-r--r-- 1 ftpuser ftpusers 699367 Sep 9 1999 w2n213.exe
+-rw-r--r-- 1 ftpuser ftpusers 771404 Sep 25 2000 w2ny2k.exe
+-rw-r--r-- 1 ftpuser ftpusers 240179 Jun 4 1996 wan31a.exe
+-rw-r--r-- 1 ftpuser ftpusers 135592 Jun 16 1995 wanx02.exe
+-rw-r--r-- 1 ftpuser ftpusers 79254744 Jul 20 2001 was351.exe
+-rw-r--r-- 1 ftpuser ftpusers 28100 Sep 18 1993 watch.exe
+-rw-r--r-- 1 ftpuser ftpusers 7884641 Apr 23 10:17 waview71.exe
+-rw-r--r-- 1 ftpuser ftpusers 182961 Jul 9 2001 wbdav51.exe
+-rw-r--r-- 1 ftpuser ftpusers 53418 Aug 21 1996 web002.exe
+-rw-r--r-- 1 ftpuser ftpusers 182219 Mar 1 2001 webdv51.exe
+-rw-r--r-- 1 ftpuser ftpusers 2574191 Oct 5 1999 weblsp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 3589741 Jun 22 1998 webser31.exe
+-rw-r--r-- 1 ftpuser ftpusers 27063 Nov 1 1995 welcom.exe
+-rw-r--r-- 1 ftpuser ftpusers 1887450 Apr 23 2001 winntwms.exe
+-rw-r--r-- 1 ftpuser ftpusers 28104 Jul 17 1997 wkstrk.exe
+-rw-r--r-- 1 ftpuser ftpusers 52547 Jul 20 1995 wpca31.exe
+-rw-r--r-- 1 ftpuser ftpusers 89314 Jul 20 1995 wpfm31.exe
+-rw-r--r-- 1 ftpuser ftpusers 41008 Sep 11 1995 wpmdm2.exe
+-rw-r--r-- 1 ftpuser ftpusers 36824 Jul 18 1995 wpofus.exe
+-rw-r--r-- 1 ftpuser ftpusers 51398 Jul 20 1995 wprp31.exe
+-rw-r--r-- 1 ftpuser ftpusers 21092 Jul 18 1995 wpvwin.exe
+-rw-r--r-- 1 ftpuser ftpusers 52738 Mar 15 1994 wrkdoc.exe
+-rw-r--r-- 1 ftpuser ftpusers 683395 May 29 1997 ws250c.exe
+-rw-r--r-- 1 ftpuser ftpusers 765234 May 29 1997 ws251c.exe
+-rw-r--r-- 1 ftpuser ftpusers 212586 May 9 1997 ws3tk2b.exe
+-rw-r--r-- 1 ftpuser ftpusers 371 Mar 7 12:40 ws_ftp.log
+-rw-r--r-- 1 ftpuser ftpusers 1507075 Jun 29 1999 wtmc1.exe
+-rw-r--r-- 1 ftpuser ftpusers 32697 Jun 16 1995 x400fx.exe
+-rw-r--r-- 1 ftpuser ftpusers 660700 Jun 9 1999 x400nlm1.exe
+-rw-r--r-- 1 ftpuser ftpusers 1134477 Aug 5 1999 x400os21.exe
+-rw-r--r-- 1 ftpuser ftpusers 156483 Jan 30 17:09 xconss9f.exe
+-rw-r--r-- 1 ftpuser ftpusers 49801 Sep 18 1993 xld386.exe
+-rw-r--r-- 1 ftpuser ftpusers 1043685 Jul 27 2001 zd2dmi1.exe
+-rw-r--r-- 1 ftpuser ftpusers 365016 Dec 19 2001 zd2dstfx.exe
+-rw-r--r-- 1 ftpuser ftpusers 338947 Jul 20 2001 zd2scan.exe
+-rw-r--r-- 1 ftpuser ftpusers 24341430 Mar 1 09:27 zd322k1.exe
+-rw-r--r-- 1 ftpuser ftpusers 24350056 Mar 1 09:35 zd322k2.exe
+-rw-r--r-- 1 ftpuser ftpusers 95330 Mar 14 18:03 zd32dupw.exe
+-rw-r--r-- 1 ftpuser ftpusers 26945103 Mar 1 09:16 zd32nw.exe
+-rw-r--r-- 1 ftpuser ftpusers 26937023 Mar 1 09:21 zd32nw4.exe
+-rw-r--r-- 1 ftpuser ftpusers 26944994 Feb 5 12:18 zd32nw5.exe
+-rw-r--r-- 1 ftpuser ftpusers 24349972 Jul 29 2001 zd32p2k1.exe
+-rw-r--r-- 1 ftpuser ftpusers 24349896 Jul 29 2001 zd32p2k2.exe
+-rw-r--r-- 1 ftpuser ftpusers 26936865 Jul 29 2001 zd32pnw4.exe
+-rw-r--r-- 1 ftpuser ftpusers 26944944 Jul 29 2001 zd32pnw5.exe
+-rw-r--r-- 1 ftpuser ftpusers 128456 Jan 29 14:50 zd3awsr1.exe
+-rw-r--r-- 1 ftpuser ftpusers 1242985 Dec 19 2001 zd3ccpp.exe
+-rw-r--r-- 1 ftpuser ftpusers 304923 Dec 19 2001 zd3dac.exe
+-rw-r--r-- 1 ftpuser ftpusers 537680 Feb 22 15:31 zd3dupws.exe
+-rw-r--r-- 1 ftpuser ftpusers 142260 Nov 8 2001 zd3dxsnp.exe
+-rw-r--r-- 1 ftpuser ftpusers 94250 Dec 4 2001 zd3idnt1.exe
+-rw-r--r-- 1 ftpuser ftpusers 1443132 Jan 2 2002 zd3ntmsi.exe
+-rw-r--r-- 1 ftpuser ftpusers 15512136 Dec 20 2001 zd3o8i1.exe
+-rw-r--r-- 1 ftpuser ftpusers 15575094 Dec 19 2001 zd3o8i2.exe
+-rw-r--r-- 1 ftpuser ftpusers 204858 May 24 10:03 zd3rosnp.exe
+-rw-r--r-- 1 ftpuser ftpusers 298505 Jan 9 2002 zd3scn.exe
+-rw-r--r-- 1 ftpuser ftpusers 149726 Dec 18 2001 zd3wm95.exe
+-rw-r--r-- 1 ftpuser ftpusers 180523 Jan 9 2002 zd3wminv.exe
+-rw-r--r-- 1 ftpuser ftpusers 166988 Dec 18 2001 zd3wmsch.exe
+-rw-r--r-- 1 ftpuser ftpusers 195447 Dec 19 2001 zd3wsmg.exe
+-rw-r--r-- 1 ftpuser ftpusers 381437 Mar 19 14:21 zd3xwsrg.exe
+-rw-r--r-- 1 ftpuser ftpusers 125036 Apr 18 15:53 zd3xwuol.exe
+-rw-r--r-- 1 ftpuser ftpusers 180429 Apr 18 16:30 zd3xzisw.exe
+-rw-r--r-- 1 ftpuser ftpusers 226961 Mar 14 10:01 zd3zpol.exe
+-rw-r--r-- 1 ftpuser ftpusers 1274878 May 1 17:41 zenintg.exe
+-rw-r--r-- 1 ftpuser ftpusers 1865 May 9 2001 zenstart.txt
+-rw-r--r-- 1 ftpuser ftpusers 2408726 Feb 23 2001 zfd2pt3b.exe
+-rw-r--r-- 1 ftpuser ftpusers 62396652 Mar 21 2000 zfd2sp1.exe
+-rw-r--r-- 1 ftpuser ftpusers 293221 May 22 2001 zfd2tsfx.exe
+-rw-r--r-- 1 ftpuser ftpusers 97309 Oct 20 2000 zfd3site.exe
+-rw-r--r-- 1 ftpuser ftpusers 46890033 Nov 23 2001 zfd3sp1a.exe
+-rw-r--r-- 1 ftpuser ftpusers 31452136 Aug 10 2000 zfn101.exe
+-rw-r--r-- 1 ftpuser ftpusers 1647316 Nov 23 2001 zfs2jvm.exe
+-rw-r--r-- 1 ftpuser ftpusers 215046 Dec 18 2001 zfs2pt1.exe
+-rw-r--r-- 1 ftpuser ftpusers 262640 Dec 20 2001 zfs2sel.exe
+-rw-r--r-- 1 ftpuser ftpusers 54876346 Jan 18 14:59 zfs2sp1a.exe
+-rw-r--r-- 1 ftpuser ftpusers 1903657 Feb 5 2001 zfsdbpb.exe
+-rw-r--r-- 1 ftpuser ftpusers 96356 Oct 11 2000 zisclr.exe
+-rw-r--r-- 1 ftpuser ftpusers 94293 Dec 19 2001 zs2dbbk.exe
+-rw-r--r-- 1 ftpuser ftpusers 141307 Dec 20 2001 zs2ipg.exe
+-rw-r--r-- 1 ftpuser ftpusers 1173802 Dec 19 2001 zs2mibs.exe
+-rw-r--r-- 1 ftpuser ftpusers 943931 Jan 23 08:51 zs2ndst1.exe
+-rw-r--r-- 1 ftpuser ftpusers 516401 Jun 4 13:23 zs2rbs.exe
+-rw-r--r-- 1 ftpuser ftpusers 1095584 Mar 13 11:41 zs2smtp.exe
+-rw-r--r-- 1 ftpuser ftpusers 981014 Dec 5 2001 zs2util2.exe
+-rw-r--r-- 1 ftpuser ftpusers 92151 Jun 6 11:14 zs3sch.exe
+-rw-r--r-- 1 ftpuser ftpusers 1039314 Oct 13 1998 zw100p1.exe
+-rw-r--r-- 1 ftpuser ftpusers 194420 Nov 6 1998 zw101p1.exe
+-rw-r--r-- 1 ftpuser ftpusers 1065727 Nov 22 1999 zw110p3.exe
+226 Listing completed.
+ftp> close
+221-Thank you and have a nice day.
+221
+ftp> \ No newline at end of file
diff --git a/netwerk/streamconv/converters/parse-ftp/U-ncFTPd.out b/netwerk/streamconv/converters/parse-ftp/U-ncFTPd.out
new file mode 100644
index 000000000..6e3bac46f
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-ncFTPd.out
@@ -0,0 +1,1377 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+01-01-1997 00:00:00 2419 Readme
+07-10-2002 11:03:00 <DIR> incoming
+07-10-2002 10:18:00 <DIR> outgoing
+05-10-2002 10:16:00 <DIR> priv
+07-10-2002 08:12:00 <DIR> pub
+07-08-2002 19:20:00 <DIR> allupdates
+01-01-1997 00:00:00 <DIR> netwire
+07-09-2002 19:20:00 <DIR> support
+01-10-2002 00:00:00 <JUNCTION> updates -> allupdates
+07-27-1999 00:00:00 19448 0dsb.exe
+09-17-1993 00:00:00 49351 215mir.exe
+09-17-1993 00:00:00 32586 215sec.exe
+09-17-1993 00:00:00 136344 21fix.exe
+09-17-1993 00:00:00 57276 223200.exe
+11-01-1995 00:00:00 119616 22bkup.exe
+10-13-1995 00:00:00 19820 22dos5.exe
+11-01-1995 00:00:00 32980 22nd2f.exe
+05-09-2002 11:30:00 92151 236779.exe
+01-17-2001 00:00:00 273958 242234.exe
+07-10-2001 00:00:00 283462 243798.exe
+12-18-2001 00:00:00 160893 251000.exe
+12-18-2001 00:00:00 205531 252143.exe
+12-18-2001 00:00:00 183262 253720.exe
+11-06-2001 00:00:00 231638 260624.exe
+06-21-2001 00:00:00 250545 264837.exe
+02-21-2002 16:33:00 589722 265058a.exe
+11-07-2001 00:00:00 336586 269308.exe
+11-06-2001 00:00:00 345275 270050.exe
+11-06-2001 00:00:00 103027 270410.exe
+05-09-2002 07:13:00 341460 275382.exe
+05-09-2002 11:23:00 365835 275436.exe
+10-09-2001 00:00:00 230063 275520.exe
+10-02-2001 00:00:00 285953 275820.exe
+11-16-2001 00:00:00 156517 277412.exe
+12-19-2001 00:00:00 839272 278415.exe
+12-19-2001 00:00:00 130983 282848.exe
+09-17-1993 00:00:00 61891 286dwn.exe
+05-09-2002 07:18:00 136529 290254.exe
+04-12-2002 17:07:00 96694 290261.exe
+05-09-2002 07:22:00 230377 291158.exe
+06-27-2002 12:20:00 114329 295137.exe
+09-17-1993 00:00:00 84885 2xto3x.exe
+09-17-1993 00:00:00 60861 300pt1.exe
+09-17-1993 00:00:00 180279 310pt1.exe
+11-11-1996 00:00:00 178076 311ptg.exe
+04-29-1996 00:00:00 188572 312du1.exe
+03-18-1998 00:00:00 168258 312ptd.exe
+08-25-1999 00:00:00 436629 312y2kp2.exe
+06-29-2001 00:00:00 2365264 33sp3.exe
+09-17-1993 00:00:00 28881 386dcb.exe
+09-17-1993 00:00:00 33111 3cboot.exe
+11-10-1995 00:00:00 27583 400pt1.exe
+10-23-1995 00:00:00 79295 401pt6.exe
+08-26-1994 00:00:00 42873 402pa1.exe
+03-28-1995 00:00:00 50737 402pt1.exe
+06-08-1998 00:00:00 548398 410pt8b.exe
+08-25-1999 00:00:00 285471 410y2kp2.exe
+07-23-1999 00:00:00 538544 411y2kp2.exe
+04-29-1996 00:00:00 370469 41filr.exe
+01-02-1997 00:00:00 58965 41migutl.exe
+08-29-1995 00:00:00 173978 41ndir.exe
+11-24-1997 00:00:00 42101 41rem1.exe
+07-09-1996 00:00:00 855292 41rtr2.exe
+07-23-1999 00:00:00 212785 42y2kp1.exe
+07-03-2001 00:00:00 3043701 48sp3.exe
+05-22-2001 00:00:00 308856 4pent.exe
+04-06-1998 00:00:00 1072023 4xmigr2.exe
+11-17-1995 00:00:00 125457 4xrep1.exe
+07-06-1994 00:00:00 29001 50z70.exe
+11-01-1995 00:00:00 23248 55sx60.exe
+12-04-1998 00:00:00 647818 95220p1.exe
+03-25-1999 00:00:00 905243 95250p2.exe
+06-21-1999 00:00:00 694344 9530p1.exe
+06-13-2000 00:00:00 794454 9531pt2.exe
+10-03-1999 00:00:00 4380134 9531sp2.exe
+11-16-2000 00:00:00 1306298 95321pt5.exe
+06-13-2000 00:00:00 494394 9532pt3.exe
+11-06-2001 00:00:00 483405 95331pt1.exe
+06-02-2000 00:00:00 19588899 a526aix.z
+06-02-2000 00:00:00 17196628 a526hp.z
+06-02-2000 00:00:00 14813432 a526sol.z
+07-09-1999 00:00:00 238005 accupg1b.exe
+09-17-1993 00:00:00 19472 aceclp.exe
+06-19-2001 00:00:00 2061142 acmgtcl.exe
+12-17-1996 00:00:00 52792 actkey.exe
+11-08-1996 00:00:00 1026928 adde1.exe
+09-10-1997 00:00:00 476094 adm32_22.exe
+01-10-1997 00:00:00 4204451 adm4113x.exe
+01-10-1997 00:00:00 3813257 adm41195.exe
+01-10-1997 00:00:00 5377426 adm411nt.exe
+05-23-2001 00:00:00 130826 admattrs.exe
+05-23-2001 00:00:00 3291925 admn519f.exe
+07-15-1997 00:00:00 273404 adtus3.exe
+09-17-1993 00:00:00 25475 afix1.exe
+09-17-1993 00:00:00 25929 afix2.exe
+09-17-1993 00:00:00 26184 afix4.exe
+04-10-2001 00:00:00 116034 afnwcgi1.exe
+01-28-2002 13:43:00 175949 afp100j.exe
+07-12-1999 00:00:00 90415 afp11.exe
+11-01-1995 00:00:00 513677 aiodrv.exe
+08-12-1995 00:00:00 26752 aiotrm.exe
+02-08-2000 00:00:00 113328 alx311cm.exe
+12-11-2001 00:00:00 202594 am210pt2.exe
+12-10-2001 00:00:00 1126900 am210snp.exe
+12-11-2001 00:00:00 267218 amsammg.exe
+11-29-2001 00:00:00 4394406 amw2ksp1.exe
+11-06-1996 00:00:00 34959 anlmde.exe
+11-20-1996 00:00:00 70315 antde.exe
+12-10-1997 00:00:00 2778036 apinlm.exe
+04-05-1994 00:00:00 47772 apinst.exe
+12-10-1997 00:00:00 3367826 apios2.exe
+09-17-1993 00:00:00 44662 apsvap.exe
+10-05-1998 00:00:00 1507519 async1.exe
+07-25-1995 00:00:00 431852 asyq4a.exe
+09-17-1993 00:00:00 68700 atalk.exe
+09-17-1993 00:00:00 22944 atdisk.exe
+01-29-1996 00:00:00 222222 atk307.exe
+09-24-1999 00:00:00 259359 atmdrv04.exe
+06-14-1996 00:00:00 22012 atok31.exe
+09-17-1993 00:00:00 25152 atps1.exe
+09-17-1993 00:00:00 25812 atps2.exe
+09-17-1993 00:00:00 206226 atsup.exe
+09-15-1997 00:00:00 249262 audit410.exe
+07-25-1995 00:00:00 27058 autoda.exe
+03-28-2001 00:00:00 53955568 azfd3sp1.exe
+03-30-2000 00:00:00 1267891 bacl105.exe
+04-24-1998 00:00:00 564407 bm21y2k.exe
+12-09-1999 00:00:00 64354 bm2ncs2.exe
+11-13-2000 00:00:00 5025837 bm30sp3.exe
+03-27-2002 10:48:00 118425 bm35adm6.exe
+09-25-2001 00:00:00 8950758 bm35sp3.exe
+05-31-2002 15:43:00 1560521 bm36c02.exe
+11-06-2001 00:00:00 1995053 bm36nsp1.exe
+01-30-2002 13:44:00 4187534 bm36sp1a.exe
+04-19-2002 13:52:00 146884 bm37flt.exe
+04-19-2002 13:54:00 3958423 bm37vpn1.exe
+06-16-2000 00:00:00 2192048 bm3cp3.exe
+03-27-2000 00:00:00 521873 bm3licfx.exe
+01-21-1999 00:00:00 550905 bm3netad.exe
+10-08-1999 00:00:00 28435 bm3pcfg.exe
+10-20-1999 00:00:00 30429 bm3rmv3.exe
+09-02-1999 00:00:00 4865777 bm3sp2.exe
+01-11-2000 00:00:00 3934644 bm3sp2j.exe
+01-16-2001 00:00:00 105579 bm3sso2.exe
+11-23-1998 00:00:00 114564 bmas203.exe
+07-27-2000 00:00:00 185953 bmas204.exe
+05-29-2001 00:00:00 227934 bmas3x01.exe
+04-14-1998 00:00:00 2409166 bmnwntb.exe
+10-07-1999 00:00:00 235512 bmp114.exe
+08-25-2000 00:00:00 114828 bmsamp1.exe
+02-05-2001 00:00:00 7822377 bmsp2d.exe
+05-09-2001 00:00:00 177276 bmvpn3y.exe
+07-16-1997 00:00:00 57666 bndfx4.exe
+09-26-1997 00:00:00 22178 brdrem1.exe
+09-17-1993 00:00:00 140225 brgcom.exe
+03-17-1998 00:00:00 64130 bwcc.exe
+05-10-2000 00:00:00 106576 c112brj.exe
+05-09-2000 00:00:00 107820 c112crcj.exe
+05-10-2000 00:00:00 106834 c112crj.exe
+03-05-2002 13:14:00 35687507 c1_132.exe
+02-27-2001 00:00:00 188379 c1unx85a.exe
+06-02-2000 00:00:00 24246977 c526aix.z
+06-02-2000 00:00:00 39823205 c526hp.z
+06-02-2000 00:00:00 31630789 c526sol.z
+12-04-1996 00:00:00 39967 ccmdll.exe
+06-21-1999 00:00:00 3532557 ccmln1.exe
+04-21-2000 00:00:00 3610648 ccmln2.exe
+10-30-1998 00:00:00 7242383 ccmlo1.exe
+03-06-1997 00:00:00 71189 cdisc.exe
+08-19-1998 00:00:00 298109 cdup5a.exe
+10-14-1998 00:00:00 1554357 cfgrd6b.exe
+09-17-1993 00:00:00 30799 chk375.exe
+06-16-1997 00:00:00 85538 chtree1.exe
+12-08-1999 00:00:00 28171 clibaux1.exe
+09-08-2000 00:00:00 2819 clients.txt
+09-11-2000 00:00:00 16820824 clntaot.exe
+01-05-1999 00:00:00 7269162 clos2d1.exe
+06-24-1996 00:00:00 2960384 clt511.bin
+03-24-1999 00:00:00 195429 clty2kp1.exe
+11-22-1993 00:00:00 76117 comchk.exe
+11-01-1995 00:00:00 76738 comsub.exe
+08-16-1996 00:00:00 74759 comx.exe
+02-22-2001 00:00:00 102496 comx218.exe
+12-05-2000 00:00:00 117584 confg9.exe
+09-17-1993 00:00:00 27438 conlog.exe
+09-17-1993 00:00:00 20051 cpuchk.exe
+01-07-2000 00:00:00 96755 cron5.exe
+07-21-2001 00:00:00 22439431 cs1sp2.exe
+02-19-2002 16:08:00 12643202 cs1sp3.exe
+02-28-2001 00:00:00 2395980 cs2ep2.exe
+02-17-2000 00:00:00 97982 csatpxy2.exe
+01-30-1997 00:00:00 888262 csserv.exe
+01-30-1997 00:00:00 888092 ctserv.exe
+09-20-1999 00:00:00 1195718 ctsv20_1.pdf
+08-30-2000 00:00:00 97050 cvsbind.exe
+01-05-1996 00:00:00 1040603 d70f15.exe
+01-05-1996 00:00:00 1046550 d70g15.exe
+01-05-1996 00:00:00 1041138 d70i15.exe
+01-05-1996 00:00:00 1042404 d70s15.exe
+01-05-1996 00:00:00 1031373 d70u15.exe
+10-31-1995 00:00:00 309903 d72pnw.exe
+08-17-1995 00:00:00 26322 daishm.exe
+01-17-2002 09:55:00 92347 decrenfx.exe
+11-24-1997 00:00:00 32573 devmon.exe
+11-23-1999 00:00:00 225697 dhcp21r.exe
+07-27-1994 00:00:00 65667 diag.exe
+07-03-1996 00:00:00 776679 dialr1.exe
+07-03-1996 00:00:00 1307891 dialr2.exe
+07-03-1996 00:00:00 1330220 dialr3.exe
+09-17-1993 00:00:00 62202 distst.exe
+02-08-2001 00:00:00 133345 dlttape.exe
+12-13-1995 00:00:00 174566 dr6tid.exe
+05-15-2002 15:23:00 188110 dradpt1a.exe
+04-11-2002 10:37:00 12654872 drdt10.exe
+04-11-2002 10:50:00 7991951 drnt10.exe
+12-09-1993 00:00:00 259966 drv2x.exe
+09-17-1993 00:00:00 366568 drvkit.exe
+12-02-1998 00:00:00 28773 drvspc.exe
+07-12-1994 00:00:00 242836 ds310.exe
+12-13-1999 00:00:00 739008 ds410q.exe
+06-11-2002 18:01:00 683746 ds616.exe
+07-03-2002 19:58:00 1237908 ds760a.exe
+06-12-2002 13:47:00 3084809 ds880d_a.exe
+06-07-2000 00:00:00 2366484 ds8c.exe
+05-31-2000 00:00:00 300572 dsbrowse.exe
+11-10-1998 00:00:00 425220 dsdiag1.exe
+04-15-1998 00:00:00 766525 dskdrv.exe
+05-02-1997 00:00:00 201308 dsright2.exe
+02-04-2002 14:26:00 6620 dsrmenu5.tgz
+01-11-2002 12:06:00 32671 dsx86upg.tgz
+11-22-1999 00:00:00 438327 duprid.exe
+11-30-1999 00:00:00 366231 dw271i1.exe
+10-31-2001 00:00:00 6444327 dx1patch.exe
+12-11-2001 00:00:00 764705 dxjdbc1a.exe
+07-31-2001 00:00:00 369669 dxnotp1.exe
+01-11-2002 17:32:00 325977 dxntp1.exe
+01-11-2002 17:11:00 6446882 dxnwp1.exe
+01-15-2002 18:08:00 27292445 dxx10a.tgz
+09-18-1993 00:00:00 420838 e2isa.exe
+05-15-2002 09:35:00 299227554 edir851.exe
+06-19-2002 22:20:00 13752049 edir8527.exe
+06-18-2002 17:22:00 8909701 edir8527.tgz
+05-23-2002 12:35:00 35256093 edir862.exe
+03-07-2002 13:22:00 30290896 edir862.tgz
+06-20-2002 11:12:00 12405810 edir862sp1.exe
+06-20-2002 11:07:00 7623982 edir862sp1a.tgz
+06-19-2002 23:26:00 178010922 edirw8527.exe
+08-01-1995 00:00:00 739976 edvwin.exe
+04-12-2002 15:32:00 270433 egdpvr02.exe
+01-15-2002 10:28:00 6660863 einstall.exe
+09-18-1993 00:00:00 19547 els2dt.exe
+09-18-1993 00:00:00 46872 elsupd.exe
+09-18-1993 00:00:00 44481 emshdl.exe
+11-30-2001 00:00:00 171889 es7000.exe
+09-18-1993 00:00:00 395219 escsi.exe
+11-01-1995 00:00:00 50164 esdidr.exe
+09-18-1993 00:00:00 22207 esdifx.exe
+04-16-2001 00:00:00 162763 etbox7.exe
+09-18-1993 00:00:00 28262 ethrlk.exe
+09-18-1993 00:00:00 21776 ethsh.exe
+10-13-1999 00:00:00 3111638 exchnt2.exe
+03-20-1995 00:00:00 32615 exprul.exe
+07-18-1995 00:00:00 19910 facwin.exe
+09-18-1993 00:00:00 193689 faxdoc.exe
+07-18-1995 00:00:00 103299 faxsv.exe
+07-20-1998 00:00:00 566087 fbm21y2k.exe
+07-27-2000 00:00:00 263164 ffwnt1a.exe
+06-05-2000 00:00:00 9564485 fgwep1ad.exe
+11-10-1993 00:00:00 158446 fil376.exe
+09-18-1993 00:00:00 35376 filehd.exe
+01-28-1999 00:00:00 64924 filt01a.exe
+09-18-1993 00:00:00 38027 flgdir.exe
+06-25-2002 10:26:00 891667 flsysft7.exe
+07-20-1994 00:00:00 210958 flx196.exe
+09-18-1993 00:00:00 23948 fmtps2.exe
+06-01-1995 00:00:00 265642 fmwin1.exe
+06-18-1997 00:00:00 44110 fnasi21b.exe
+04-29-1997 00:00:00 35133 fnwcrns.exe
+06-18-1997 00:00:00 64944 fnwcss.exe
+06-18-1997 00:00:00 38169 fnwcx25.exe
+02-26-2001 00:00:00 18985686 fp3023a.exe
+02-26-2001 00:00:00 19034903 fp3023s.exe
+06-22-2001 00:00:00 41401158 fpa353.exe
+06-22-2001 00:00:00 40072174 fps353.exe
+08-02-1996 00:00:00 40680 frebld.exe
+01-30-2002 15:36:00 156117 ftpservk.exe
+06-20-2001 00:00:00 1427341 fzd2abnd.exe
+05-22-2001 00:00:00 121436 fzd2nal.exe
+05-22-2001 00:00:00 293122 fzd2nal1.exe
+12-18-2001 00:00:00 333581 fzd2nal2.exe
+05-23-2001 00:00:00 250445 fzd2zapp.exe
+10-10-2001 00:00:00 2619032 g32ep3b.exe
+11-23-1998 00:00:00 26193920 g41c5a41.tar
+11-23-1998 00:00:00 25907200 g41c5a43.tar
+11-23-1998 00:00:00 25190400 g41c5dg.tar
+11-23-1998 00:00:00 27494400 g41c5hp.tar
+11-23-1998 00:00:00 29337600 g41c5ncr.tar
+11-23-1998 00:00:00 27146240 g41c5sc5.tar
+11-23-1998 00:00:00 26982400 g41c5sl5.tar
+11-23-1998 00:00:00 26961920 g41c5sl6.tar
+11-23-1998 00:00:00 32808960 g41c5sun.tar
+11-23-1998 00:00:00 3614720 g41m5a41.tar
+11-23-1998 00:00:00 3604480 g41m5a43.tar
+11-23-1998 00:00:00 3481600 g41m5dg.tar
+11-23-1998 00:00:00 4280320 g41m5hp.tar
+11-23-1998 00:00:00 4495360 g41m5ncr.tar
+11-23-1998 00:00:00 5263360 g41m5sc5.tar
+11-23-1998 00:00:00 4116480 g41m5sl5.tar
+11-23-1998 00:00:00 4106240 g41m5sl6.tar
+11-20-1998 00:00:00 5939200 g41m5sun.tar
+06-02-2000 00:00:00 93137892 g526east.exe
+06-02-2000 00:00:00 84011178 g526kcc.exe
+06-02-2000 00:00:00 106015153 g526mult.exe
+06-02-2000 00:00:00 92474943 g526scan.exe
+06-02-2000 00:00:00 74449657 g526us.exe
+06-02-2000 00:00:00 80161031 g526usde.exe
+06-02-2000 00:00:00 77052636 g526usjp.exe
+12-18-1997 00:00:00 20712319 g52a1aix.z
+12-18-1997 00:00:00 17069171 g52a1hp.z
+12-18-1997 00:00:00 14703356 g52a1sol.z
+06-02-2000 00:00:00 7595802 g554ar.exe
+06-02-2000 00:00:00 39304570 g554en.exe
+06-02-2000 00:00:00 13651283 g554est.exe
+06-02-2000 00:00:00 7587459 g554he.exe
+06-02-2000 00:00:00 23317212 g554jp.exe
+06-02-2000 00:00:00 22871590 g554kcc.exe
+06-02-2000 00:00:00 30379240 g554mlt.exe
+06-02-2000 00:00:00 30469595 g554scn.exe
+08-31-2000 00:00:00 3252251 g5notmb1.exe
+08-08-1995 00:00:00 1983381 gam10.exe
+07-20-1998 00:00:00 565411 gbm21y2k.exe
+11-19-1996 00:00:00 547498 gdsmtp.exe
+10-21-1996 00:00:00 26760 gdusc1.exe
+09-18-1993 00:00:00 32876 genbio.exe
+10-03-2001 00:00:00 4589470 gep3beng.exe
+08-16-1999 00:00:00 12570112 gm527aen.bin
+06-14-2000 00:00:00 12556928 gm528aen.bin
+06-19-2000 00:00:00 12558720 gm528ben.bin
+12-21-1996 00:00:00 6081664 gmcec3.hqx
+12-21-1996 00:00:00 6086656 gmcfc3.hqx
+12-24-1996 00:00:00 6089856 gmesc3.hqx
+12-20-1996 00:00:00 6087552 gmfrc3.hqx
+12-24-1996 00:00:00 6084480 gmitc3.hqx
+12-19-1996 00:00:00 6079872 gmozc3.hqx
+12-19-1996 00:00:00 6081792 gmukc3.hqx
+12-11-1996 00:00:00 6079872 gmusc3.hqx
+09-18-1993 00:00:00 26557 gpierr.exe
+08-28-1996 00:00:00 189508 gpwrdk.exe
+08-28-1996 00:00:00 114332 gpwrnl.exe
+09-03-1996 00:00:00 99491 gpwrru.exe
+08-28-1996 00:00:00 131835 gpwrsu.exe
+08-22-1996 00:00:00 170183 gpwrsv.exe
+02-25-1998 00:00:00 74740 gpwsbr.exe
+02-25-1998 00:00:00 44964 gpwsde.exe
+02-25-1998 00:00:00 40264 gpwsfr.exe
+02-25-1998 00:00:00 39224 gpwsit.exe
+07-22-1999 00:00:00 47842 groupfix.exe
+10-19-1995 00:00:00 207875 gsc41.exe
+12-15-1997 00:00:00 811983 gsc51.exe
+06-08-1995 00:00:00 9805824 gusmtp.tar
+07-28-1999 00:00:00 4658880 gw41api.exe
+11-17-1999 00:00:00 1307103 gw41api2.exe
+07-29-1999 00:00:00 30983798 gw41aus.exe
+02-28-1996 00:00:00 86653 gw41qa.exe
+12-10-1998 00:00:00 20978 gw41sp5.txt
+01-08-1998 00:00:00 18251583 gw51sp2a.exe
+03-10-1998 00:00:00 3483616 gw51w16a.exe
+01-09-2001 00:00:00 1931948 gw52ch6.exe
+06-26-2000 00:00:00 479758 gw52sp6.exe
+02-28-2002 16:19:00 35836761 gw555cck.exe
+02-28-2002 16:34:00 26614908 gw555ee.exe
+05-31-2000 00:00:00 372421 gw55bk.exe
+02-03-2000 00:00:00 109887 gw55bp.exe
+06-19-2000 00:00:00 847939 gw55dutl.exe
+08-14-2001 00:00:00 58548675 gw55ep3a.exe
+06-25-1999 00:00:00 2497895 gw55inst.exe
+06-27-2000 00:00:00 3742457 gw55ol2.exe
+04-18-2001 00:00:00 219963 gw55puma.exe
+03-01-1999 00:00:00 19376 gw55rc.exe
+12-18-1998 00:00:00 45201 gw55sp1u.exe
+02-28-2002 16:08:00 21311033 gw55sp5a.exe
+02-19-2002 17:56:00 52764291 gw55sp5e.exe
+02-28-2002 16:13:00 21300984 gw55sp5h.exe
+02-19-2002 18:03:00 43933605 gw55sp5m.exe
+02-28-2002 16:03:00 44001516 gw55sp5s.exe
+03-09-1999 00:00:00 5867520 gw55uagb.tar
+04-23-1997 00:00:00 20446033 gw5img.exe
+11-21-2001 00:00:00 313843533 gw6sp1.exe
+11-20-2001 00:00:00 313466368 gw6sp1fr.exe
+03-13-2002 18:35:00 26705047 gw6tomcat_nt.exe
+10-15-2001 00:00:00 318278 gw6wasf.exe
+01-22-1997 00:00:00 493803 gwadm.exe
+07-26-2000 00:00:00 1900719 gwafe510.exe
+11-02-1999 00:00:00 469618 gwanlzr1.exe
+06-19-2000 00:00:00 479013 gwata417.exe
+06-19-2000 00:00:00 1731751 gwata517.exe
+08-12-1996 00:00:00 168008 gwbr41.exe
+08-31-1998 00:00:00 17881984 gwbrc5.exe
+08-26-1997 00:00:00 194213 gwbupaus.exe
+06-15-2000 00:00:00 885247 gwca55.exe
+06-29-2000 00:00:00 902786 gwca55us.exe
+08-17-1999 00:00:00 2398720 gwccarch.exe
+08-27-1998 00:00:00 19751754 gwcec5.exe
+12-01-1998 00:00:00 18095569 gwcfc5a.exe
+01-22-1997 00:00:00 499022 gwclint.exe
+06-19-2000 00:00:00 274618 gwclust.exe
+08-31-1998 00:00:00 18704283 gwczc5.exe
+08-28-1998 00:00:00 18602662 gwdec5.exe
+01-22-1997 00:00:00 577392 gwdirsnc.exe
+08-31-1998 00:00:00 18044524 gwdkc5.exe
+08-16-2001 00:00:00 2064976 gwe2mlfx.exe
+04-18-2001 00:00:00 220287 gweppuma.exe
+02-19-2002 17:38:00 106411074 gwepsp4e.exe
+02-19-2002 17:48:00 105412358 gwepsp4m.exe
+10-15-2001 00:00:00 211359 gwepwasf.exe
+08-31-1998 00:00:00 18156006 gwesc5.exe
+08-20-1999 00:00:00 2278400 gwexarch.exe
+09-02-1998 00:00:00 18094284 gwfrc5.exe
+02-05-2002 12:22:00 14809111 gwia6sp1.exe
+12-24-1998 00:00:00 47599 gwip.exe
+06-26-2000 00:00:00 2103744 gwiru55.exe
+08-31-1998 00:00:00 18176506 gwitc5.exe
+05-20-1997 00:00:00 1643991 gwjpc3.exe
+08-24-1999 00:00:00 2689024 gwlnarch.exe
+08-31-1998 00:00:00 18450385 gwmac5.exe
+06-19-2001 00:00:00 104256 gwmacvew.exe
+01-22-1997 00:00:00 521879 gwmigrat.exe
+08-18-1999 00:00:00 2387456 gwmsarch.exe
+08-31-1998 00:00:00 18442250 gwnlc5.exe
+08-31-1998 00:00:00 18496070 gwnoc5.exe
+08-27-1998 00:00:00 18436940 gwozc5.exe
+08-29-2001 00:00:00 735542 gwpdchk.exe
+08-28-2001 00:00:00 29521018 gwpdlk56.exe
+08-14-2001 00:00:00 29520686 gwpdlock.exe
+08-31-1998 00:00:00 18696898 gwplc5.exe
+03-05-1996 00:00:00 1388969 gwpoc.exe
+08-31-1998 00:00:00 17738497 gwpoc5.exe
+01-22-2002 16:48:00 10400450 gwport32.exe
+08-31-1998 00:00:00 18492682 gwruc5.exe
+08-31-1998 00:00:00 18154021 gwsuc5.exe
+08-31-1998 00:00:00 17958220 gwsvc5.exe
+01-16-2002 09:41:00 536848 gwsyclo.exe
+11-09-1999 00:00:00 78740 gwtps1v2.exe
+08-28-1998 00:00:00 18432206 gwukc5.exe
+08-27-1998 00:00:00 18544901 gwusc5.exe
+10-18-1995 00:00:00 210542 gwusr1.exe
+10-18-1995 00:00:00 1404401 gwusr2.exe
+03-28-1997 00:00:00 2467040 gwusr3.exe
+10-01-1997 00:00:00 767611 gwwa4p1.exe
+03-04-1998 00:00:00 2092781 gwwebcgi.z
+08-04-1999 00:00:00 345006 gwy195.exe
+10-09-2001 00:00:00 102293 hdir501c.exe
+08-21-1998 00:00:00 1138106 highutl1.exe
+03-28-1995 00:00:00 567026 hpt004.exe
+03-09-1995 00:00:00 64329 hpt005.exe
+08-27-1996 00:00:00 602958 hpt006.exe
+03-09-1995 00:00:00 497382 hpt007.exe
+03-09-1995 00:00:00 510029 hpt008.exe
+03-13-1995 00:00:00 596667 hpt009.exe
+11-20-1995 00:00:00 942798 hpt011.exe
+08-11-1995 00:00:00 176332 hpt013.exe
+03-16-1999 00:00:00 1070543 hstdev.exe
+04-05-2002 14:51:00 246782 httpstk1.exe
+04-19-2000 00:00:00 262791 i2odrv5.exe
+07-20-1998 00:00:00 565749 ibm21y2k.exe
+09-18-1993 00:00:00 24735 ibmmem.exe
+09-18-1993 00:00:00 60883 ibmrt.exe
+07-11-2001 00:00:00 2621963 ic15fp2.exe
+02-08-2002 16:39:00 2905716 ic15fp3.exe
+04-04-2001 00:00:00 9581302 ic15sp1.exe
+12-14-2001 00:00:00 1585498 ic20fp1.exe
+01-14-2002 09:32:00 4520778 ic20fp2.exe
+05-30-2002 15:01:00 4777958 ic20sp1.exe
+03-28-2002 17:46:00 142010 ichcdump.exe
+09-20-1994 00:00:00 36043 ide.exe
+09-18-1993 00:00:00 24552 ide286.exe
+09-18-1993 00:00:00 27300 ide386.exe
+06-09-2000 00:00:00 105249 ideata5a.exe
+04-17-2000 00:00:00 1356133 ihp232.exe
+03-08-2002 15:40:00 93664 imspmfix.exe
+07-23-1998 00:00:00 7338542 in42sp2.exe
+11-08-1995 00:00:00 430410 ind41.exe
+03-20-1997 00:00:00 63751 inetcs.exe
+03-20-1997 00:00:00 60414 inetct.exe
+04-28-1997 00:00:00 69792 inetha.exe
+10-18-1995 00:00:00 1094896 inf1.exe
+10-18-1995 00:00:00 798379 inff1.exe
+01-09-2002 00:00:00 151877 installa.exe
+06-09-1995 00:00:00 836804 instll.exe
+10-09-2000 00:00:00 101582 instp5x.exe
+09-18-1993 00:00:00 39511 int215.exe
+09-18-1993 00:00:00 19521 intfix.exe
+09-18-1993 00:00:00 35521 intrud.exe
+12-04-1997 00:00:00 5594188 inwc2enh.exe
+09-18-1993 00:00:00 69340 ipc212.exe
+09-18-1993 00:00:00 24423 ipcfg.exe
+08-13-2001 00:00:00 593463 ipcost.exe
+06-24-1999 00:00:00 131414 ipg4201a.exe
+06-30-2000 00:00:00 617600 ipgc07a.exe
+02-11-2000 00:00:00 233838 ipgsb06.exe
+10-02-1999 00:00:00 107564 ipgsn10a.exe
+11-15-1999 00:00:00 44888 ipgwdoc.exe
+09-18-1993 00:00:00 65876 ipt112.exe
+09-23-1998 00:00:00 842325 ipx660.exe
+12-01-1995 00:00:00 37227 ipxspx.exe
+09-18-1993 00:00:00 22904 isa30.exe
+09-18-1993 00:00:00 31546 isa311.exe
+09-18-1993 00:00:00 24391 isarem.exe
+04-09-1997 00:00:00 49650 iwsbp1.exe
+11-21-2000 00:00:00 6073482 jbm30sp3.exe
+10-19-1995 00:00:00 109173 jcon.exe
+08-16-2001 00:00:00 185167 jr08993.exe
+08-15-2001 00:00:00 54187 jr10449.exe
+08-15-2001 00:00:00 51804 jr10470.exe
+05-29-2001 00:00:00 105466 jr10490.exe
+10-16-2000 00:00:00 17936 jr10662.exe
+10-16-2000 00:00:00 51421 jr10803.exe
+08-15-2001 00:00:00 884373 jr10823.exe
+08-15-2001 00:00:00 1909 jr10923.zip
+10-16-2000 00:00:00 53610 jr11209.exe
+10-16-2000 00:00:00 272210 jr11213.exe
+05-27-2001 00:00:00 32984 jr11223.exe
+10-16-2000 00:00:00 45200 jr11409.exe
+05-27-2001 00:00:00 488829 jr12054.exe
+08-15-2001 00:00:00 17761 jr12089.exe
+05-27-2001 00:00:00 245833 jr12125.exe
+08-15-2001 00:00:00 242650 jr12129.exe
+05-27-2001 00:00:00 144543 jr12229.exe
+05-27-2001 00:00:00 23194 jr12349.exe
+08-15-2001 00:00:00 158924 jr12415.exe
+10-16-2000 00:00:00 39844 jr12518.exe
+10-16-2000 00:00:00 42015 jr12676.exe
+05-27-2001 00:00:00 42090 jr12692.exe
+05-29-2001 00:00:00 41998 jr12705.exe
+10-16-2000 00:00:00 21903 jr12706.exe
+10-16-2000 00:00:00 75818 jr12765.exe
+08-15-2001 00:00:00 245898 jr12768.exe
+10-16-2000 00:00:00 144542 jr12773.exe
+05-29-2001 00:00:00 144542 jr12775.exe
+08-15-2001 00:00:00 144543 jr12776.exe
+10-16-2000 00:00:00 44352 jr12777.exe
+05-27-2001 00:00:00 44355 jr12778.exe
+08-15-2001 00:00:00 43721 jr12828.exe
+05-27-2001 00:00:00 52823 jr12890.exe
+10-16-2000 00:00:00 52824 jr12947.exe
+10-16-2000 00:00:00 74323 jr12978.exe
+05-27-2001 00:00:00 74323 jr12979.exe
+05-29-2001 00:00:00 74326 jr12987.exe
+05-27-2001 00:00:00 16573256 jr13042.exe
+08-15-2001 00:00:00 16586769 jr13046.exe
+08-15-2001 00:00:00 170632 jr13047.exe
+08-15-2001 00:00:00 55210 jr13105.exe
+08-15-2001 00:00:00 124966 jr13147.exe
+10-16-2000 00:00:00 43318 jr13259.exe
+10-16-2000 00:00:00 33183 jr13461.exe
+05-27-2001 00:00:00 84700 jr13554.exe
+10-16-2000 00:00:00 84649 jr13555.exe
+05-27-2001 00:00:00 52564 jr13557.exe
+10-16-2000 00:00:00 52161 jr13558.exe
+05-29-2001 00:00:00 52167 jr13559.exe
+05-27-2001 00:00:00 54942 jr13616.exe
+10-16-2000 00:00:00 54947 jr13617.exe
+08-15-2001 00:00:00 56424 jr13619.exe
+09-17-1999 00:00:00 71827 jr13627.exe
+10-16-2000 00:00:00 83182 jr13637.exe
+05-29-2001 00:00:00 108483 jr13722.exe
+08-15-2001 00:00:00 170173 jr13734.exe
+08-15-2001 00:00:00 641941 jr13748.exe
+05-29-2001 00:00:00 641950 jr13749.exe
+05-29-2001 00:00:00 579521 jr13886.exe
+08-15-2001 00:00:00 126491 jr13891.exe
+05-27-2001 00:00:00 109292 jr14132.exe
+08-15-2001 00:00:00 109181 jr14134.exe
+05-29-2001 00:00:00 39830 jr14185.exe
+08-15-2001 00:00:00 72780 jr14278.exe
+08-15-2001 00:00:00 345689 jr14358.exe
+05-27-2001 00:00:00 642240 jr14359.exe
+10-16-2000 00:00:00 642388 jr14360.exe
+05-27-2001 00:00:00 313078 jr14367.exe
+05-27-2001 00:00:00 109587 jr14402.exe
+08-15-2001 00:00:00 71603 jr14457.exe
+08-15-2001 00:00:00 567270 jr14500.exe
+08-15-2001 00:00:00 157611 jr14523.exe
+08-15-2001 00:00:00 161290 jr14556.exe
+05-27-2001 00:00:00 161439 jr14585.exe
+10-16-2000 00:00:00 161435 jr14586.exe
+10-16-2000 00:00:00 186037 jr14840.exe
+10-16-2000 00:00:00 368604 jr14936.exe
+08-15-2001 00:00:00 115132 jr15013.exe
+08-15-2001 00:00:00 568164 jr15133.exe
+08-15-2001 00:00:00 217169 jr15338.exe
+08-15-2001 00:00:00 362664 jr15396.exe
+08-15-2001 00:00:00 104143 jr15509.exe
+08-15-2001 00:00:00 473822 jr15544.exe
+07-25-2001 00:00:00 484196 jssl11d.exe
+07-20-2001 00:00:00 36251555 jvm122.exe
+02-28-2002 08:06:00 49007010 jvm131.exe
+03-28-2001 00:00:00 48672254 jzfd3sp1.exe
+07-17-1997 00:00:00 66469 killq.exe
+03-01-1994 00:00:00 202716 l11f01.exe
+03-01-1994 00:00:00 202878 l11g01.exe
+03-01-1994 00:00:00 202460 l11i01.exe
+01-06-1994 00:00:00 23583 l11p06.exe
+03-01-1994 00:00:00 202249 l11s01.exe
+11-24-1993 00:00:00 30533 l11u05.exe
+04-20-1999 00:00:00 206616 lanchk.exe
+10-21-1996 00:00:00 341280 landr9.exe
+05-14-1998 00:00:00 4610909 landrv.exe
+09-10-1996 00:00:00 24799 lanwcs.exe
+09-04-1996 00:00:00 37088 lanwct.exe
+09-04-1996 00:00:00 42514 lanwes.exe
+09-11-1996 00:00:00 42417 lanwfr.exe
+09-10-1996 00:00:00 36855 lanwha.exe
+09-04-1996 00:00:00 42397 lanwit.exe
+01-31-2002 16:00:00 16012931 lanwp02.exe
+12-16-1996 00:00:00 342390 lat002.exe
+09-18-1993 00:00:00 133326 ld401a.exe
+02-07-2000 00:00:00 166765 ldr312ft.exe
+09-18-1993 00:00:00 26450 leap.exe
+06-09-1994 00:00:00 180540 lg4084.exe
+12-14-1995 00:00:00 91840 lg42l4.exe
+10-11-1995 00:00:00 72061 li3pre.exe
+06-02-1998 00:00:00 258605 lib311b.exe
+09-20-1999 00:00:00 273268 lib312d.exe
+02-23-2000 00:00:00 977416 libupj4.exe
+06-26-1995 00:00:00 111269 lo30a2.exe
+06-26-1995 00:00:00 94927 lo30t1.exe
+09-18-1993 00:00:00 105128 load.exe
+08-26-1998 00:00:00 111722 loaddll1.exe
+09-18-1993 00:00:00 20810 locins.exe
+03-09-1995 00:00:00 74768 log376.exe
+09-15-1997 00:00:00 269333 log410a.exe
+02-23-2000 00:00:00 99524 longnam.exe
+03-05-1997 00:00:00 1563061 lpo51a.exe
+03-14-1997 00:00:00 115601 lpo51b.exe
+06-12-1995 00:00:00 373114 lw42w2.exe
+09-20-1996 00:00:00 986579 lw50w1.exe
+08-21-1996 00:00:00 79276 lwg50a.exe
+08-18-1998 00:00:00 115527 lwp001.exe
+08-20-1998 00:00:00 54951 lwp002.exe
+05-06-1996 00:00:00 447982 lwp413.exe
+11-30-1994 00:00:00 231591 lwp423.exe
+05-18-1998 00:00:00 26516 lwp501.exe
+05-15-1998 00:00:00 27895 lwp511.exe
+09-18-1993 00:00:00 21913 lwpo30.exe
+09-03-1997 00:00:00 47334 lwpping.exe
+08-09-1999 00:00:00 356846 lzfw01c.exe
+10-18-1993 00:00:00 33252 lzfwdi.exe
+07-14-1999 00:00:00 1083871 lzfwlf.exe
+06-16-1995 00:00:00 29057 lzfwqa.exe
+09-07-1994 00:00:00 26848 lzw001.exe
+05-16-1995 00:00:00 29431 lzw002.exe
+09-18-1993 00:00:00 151295 lzw40.exe
+09-18-1993 00:00:00 29379 m30pat.exe
+07-24-1996 00:00:00 122720 macfil.exe
+07-10-1997 00:00:00 347278 macpt3d.exe
+05-29-1996 00:00:00 193792 mactsa.bin
+07-23-1996 00:00:00 232349 mactsa.exe
+02-21-1996 00:00:00 210004 mailcl.exe
+03-13-1995 00:00:00 48964 map312.exe
+11-24-1997 00:00:00 144574 map410b.exe
+10-10-2001 00:00:00 127956 masv_sp3.exe
+02-28-2001 00:00:00 266084 mbcmnup1.exe
+08-13-1998 00:00:00 508288 mclupd6a.bin
+09-18-1993 00:00:00 22803 mcmfm.exe
+02-11-1994 00:00:00 37710 mdf178.exe
+09-18-1993 00:00:00 87520 menu34.exe
+11-15-1993 00:00:00 20214 menuhi.exe
+09-18-1993 00:00:00 91376 menus.exe
+08-15-2001 00:00:00 5040875 mgt22010.exe
+11-03-1993 00:00:00 683946 mhs173.exe
+02-14-1994 00:00:00 656047 mhs183.exe
+02-07-1994 00:00:00 664789 mhs184.exe
+11-03-1997 00:00:00 85281 mhsmcu.exe
+09-18-1993 00:00:00 54627 mhsmd.exe
+08-16-1994 00:00:00 604103 mhsslt.exe
+06-30-1995 00:00:00 132603 mhsvr1.exe
+08-01-1996 00:00:00 449605 migrat.exe
+09-18-1993 00:00:00 33708 mirrem.exe
+01-05-2000 00:00:00 27044 mixmod6.exe
+09-18-1993 00:00:00 96673 mkuser.exe
+09-18-1995 00:00:00 68504 mon176.exe
+05-18-1995 00:00:00 66024 monsft.exe
+09-18-1993 00:00:00 424897 morebk.exe
+09-18-1993 00:00:00 37818 mountr.exe
+09-18-1993 00:00:00 19452 mouse.exe
+02-03-1994 00:00:00 32801 mpr182.exe
+07-15-1994 00:00:00 125166 mpr199.exe
+06-04-1996 00:00:00 1066126 mpr31a.exe
+10-28-1996 00:00:00 1082729 mpr31b.exe
+09-23-1994 00:00:00 31245 mprper.exe
+03-24-1995 00:00:00 38997 mprul3.exe
+10-11-1995 00:00:00 122440 mprx25.exe
+08-02-1996 00:00:00 328085 msml21.exe
+10-05-1998 00:00:00 5876316 msmlos21.exe
+08-02-1999 00:00:00 70822 msmpcu.exe
+05-31-2000 00:00:00 6355314 mw26sp3.exe
+07-31-2000 00:00:00 119531 mw26trd1.exe
+11-13-2000 00:00:00 3054719 mw27sp1.exe
+11-23-1999 00:00:00 27173 mw5mcal1.exe
+05-17-2000 00:00:00 253007 mwhp01b.exe
+01-25-2002 11:47:00 255066 mwhp01c.exe
+09-01-2000 00:00:00 9813556 mwinoc1k.exe
+09-01-2000 00:00:00 8298211 mwinoc2k.exe
+02-20-2002 14:35:00 141530 mwipgrop.exe
+10-09-1996 00:00:00 566807 mwmis01.exe
+01-26-1999 00:00:00 1070535 mwnma26.exe
+10-16-1998 00:00:00 265545 mwnma3a.exe
+10-16-1998 00:00:00 300304 mwnma4a.exe
+04-12-2001 00:00:00 2180810 mwnmaupd.exe
+01-12-2000 00:00:00 154598 mwnxp26.exe
+04-09-2001 00:00:00 339201 mwnxpfix.exe
+08-20-1999 00:00:00 1502706 mwzen01.exe
+03-28-2001 00:00:00 58460632 mzfd3sp1.exe
+05-24-2001 00:00:00 2407200 n51_nis1.exe
+05-16-2000 00:00:00 6840962 n8slinux.01
+02-18-1998 00:00:00 217465 na4nty2k.exe
+09-18-1993 00:00:00 48510 nacs2.exe
+05-28-1996 00:00:00 64238 nadhep.exe
+03-23-1999 00:00:00 1777018 nal201p2.exe
+10-29-1996 00:00:00 38276 nam312.exe
+06-06-2000 00:00:00 199571 nam41d.exe
+05-24-2002 15:12:00 104382 nat600d.exe
+09-18-1993 00:00:00 322806 nbckup.exe
+01-10-1997 00:00:00 21328 nbora.exe
+08-12-1997 00:00:00 18843 nc1tip.txt
+06-03-2002 09:30:00 838367 nccutl10.exe
+10-24-2000 00:00:00 7725859 nce8slr1.z
+09-18-1993 00:00:00 77251 nconfg.exe
+10-10-1997 00:00:00 19889 ncpec.exe
+09-15-1997 00:00:00 144892 ncpy410a.exe
+11-21-2000 00:00:00 136962 ncs3.exe
+10-01-1996 00:00:00 704205 ncv201.exe
+10-01-1996 00:00:00 811853 ncv202.exe
+04-21-1998 00:00:00 489774 ncv20y2k.exe
+11-12-2001 00:00:00 142314 ndb410q.exe
+02-21-2002 13:36:00 820712 ndp21p3c.exe
+06-21-2002 12:06:00 853818 ndp21p4.exe
+10-17-2001 00:00:00 1008445 ndp2xp7.exe
+02-21-2002 13:53:00 530101 ndpcnw6.exe
+02-21-2002 13:48:00 909348 ndpcsp3a.exe
+07-17-2001 00:00:00 94047 ndpsinf.exe
+10-04-2001 00:00:00 11673051 ndpsw2k.exe
+09-18-1993 00:00:00 59495 ndr345.exe
+02-02-2000 00:00:00 112722 nds4ntp1.exe
+08-17-2000 00:00:00 507960 nds4ntu3.exe
+10-27-2000 00:00:00 3437308 nds8lnx1.gz
+07-17-2001 00:00:00 14133762 ndsas3s1.exe
+09-18-1993 00:00:00 24182 ndscsi.exe
+09-18-1993 00:00:00 41652 ndspx.exe
+07-20-2000 00:00:00 6712 ndssch.gz
+09-18-1993 00:00:00 20023 ndstac.exe
+09-18-1993 00:00:00 211239 ne286.exe
+10-24-2000 00:00:00 5894979 ned8slr1.z
+05-03-2000 00:00:00 82148198 nesn451a.exe
+12-20-2000 00:00:00 1157470 nesn51b.exe
+11-28-2001 00:00:00 866140 nesn51c.exe
+03-05-2002 06:54:00 865375 nesn51d.exe
+03-16-1999 00:00:00 138202 netarng3.exe
+02-04-1998 00:00:00 73822 netfr.exe
+03-12-1996 00:00:00 306211 netusr.exe
+02-04-1998 00:00:00 74054 netwbr.exe
+02-04-1998 00:00:00 56229 netwde.exe
+08-28-1996 00:00:00 27699 netwdk.exe
+02-02-1998 00:00:00 67776 netwes.exe
+02-12-1998 00:00:00 59210 netwit.exe
+08-28-1996 00:00:00 28000 netwno.exe
+09-10-1996 00:00:00 53501 netwru.exe
+08-23-1996 00:00:00 27741 netwsv.exe
+03-18-2002 15:27:00 1539054 nfap1sp1.exe
+08-22-1994 00:00:00 290090 nfs193.exe
+12-30-1997 00:00:00 2266015 nfs203.exe
+11-23-1998 00:00:00 2007873 nfs205.exe
+07-20-2001 00:00:00 6472548 nfs30sp2.exe
+03-06-2002 15:56:00 1310460 nfs30sp3a.exe
+05-29-2002 14:59:00 1186381 nfs3nwci.exe
+08-28-2001 00:00:00 5440307 nfs3sp1.exe
+02-02-2001 00:00:00 1280002 nfsadmn2.exe
+01-20-1998 00:00:00 38114 nfsmlaup.exe
+08-02-1999 00:00:00 35803 nfsnam23.exe
+09-18-1993 00:00:00 245015 ngm121.exe
+09-18-1993 00:00:00 1240500 ngm137.exe
+09-18-1993 00:00:00 145298 ngm138.exe
+09-18-1993 00:00:00 145010 ngm139.exe
+10-28-1993 00:00:00 781292 ngm170.exe
+12-03-1993 00:00:00 202093 ngm175.exe
+12-06-1993 00:00:00 201248 ngm176.exe
+05-26-1994 00:00:00 279862 ngm192.exe
+12-20-1996 00:00:00 945888 ngm211.exe
+08-05-1995 00:00:00 1403369 ngwadm.exe
+08-13-1996 00:00:00 1810533 ngwaup.exe
+10-31-1995 00:00:00 106862 ngwmfc.exe
+03-15-1995 00:00:00 662953 ngwsnc.exe
+09-18-1993 00:00:00 27283 ni5010.exe
+07-10-2001 00:00:00 786223 nicid157.exe
+07-10-2001 00:00:00 761229 nicie157.exe
+01-15-2002 11:38:00 59300 nicimig.tgz
+01-17-2002 09:35:00 6802379 nims265.tgz
+01-31-2002 10:19:00 2526415 nims265.zip
+01-31-2002 11:14:00 121765 nims265a.zip
+01-14-2002 16:09:00 4894646 nims26l.tgz
+01-14-2002 16:05:00 2492982 nims26n.zip
+02-27-2002 16:49:00 5385381 nims26sb.z
+11-08-1999 00:00:00 343052 nims2_1a.exe
+04-15-2002 15:54:00 12495019 nims303.tar.z
+04-15-2002 15:53:00 7563916 nims303.tgz
+04-15-2002 15:54:00 7696073 nims303.zip
+05-23-1997 00:00:00 1252720 nip202.exe
+10-23-1998 00:00:00 1180104 nip203.exe
+04-19-1996 00:00:00 6212358 nip22b.exe
+07-09-1996 00:00:00 555990 nip318.exe
+07-09-1996 00:00:00 69020 nip319.exe
+11-02-2001 00:00:00 2489203 nipp10a.exe
+09-19-2000 00:00:00 3753117 nipt1.exe
+03-05-1996 00:00:00 6369467 nipw22.exe
+05-29-1996 00:00:00 42316 nipw2x.exe
+06-07-2000 00:00:00 4286209 njcl5a.exe
+06-10-1998 00:00:00 102325 nls212.exe
+07-24-2000 00:00:00 155414 nlsdll.exe
+05-25-2001 00:00:00 16952278 nlslsp6.exe
+01-04-2000 00:00:00 215729 nlsty2k.exe
+11-28-1995 00:00:00 1462112 nms002.exe
+03-08-1994 00:00:00 48618 nmsddf.exe
+11-15-1994 00:00:00 434841 nmsxp1.exe
+09-18-1993 00:00:00 28499 nnscpt.exe
+09-18-1993 00:00:00 88964 nnst40.exe
+09-18-1993 00:00:00 89092 nnstll.exe
+07-25-1995 00:00:00 32483 not131.exe
+10-12-1998 00:00:00 6707094 notes41.exe
+06-08-2000 00:00:00 4556171 notes51.exe
+09-18-1993 00:00:00 24900 novadf.exe
+09-18-1993 00:00:00 30691 np600a.exe
+08-02-1999 00:00:00 17097790 nppb_1.exe
+08-02-1999 00:00:00 17097771 nppb_2.exe
+03-15-2002 16:33:00 633317 nps15dpa.exe
+06-28-2002 09:08:00 31183790 nps15sp1.exe
+09-10-2001 00:00:00 8200267 npsgad01.exe
+04-12-2001 00:00:00 114902 npsnsapi.exe
+02-11-2002 15:57:00 615863 nptr95b.exe
+06-30-1997 00:00:00 22915 nrsbuild.exe
+06-23-1997 00:00:00 793469 nrsnt.exe
+06-18-1998 00:00:00 53586091 nsbgwsp3.exe
+03-22-1994 00:00:00 455182 nsd004.exe
+08-21-1998 00:00:00 1964329 nsr511n.zip
+06-24-1996 00:00:00 1935353 nsrtr51n.zip
+02-13-2002 13:36:00 93785 nsschk1a.exe
+07-30-1997 00:00:00 116845 nsync1.exe
+09-16-1999 00:00:00 10933860 nt411b.exe
+10-26-1998 00:00:00 1084753 nt411p1.exe
+04-06-1999 00:00:00 744586 nt430p2.exe
+06-22-1999 00:00:00 834534 nt451p1.exe
+03-23-2000 00:00:00 920405 nt46pt1.exe
+10-03-1999 00:00:00 4017917 nt46sp2.exe
+08-11-2000 00:00:00 765887 nt471pt2.exe
+06-13-2000 00:00:00 448015 nt47pt3.exe
+05-09-2002 07:26:00 1081217 nt480pt5.exe
+11-06-2001 00:00:00 898400 nt481pt1.exe
+06-14-2002 14:07:00 291026 nt483pt2.exe
+11-19-1998 00:00:00 150230 ntprint.exe
+07-18-1995 00:00:00 114593 ntwin.exe
+09-18-1993 00:00:00 28138 nver30.exe
+01-07-1997 00:00:00 28798 nw3dfs.exe
+01-07-1997 00:00:00 24257 nw4dfs.exe
+11-13-2000 00:00:00 80377034 nw4sp9.exe
+08-27-2001 00:00:00 866224 nw4wsock.exe
+12-20-2000 00:00:00 158210659 nw50sp6a.exe
+07-23-2001 00:00:00 490599 nw51fs1.exe
+02-17-2000 00:00:00 684981 nw51inst.exe
+08-21-2001 00:00:00 513640 nw51nrm1.exe
+07-24-2001 00:00:00 294037836 nw51sp3.exe
+02-25-2002 11:26:00 300006242 nw51sp4.exe
+04-27-2000 00:00:00 332610 nw51upd1.exe
+06-24-2002 14:54:00 3250529 nw56up1.exe
+09-09-1999 00:00:00 38435 nw5nss.exe
+02-17-2000 00:00:00 251511 nw5nwip.exe
+05-16-2000 00:00:00 169896 nw5psrv2.exe
+06-20-2000 00:00:00 378831 nw5tcp.exe
+03-22-2002 16:33:00 1533365 nw6nss1a.exe
+10-22-2001 00:00:00 633339 nw6sms1a.exe
+03-06-2002 17:15:00 237785656 nw6sp1.exe
+03-11-2002 12:19:00 568253661 nw6sp1ef.exe
+03-11-2002 12:59:00 567439767 nw6sp1ef56.exe
+03-22-2002 12:23:00 566604272 nw6sp1eg.exe
+03-22-2002 13:02:00 566458792 nw6sp1ei.exe
+03-11-2002 10:57:00 566528467 nw6sp1ep.exe
+03-22-2002 16:05:00 567333526 nw6sp1er.exe
+03-13-2002 16:55:00 565955338 nw6sp1es.exe
+03-23-1999 00:00:00 1344552 nwadmnp1.exe
+05-10-1995 00:00:00 478371 nwc001.exe
+02-24-1995 00:00:00 251557 nwc002.exe
+01-31-1996 00:00:00 1598884 nwc201.exe
+11-22-1995 00:00:00 1524102 nwc202.exe
+01-22-1998 00:00:00 1328082 nwc206.exe
+11-18-1996 00:00:00 1382188 nwc207.exe
+10-24-1996 00:00:00 547655 nwc208.exe
+08-12-1997 00:00:00 29587 nwc2tp.txt
+09-18-1993 00:00:00 21386 nwc386.exe
+10-05-1994 00:00:00 102446 nwcdll.exe
+02-27-1996 00:00:00 33443 nwcinf.exe
+09-11-1998 00:00:00 22331 nwcmod.exe
+09-20-1995 00:00:00 71514 nwcncs.exe
+07-11-1997 00:00:00 37424 nwcppp.exe
+03-13-2000 00:00:00 36603464 nwcssp1.exe
+03-23-2000 00:00:00 170397 nwcsupd1.exe
+02-14-1995 00:00:00 367734 nwcwin.exe
+05-22-1998 00:00:00 367002 nwcwrt.exe
+12-16-1996 00:00:00 77941 nwda01.exe
+05-08-2002 12:21:00 147838 nwftpd6.exe
+01-29-2002 15:30:00 128211 nwipadm4.exe
+11-01-1995 00:00:00 571623 nwl11e.exe
+11-01-1995 00:00:00 579046 nwl11f.exe
+11-01-1995 00:00:00 585907 nwl11g.exe
+11-01-1995 00:00:00 576676 nwl11i.exe
+11-01-1995 00:00:00 579137 nwl11s.exe
+12-13-1995 00:00:00 184137 nwltid.exe
+04-09-1999 00:00:00 13639159 nwmac.exe
+03-23-1999 00:00:00 2264037 nwmp2.exe
+06-15-2001 00:00:00 16902888 nwovly2.exe
+04-02-1997 00:00:00 2536221 nwpa300.exe
+05-07-2001 00:00:00 155727 nwpa5.exe
+12-07-2001 00:00:00 254835 nwpapt2a.exe
+11-15-1993 00:00:00 26440 nwparr.exe
+06-09-1999 00:00:00 1341903 nwpaup1a.exe
+02-27-1997 00:00:00 7763041 nws25b.exe
+03-11-1999 00:00:00 73306 nwsaahpr.exe
+02-29-2000 00:00:00 12091868 nwsb41wa.exe
+08-11-1999 00:00:00 38819 nwsp2aai.exe
+02-04-2000 00:00:00 287681 nwsso.exe
+02-24-2000 00:00:00 112641 nwtape1.exe
+11-15-1993 00:00:00 66111 nwtlg.exe
+06-16-1995 00:00:00 126883 o31mci.exe
+07-25-1995 00:00:00 73911 o4crtl.exe
+04-27-1999 00:00:00 4957532 odbcbeta.exe
+11-08-2001 00:00:00 6488080 odemandb.exe
+07-28-1999 00:00:00 671132 odi33g.exe
+07-30-1997 00:00:00 409920 odiwan1.exe
+07-18-1995 00:00:00 48296 of31pt.exe
+09-18-1993 00:00:00 111219 os2p1.exe
+12-18-1998 00:00:00 610164 os2pt2.exe
+11-26-1996 00:00:00 896477 os2u1.exe
+05-30-2000 00:00:00 4229434 os4pt1.exe
+03-02-2001 00:00:00 4227811 os5pt2a.exe
+09-18-1993 00:00:00 216072 othdrv.exe
+12-04-1996 00:00:00 66394 ovvmdl.exe
+10-25-1996 00:00:00 26153 p1000.exe
+01-03-1995 00:00:00 242785 p10g05.exe
+01-03-1995 00:00:00 242514 p10i05.exe
+01-03-1995 00:00:00 242647 p10s05.exe
+05-12-1995 00:00:00 33893 p2scsi.exe
+05-11-1999 00:00:00 659891 pager1.exe
+09-18-1993 00:00:00 50002 pat301.exe
+09-18-1993 00:00:00 50015 pat303.exe
+09-18-1993 00:00:00 49975 pat304.exe
+09-18-1993 00:00:00 49878 pat306.exe
+09-18-1993 00:00:00 29863 pat311.exe
+09-18-1993 00:00:00 49888 pat312.exe
+09-18-1993 00:00:00 49823 pat314.exe
+09-18-1993 00:00:00 33034 pat315.exe
+09-18-1993 00:00:00 49900 pat317.exe
+09-18-1993 00:00:00 49858 pat321.exe
+09-18-1993 00:00:00 49901 pat323.exe
+09-18-1993 00:00:00 50232 pat326.exe
+09-18-1993 00:00:00 49842 pat334.exe
+09-18-1993 00:00:00 49930 pat354.exe
+09-18-1993 00:00:00 30322 patman.exe
+09-18-1993 00:00:00 35789 paudfx.exe
+07-20-1998 00:00:00 565974 pbm21y2k.exe
+06-15-1994 00:00:00 63237 pburst.exe
+09-18-1993 00:00:00 35522 pcn22x.exe
+09-18-1993 00:00:00 25266 pcn23x.exe
+09-18-1993 00:00:00 46823 pcn2pa.exe
+09-18-1993 00:00:00 30816 pcnscs.exe
+09-18-1993 00:00:00 22801 pdf.exe
+09-18-1993 00:00:00 38018 pdf311.exe
+08-27-2001 00:00:00 8552350 pdlckcmp.exe
+01-22-1997 00:00:00 699150 perfectf.exe
+06-07-2000 00:00:00 214597 pfar6.exe
+09-18-1993 00:00:00 26618 pfix1.exe
+09-18-1993 00:00:00 26734 pfix3.exe
+07-18-1995 00:00:00 23435 pifoff.exe
+08-26-1999 00:00:00 70799 pkernel.exe
+08-12-1999 00:00:00 252312 pkis.pdf
+02-08-2000 00:00:00 772450 pkisnmas.exe
+09-11-1995 00:00:00 63891 plpd8.exe
+03-28-2002 12:17:00 212389 plpdsoc2.exe
+12-13-1995 00:00:00 181777 pnwtid.exe
+11-17-1995 00:00:00 186437 pnxtfx.exe
+01-03-2001 00:00:00 4463887 preds8a.exe
+09-18-1993 00:00:00 75026 pro10.exe
+11-01-1995 00:00:00 28781 prog.exe
+09-18-1993 00:00:00 23802 propth.exe
+01-29-1996 00:00:00 25129 prt312.exe
+09-18-1993 00:00:00 31193 prtime.exe
+07-20-1995 00:00:00 130827 prupc.exe
+09-18-1993 00:00:00 34893 ps110.exe
+09-18-1993 00:00:00 25963 ps2286.exe
+09-18-1993 00:00:00 24576 ps22is.exe
+09-18-1993 00:00:00 42925 ps2311.exe
+09-18-1993 00:00:00 29867 ps2386.exe
+09-18-1993 00:00:00 28205 ps2cmb.exe
+09-18-1993 00:00:00 23372 ps2esd.exe
+09-18-1993 00:00:00 24336 ps2fx.exe
+09-18-1993 00:00:00 76207 ps2isa.exe
+09-18-1993 00:00:00 23955 ps2m57.exe
+12-14-1993 00:00:00 36351 ps2opt.exe
+06-30-1995 00:00:00 162367 ps3x02.exe
+01-23-1996 00:00:00 85566 ps4x03.exe
+10-24-2001 00:00:00 172677 psrvr112.exe
+09-18-1993 00:00:00 52324 ptf286.exe
+09-18-1993 00:00:00 112633 ptf350.exe
+09-18-1993 00:00:00 48074 ptf374.exe
+09-18-1993 00:00:00 39025 ptf378.exe
+09-18-1993 00:00:00 30600 ptf380.exe
+03-25-1994 00:00:00 525519 ptf410.exe
+09-29-1993 00:00:00 501986 ptf411.exe
+09-29-1993 00:00:00 350294 ptf412.exe
+09-29-1993 00:00:00 473981 ptf413.exe
+09-29-1993 00:00:00 480777 ptf414.exe
+09-29-1993 00:00:00 488223 ptf415.exe
+10-22-1993 00:00:00 147005 ptf424.exe
+08-14-1995 00:00:00 109320 ptf425.exe
+10-18-1993 00:00:00 109064 ptf426.exe
+10-07-1994 00:00:00 292097 ptf437.exe
+04-12-1994 00:00:00 464842 ptf569.exe
+11-16-1994 00:00:00 453054 pu3x01.exe
+05-02-1995 00:00:00 553603 pu4x03.exe
+05-29-2002 17:29:00 280505 pwdsnc1.exe
+05-31-2002 11:45:00 758411 pxy031.exe
+08-31-2000 00:00:00 785651 pxyauth.exe
+11-01-1995 00:00:00 25270 qa.exe
+07-25-1995 00:00:00 22674 qaos2.exe
+07-18-1995 00:00:00 21421 qkinst.exe
+12-04-1995 00:00:00 390862 qlfix.exe
+10-05-1995 00:00:00 21028 quest.exe
+11-23-1998 00:00:00 13847723 r16524br.exe
+11-23-1998 00:00:00 15367885 r16524ce.exe
+11-23-1998 00:00:00 13974046 r16524cf.exe
+11-23-1998 00:00:00 14636368 r16524cs.exe
+11-23-1998 00:00:00 14606815 r16524ct.exe
+11-23-1998 00:00:00 14396472 r16524cz.exe
+11-23-1998 00:00:00 14526983 r16524de.exe
+11-23-1998 00:00:00 13996151 r16524dk.exe
+11-24-1998 00:00:00 14083999 r16524es.exe
+11-24-1998 00:00:00 14036283 r16524fr.exe
+11-24-1998 00:00:00 14168496 r16524it.exe
+11-30-1998 00:00:00 15194180 r16524jp.exe
+11-24-1998 00:00:00 14717983 r16524kr.exe
+11-24-1998 00:00:00 13957605 r16524ma.exe
+11-24-1998 00:00:00 13018097 r16524nl.exe
+11-24-1998 00:00:00 14282386 r16524no.exe
+11-24-1998 00:00:00 14592999 r16524oz.exe
+11-24-1998 00:00:00 14683051 r16524pl.exe
+11-24-1998 00:00:00 13868667 r16524ru.exe
+11-24-1998 00:00:00 14075816 r16524su.exe
+11-24-1998 00:00:00 14090792 r16524sv.exe
+11-24-1998 00:00:00 14598010 r16524uk.exe
+11-23-1998 00:00:00 14633171 r16524us.exe
+10-08-1999 00:00:00 13892746 r16525br.exe
+10-08-1999 00:00:00 15412960 r16525ce.exe
+10-08-1999 00:00:00 14019075 r16525cf.exe
+10-08-1999 00:00:00 14681320 r16525cs.exe
+10-08-1999 00:00:00 14651741 r16525ct.exe
+10-08-1999 00:00:00 14443408 r16525cz.exe
+08-24-1999 00:00:00 14572069 r16525de.exe
+10-08-1999 00:00:00 14041141 r16525dk.exe
+10-08-1999 00:00:00 14129003 r16525es.exe
+10-08-1999 00:00:00 14081224 r16525fr.exe
+10-08-1999 00:00:00 14213472 r16525it.exe
+10-08-1999 00:00:00 15239217 r16525jp.exe
+10-08-1999 00:00:00 14762877 r16525kr.exe
+10-08-1999 00:00:00 14004580 r16525ma.exe
+10-08-1999 00:00:00 14520305 r16525nl.exe
+10-08-1999 00:00:00 14327373 r16525no.exe
+10-08-1999 00:00:00 14638087 r16525oz.exe
+10-08-1999 00:00:00 14730025 r16525pl.exe
+10-08-1999 00:00:00 13915653 r16525ru.exe
+10-08-1999 00:00:00 14120807 r16525su.exe
+10-08-1999 00:00:00 14135776 r16525sv.exe
+10-08-1999 00:00:00 14643087 r16525uk.exe
+08-24-1999 00:00:00 14678258 r16525us.exe
+11-20-1998 00:00:00 34195974 r524east.exe
+11-21-1998 00:00:00 29934184 r524kcc.exe
+11-21-1998 00:00:00 40546603 r524mult.exe
+11-21-1998 00:00:00 33377124 r524scan.exe
+11-21-1998 00:00:00 17133749 r524us.exe
+11-21-1998 00:00:00 20919099 r524usde.exe
+12-21-1998 00:00:00 21776910 r524usjp.exe
+10-11-1999 00:00:00 33695357 r525east.exe
+10-11-1999 00:00:00 29387389 r525kcc.exe
+10-11-1999 00:00:00 39896412 r525mult.exe
+10-11-1999 00:00:00 32843372 r525scan.exe
+10-11-1999 00:00:00 18205814 r525us.exe
+10-11-1999 00:00:00 20711743 r525usde.exe
+10-14-1999 00:00:00 19744627 r525usjp.exe
+02-25-1999 00:00:00 21883384 r551en.exe
+02-26-1999 00:00:00 38653860 r551mult.exe
+02-25-1999 00:00:00 38136537 r551scan.exe
+10-19-1999 00:00:00 37890181 r552mult.exe
+10-19-1999 00:00:00 37404535 r552scan.exe
+02-11-2000 00:00:00 22183381 r553aen.exe
+02-11-2000 00:00:00 32216751 r553aest.exe
+02-11-2000 00:00:00 24925427 r553ajp.exe
+02-11-2000 00:00:00 27749699 r553akcc.exe
+02-11-2000 00:00:00 38006860 r553amlt.exe
+02-11-2000 00:00:00 37454601 r553ascn.exe
+04-06-1998 00:00:00 87518 rad102.exe
+11-23-1998 00:00:00 260651 rad104.exe
+03-04-2002 16:09:00 118100 radatr4.exe
+02-28-1997 00:00:00 575303 ramac.exe
+06-07-1995 00:00:00 66500 rbuild.exe
+02-27-1998 00:00:00 23539 rdmsg0.exe
+04-03-2000 00:00:00 91403 revfhrft.exe
+07-27-2001 00:00:00 138359 rinstall.exe
+11-04-1993 00:00:00 211615 ripsap.exe
+09-18-1993 00:00:00 192641 rlit92.exe
+09-18-1993 00:00:00 155252 rlit93.exe
+07-18-1995 00:00:00 780218 rofwin.exe
+09-18-1993 00:00:00 36120 routez.exe
+09-18-1993 00:00:00 96684 routfx.exe
+10-05-1998 00:00:00 141605 rplkt5.exe
+05-11-1994 00:00:00 72596 rsync1.exe
+09-18-1993 00:00:00 23294 rxnet.exe
+03-28-2001 00:00:00 48534006 rzfd3sp1.exe
+06-16-1994 00:00:00 39313 saa005.exe
+08-16-2001 00:00:00 534003 saa008.exe
+08-11-1994 00:00:00 80219 saa010.exe
+09-01-1994 00:00:00 142620 saa012.exe
+08-16-2001 00:00:00 943059 saa023.exe
+12-24-1996 00:00:00 154805 saa031.exe
+08-16-2001 00:00:00 4659719 saa20040.exe
+08-16-2001 00:00:00 2550556 saa21030.exe
+08-15-2001 00:00:00 63688405 saa22010.exe
+08-15-2001 00:00:00 9396094 saa2210e.exe
+08-15-2001 00:00:00 10338946 saa30020.exe
+08-15-2001 00:00:00 9315931 saa40020.exe
+06-29-2000 00:00:00 169062 saa4pt1.exe
+06-27-1995 00:00:00 20269 saamic.exe
+06-03-1998 00:00:00 1646 saapatch.txt
+11-30-1995 00:00:00 32233 saarot.exe
+08-03-1995 00:00:00 29347 saaupg.exe
+06-26-1996 00:00:00 282396 sback6.exe
+06-07-2001 00:00:00 376293 sbcon1.exe
+07-20-1998 00:00:00 564045 sbm21y2k.exe
+03-02-2001 00:00:00 8341393 sbs5pt2a.exe
+12-05-1997 00:00:00 244604 schcmp2.exe
+08-12-1999 00:00:00 151673 scmddoc.exe
+05-04-2001 00:00:00 167290 scmdflt.exe
+09-18-1993 00:00:00 40595 sec286.exe
+05-25-1994 00:00:00 29661 secdoc.exe
+09-18-1993 00:00:00 310609 secdos.exe
+05-26-2000 00:00:00 7039614 secexp64.01
+08-10-2000 00:00:00 5016153 secexp64.z
+11-15-1993 00:00:00 167904 seclog.exe
+09-18-1993 00:00:00 632669 secnns.exe
+09-18-1993 00:00:00 449590 secprn.exe
+09-18-1993 00:00:00 322007 secsys.exe
+05-26-2000 00:00:00 7351040 secus64.01
+08-10-2000 00:00:00 5457221 secus64.z
+09-18-1993 00:00:00 510733 secut1.exe
+09-18-1993 00:00:00 556873 secut2.exe
+09-18-1993 00:00:00 431691 secut3.exe
+08-29-2001 00:00:00 134525 servinst.exe
+05-25-1996 00:00:00 367009 setdoc.exe
+09-18-1993 00:00:00 24541 setfx.exe
+09-18-1993 00:00:00 56904 setupc.exe
+07-21-1997 00:00:00 75076 sftpt2.exe
+09-18-1993 00:00:00 67817 sftutl.exe
+09-02-1999 00:00:00 49345 showenv1.exe
+11-06-1997 00:00:00 25774 silent.exe
+04-23-2002 09:38:00 181878 slp107g.exe
+08-28-2001 00:00:00 184680 slpinsp3.exe
+09-18-1993 00:00:00 59254 smfsel.exe
+01-31-1997 00:00:00 2747104 smsup6.exe
+09-25-1996 00:00:00 131884 smt121.exe
+11-10-1993 00:00:00 105031 smt171.exe
+05-24-1996 00:00:00 1764462 smtos2.exe
+10-11-1996 00:00:00 322954 smtp1.exe
+05-19-1997 00:00:00 441783 smtp2.exe
+09-19-1997 00:00:00 2862615 smtp3.exe
+07-14-1998 00:00:00 2882529 smtp4.exe
+08-01-1995 00:00:00 53164 smtslp.exe
+06-04-1996 00:00:00 298148 sna31a.exe
+03-07-2002 10:28:00 148302 snmpfix.exe
+07-20-1995 00:00:00 147265 snupd2.exe
+07-20-1995 00:00:00 163195 snupdu.exe
+07-14-2000 00:00:00 12675957 sp1_ce.02
+04-25-2000 00:00:00 9547499 sp1_edir.02
+09-20-1999 00:00:00 230035 sp3to3a.exe
+02-25-1998 00:00:00 74372 spanish.exe
+05-23-1996 00:00:00 5323860 srapi.exe
+11-08-1996 00:00:00 38967 srout4.exe
+07-24-2000 00:00:00 812158 srvinst.exe
+08-23-1996 00:00:00 54912 srvmn1.exe
+06-30-1995 00:00:00 38078 stampd.exe
+02-21-2002 11:15:00 126042 strmft1.exe
+08-23-2000 00:00:00 250945 strtl8a.exe
+03-08-1999 00:00:00 36114 stufkey5.exe
+02-11-1998 00:00:00 52344 stylbr.exe
+04-14-1997 00:00:00 50098 stylct.exe
+02-11-1998 00:00:00 35645 styles.exe
+02-11-1998 00:00:00 37446 stylfr.exe
+04-14-1997 00:00:00 77671 stylha.exe
+02-12-1998 00:00:00 36626 stylit.exe
+04-16-1997 00:00:00 55674 stylsc.exe
+12-12-1995 00:00:00 37297 supwin.exe
+09-18-1993 00:00:00 186171 sys233.exe
+09-18-1993 00:00:00 159178 sys368.exe
+05-10-1995 00:00:00 161608 sys376.exe
+09-18-1993 00:00:00 61914 syschk.exe
+09-18-1993 00:00:00 81300 syslod.exe
+07-14-1997 00:00:00 418576 tabnd2a.exe
+01-13-1997 00:00:00 9831871 tambt1.exe
+05-04-1998 00:00:00 172843 tback3.exe
+09-01-1998 00:00:00 58235 tbox7.exe
+05-04-1998 00:00:00 174964 tcopy2.exe
+05-18-1998 00:00:00 781603 tcp312.exe
+08-01-2001 00:00:00 1223056 tcp542u.exe
+04-10-2002 08:49:00 1124221 tcp553v.exe
+05-24-2002 16:03:00 1221375 tcp590s.exe
+04-15-2002 10:50:00 315088 tcp604m.exe
+05-07-2002 11:27:00 1118361 tcp604s.exe
+02-09-1998 00:00:00 6902826 tel01a.exe
+01-21-1998 00:00:00 97084 tel40d.exe
+09-18-1993 00:00:00 33888 tim286.exe
+09-18-1993 00:00:00 20453 tim386.exe
+11-02-1998 00:00:00 105037 timefx.exe
+03-29-1994 00:00:00 31521 tokws.exe
+01-25-2001 00:00:00 123321 trpmon.exe
+09-18-1993 00:00:00 26100 trxnet.exe
+08-21-1996 00:00:00 88579 tsa410.exe
+06-25-2002 10:29:00 724997 tsa5up9.exe
+01-12-2000 00:00:00 127632 tsands.exe
+11-02-1999 00:00:00 20771 ttsy2k.exe
+09-22-1995 00:00:00 19933 ttyncs.exe
+08-03-1994 00:00:00 834048 tux001.tar
+08-03-1994 00:00:00 845824 tux002.tar
+08-03-1994 00:00:00 1034240 tux003.tar
+08-03-1994 00:00:00 2764800 tux004.tar
+08-03-1994 00:00:00 2836480 tux005.tar
+08-03-1994 00:00:00 1252352 tux006.tar
+08-03-1994 00:00:00 1355264 tux007.tar
+08-03-1994 00:00:00 1710080 tux008.tar
+08-03-1994 00:00:00 3502080 tux009.tar
+08-03-1994 00:00:00 3573760 tux010.tar
+08-04-1994 00:00:00 258236 tux011.exe
+08-04-1994 00:00:00 258250 tux012.exe
+08-04-1994 00:00:00 304451 tux013.exe
+08-04-1994 00:00:00 602748 tux014.exe
+08-04-1994 00:00:00 351070 tux015.exe
+08-04-1994 00:00:00 460026 tux016.exe
+09-18-1993 00:00:00 34077 ucpy.exe
+09-18-1993 00:00:00 103354 udf355.exe
+02-22-2002 12:49:00 6994 unixinf1.tgz
+05-08-2002 14:56:00 107260 unixins2.tgz
+09-18-1993 00:00:00 25508 unld.exe
+09-18-1993 00:00:00 30830 unps2.exe
+09-18-1993 00:00:00 34857 up215c.exe
+01-06-1994 00:00:00 509794 upd311.exe
+09-18-1993 00:00:00 24330 ups.exe
+09-18-1993 00:00:00 20837 ups22.exe
+09-18-1993 00:00:00 45537 upsm70.exe
+07-22-1997 00:00:00 43743 upsnlm.exe
+10-13-1998 00:00:00 28519 userhlp.exe
+09-18-1993 00:00:00 134247 ut1192.exe
+01-14-1998 00:00:00 1632088 uxp203.exe
+11-19-1998 00:00:00 1389072 uxp205.exe
+06-06-2001 00:00:00 1341347 uxp23j.exe
+11-02-1995 00:00:00 1098502 uxpsft.exe
+11-01-1995 00:00:00 58761 v2014.exe
+09-18-1993 00:00:00 40944 v286ol.exe
+06-08-2001 00:00:00 95133 v_nfs914.exe
+09-18-1993 00:00:00 34278 vapvol.exe
+09-18-1993 00:00:00 38035 vgetsc.exe
+09-18-1993 00:00:00 52323 volinf.exe
+05-03-2001 00:00:00 2444080 vpn35e.exe
+02-13-2002 14:50:00 3838701 vpn36d.exe
+02-13-2002 14:48:00 3837285 vpn36e.exe
+08-31-1999 00:00:00 96158 vpnbs01.exe
+09-18-1993 00:00:00 49835 vrepfa.exe
+09-18-1993 00:00:00 86326 vrp215.exe
+07-31-1997 00:00:00 59336 vrp386.exe
+07-31-1997 00:00:00 43438 vrpa286.exe
+09-18-1993 00:00:00 486274 vrpels.exe
+09-18-1993 00:00:00 103958 vrpps2.exe
+09-09-1999 00:00:00 699367 w2n213.exe
+09-25-2000 00:00:00 771404 w2ny2k.exe
+06-04-1996 00:00:00 240179 wan31a.exe
+06-16-1995 00:00:00 135592 wanx02.exe
+07-20-2001 00:00:00 79254744 was351.exe
+09-18-1993 00:00:00 28100 watch.exe
+04-23-2002 10:17:00 7884641 waview71.exe
+07-09-2001 00:00:00 182961 wbdav51.exe
+08-21-1996 00:00:00 53418 web002.exe
+03-01-2001 00:00:00 182219 webdv51.exe
+10-05-1999 00:00:00 2574191 weblsp1.exe
+06-22-1998 00:00:00 3589741 webser31.exe
+11-01-1995 00:00:00 27063 welcom.exe
+04-23-2001 00:00:00 1887450 winntwms.exe
+07-17-1997 00:00:00 28104 wkstrk.exe
+07-20-1995 00:00:00 52547 wpca31.exe
+07-20-1995 00:00:00 89314 wpfm31.exe
+09-11-1995 00:00:00 41008 wpmdm2.exe
+07-18-1995 00:00:00 36824 wpofus.exe
+07-20-1995 00:00:00 51398 wprp31.exe
+07-18-1995 00:00:00 21092 wpvwin.exe
+03-15-1994 00:00:00 52738 wrkdoc.exe
+05-29-1997 00:00:00 683395 ws250c.exe
+05-29-1997 00:00:00 765234 ws251c.exe
+05-09-1997 00:00:00 212586 ws3tk2b.exe
+03-07-2002 12:40:00 371 ws_ftp.log
+06-29-1999 00:00:00 1507075 wtmc1.exe
+06-16-1995 00:00:00 32697 x400fx.exe
+06-09-1999 00:00:00 660700 x400nlm1.exe
+08-05-1999 00:00:00 1134477 x400os21.exe
+01-30-2002 17:09:00 156483 xconss9f.exe
+09-18-1993 00:00:00 49801 xld386.exe
+07-27-2001 00:00:00 1043685 zd2dmi1.exe
+12-19-2001 00:00:00 365016 zd2dstfx.exe
+07-20-2001 00:00:00 338947 zd2scan.exe
+03-01-2002 09:27:00 24341430 zd322k1.exe
+03-01-2002 09:35:00 24350056 zd322k2.exe
+03-14-2002 18:03:00 95330 zd32dupw.exe
+03-01-2002 09:16:00 26945103 zd32nw.exe
+03-01-2002 09:21:00 26937023 zd32nw4.exe
+02-05-2002 12:18:00 26944994 zd32nw5.exe
+07-29-2001 00:00:00 24349972 zd32p2k1.exe
+07-29-2001 00:00:00 24349896 zd32p2k2.exe
+07-29-2001 00:00:00 26936865 zd32pnw4.exe
+07-29-2001 00:00:00 26944944 zd32pnw5.exe
+01-29-2002 14:50:00 128456 zd3awsr1.exe
+12-19-2001 00:00:00 1242985 zd3ccpp.exe
+12-19-2001 00:00:00 304923 zd3dac.exe
+02-22-2002 15:31:00 537680 zd3dupws.exe
+11-08-2001 00:00:00 142260 zd3dxsnp.exe
+12-04-2001 00:00:00 94250 zd3idnt1.exe
+01-02-2002 00:00:00 1443132 zd3ntmsi.exe
+12-20-2001 00:00:00 15512136 zd3o8i1.exe
+12-19-2001 00:00:00 15575094 zd3o8i2.exe
+05-24-2002 10:03:00 204858 zd3rosnp.exe
+01-09-2002 00:00:00 298505 zd3scn.exe
+12-18-2001 00:00:00 149726 zd3wm95.exe
+01-09-2002 00:00:00 180523 zd3wminv.exe
+12-18-2001 00:00:00 166988 zd3wmsch.exe
+12-19-2001 00:00:00 195447 zd3wsmg.exe
+03-19-2002 14:21:00 381437 zd3xwsrg.exe
+04-18-2002 15:53:00 125036 zd3xwuol.exe
+04-18-2002 16:30:00 180429 zd3xzisw.exe
+03-14-2002 10:01:00 226961 zd3zpol.exe
+05-01-2002 17:41:00 1274878 zenintg.exe
+05-09-2001 00:00:00 1865 zenstart.txt
+02-23-2001 00:00:00 2408726 zfd2pt3b.exe
+03-21-2000 00:00:00 62396652 zfd2sp1.exe
+05-22-2001 00:00:00 293221 zfd2tsfx.exe
+10-20-2000 00:00:00 97309 zfd3site.exe
+11-23-2001 00:00:00 46890033 zfd3sp1a.exe
+08-10-2000 00:00:00 31452136 zfn101.exe
+11-23-2001 00:00:00 1647316 zfs2jvm.exe
+12-18-2001 00:00:00 215046 zfs2pt1.exe
+12-20-2001 00:00:00 262640 zfs2sel.exe
+01-18-2002 14:59:00 54876346 zfs2sp1a.exe
+02-05-2001 00:00:00 1903657 zfsdbpb.exe
+10-11-2000 00:00:00 96356 zisclr.exe
+12-19-2001 00:00:00 94293 zs2dbbk.exe
+12-20-2001 00:00:00 141307 zs2ipg.exe
+12-19-2001 00:00:00 1173802 zs2mibs.exe
+01-23-2002 08:51:00 943931 zs2ndst1.exe
+06-04-2002 13:23:00 516401 zs2rbs.exe
+03-13-2002 11:41:00 1095584 zs2smtp.exe
+12-05-2001 00:00:00 981014 zs2util2.exe
+06-06-2002 11:14:00 92151 zs3sch.exe
+10-13-1998 00:00:00 1039314 zw100p1.exe
+11-06-1998 00:00:00 194420 zw101p1.exe
+11-22-1999 00:00:00 1065727 zw110p3.exe
diff --git a/netwerk/streamconv/converters/parse-ftp/U-no_ug.in b/netwerk/streamconv/converters/parse-ftp/U-no_ug.in
new file mode 100644
index 000000000..aedd9cff4
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-no_ug.in
@@ -0,0 +1,84 @@
+ftp> open casper.cs.uct.ac.za
+Connected to casper.cs.uct.ac.za.
+220 casper.cs.uct.ac.za FTP server (Version 6.00LS) ready.
+Name (ftp.cs.uct.ac.za:cyp):
+331 Guest login ok, send your email address as password.
+230- Welcome to
+230- __ _ _
+230- / _| |_ _ __ ___ ___ _ _ ___| |_ __ _ ___ ______ _
+230- | |_| __| '_ \ / __/ __|| | | |/ __| __| / _` |/ __| |_ / _` |
+230- | _| |_| |_) | (__\__ \| |_| | (__| |_ | (_| | (__ _ / / (_| |
+230- |_| \__| .__(_)___|___(_)__,_|\___|\__(_)__,_|\___(_)___\__,_|
+230- |_|
+230-
+230- Publicly available downloads can be found in /pub.
+230-
+230- Do not put anything in /incoming unless it is by prior arrangement.
+230- If we do not know what it is, it will be deleted.
+230-
+230- A complete listing of available files can be found in /pub/ls-lR.gz
+230- and /pub/ls-lR. This list is updated daily at 02:00 SAST.
+230-
+230- Contents of /pub:
+230- CVC/ - Collaborative Visual Computing Laboratory
+230- DB/ - Database Laboratory
+230- DNA/ - The Data Network Architectures Laboratory
+230- FreeBSD/ - The FreeBSD Operating System
+230- distfiles/ - ports source tarball's
+230- releases/ - self-made releases
+230- OpenBSD/ - The OpenBSD Operating System
+230- windows/ - Software for Microsoft Windows
+230- ssh/ - secure shell clients
+230-
+230- This FTP site is also searchable via archie,
+230- and the web: http://ftp.cs.uct.ac.za:8000/ftpsearch
+230-
+230- UCT/UNINET users should also peruse the following
+230- anonymous FTP servers for additional resources:
+230-
+230- ftp://ftp.leg.uct.ac.za/ [ http://www.leg.uct.ac.za/ ]
+230- ftp://ftp.adamastor.ac.za/ [ http://ftp.adamastor.ac.za/ ]
+230- ftp://cabbagewrath.its.uct.ac.za/ [ don't ask about the name ]
+230-
+230- --
+230- ftp-admin@cs.uct.ac.za
+230 Guest login ok, access restrictions apply.
+Remote system type is UNIX.
+Using binary mode to transfer files.
+ftp> syst
+215 UNIX Type: L8 Version: BSD-199506
+ftp> ls
+200 PORT command successful.
+150 Opening ASCII mode data connection for '/bin/ls'.
+total 1092
+drwxr-xr-x 2 0 0 512 May 28 22:17 etc
+drwx-wx-wt 2 0 0 512 Jul 1 02:15 incoming
+drwx--x--x 2 0 0 512 Jul 3 12:19 private
+drwxr-xr-x 9 0 0 512 Jul 11 01:02 pub
+drwxr-xr-x 2 0 5 512 May 28 22:24 CVC
+drwxr-xr-x 2 0 5 512 Jul 31 2000 DB
+drwxr-xr-x 5 0 5 512 May 28 22:24 DNA
+drwxr-xr-x 4 0 0 512 Jun 12 22:13 FreeBSD
+drwxr-xr-x 3 0 5 512 May 28 22:24 OpenBSD
+drwxr-xr-x 2 0 5 512 Jun 3 15:51 Solaris
+-rw-r--r-- 1 0 0 158918 Jul 11 01:02 ls-lR
+-rw-r--r-- 1 0 0 26569 Jul 11 01:02 ls-lR.gz
+drwxr-xr-x 3 0 5 512 May 28 22:24 windows
+lrwx------ 1 0 0 25 Jun 12 22:10 4.6-RELEASE -> releases/i386/4.6-RELEASE
+lrwx------ 1 0 0 24 Jun 12 22:13 ISO-IMAGES -> releases/i386/ISO-IMAGES
+-rw-r--r-- 1 0 5 157 May 28 22:27 README.TXT
+-rw-r--r-- 1 0 5 872048 Sep 23 2001 cvsup-16.1e.tgz
+lrwxr-xr-x 1 0 0 15 May 28 22:26 distfiles -> ports/distfiles
+lrwxr-xr-x 1 0 0 14 Jun 6 17:12 packages -> ports/packages
+drwxr-xr-x 5 0 0 512 Jun 23 18:47 ports
+drwxr-xr-x 3 0 0 512 May 28 22:27 releases
+-rw-r--r-- 1 0 0 1538 Mar 15 2001 ftpmotd
+ftp> cd incoming
+250 CWD command successful.
+ftp> ls
+200 PORT command successful.
+150 Opening ASCII mode data connection for '/bin/ls'.
+ftpd: .: Permission denied
+226 Transfer complete.
+ftp> close
+221 Goodbye.
diff --git a/netwerk/streamconv/converters/parse-ftp/U-no_ug.out b/netwerk/streamconv/converters/parse-ftp/U-no_ug.out
new file mode 100644
index 000000000..5200a9b0e
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-no_ug.out
@@ -0,0 +1,26 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+05-28-2002 22:17:00 <DIR> etc
+07-01-2002 02:15:00 <DIR> incoming
+07-03-2002 12:19:00 <DIR> private
+07-11-2002 01:02:00 <DIR> pub
+05-28-2002 22:24:00 <DIR> CVC
+07-31-2000 00:00:00 <DIR> DB
+05-28-2002 22:24:00 <DIR> DNA
+06-12-2002 22:13:00 <DIR> FreeBSD
+05-28-2002 22:24:00 <DIR> OpenBSD
+06-03-2002 15:51:00 <DIR> Solaris
+07-11-2002 01:02:00 158918 ls-lR
+07-11-2002 01:02:00 26569 ls-lR.gz
+05-28-2002 22:24:00 <DIR> windows
+06-12-2002 22:10:00 <JUNCTION> 4.6-RELEASE -> releases/i386/4.6-RELEASE
+06-12-2002 22:13:00 <JUNCTION> ISO-IMAGES -> releases/i386/ISO-IMAGES
+05-28-2002 22:27:00 157 README.TXT
+09-23-2001 00:00:00 872048 cvsup-16.1e.tgz
+05-28-2002 22:26:00 <JUNCTION> distfiles -> ports/distfiles
+06-06-2002 17:12:00 <JUNCTION> packages -> ports/packages
+06-23-2002 18:47:00 <DIR> ports
+05-28-2002 22:27:00 <DIR> releases
+03-15-2001 00:00:00 1538 ftpmotd
diff --git a/netwerk/streamconv/converters/parse-ftp/U-nogid.in b/netwerk/streamconv/converters/parse-ftp/U-nogid.in
new file mode 100644
index 000000000..15f77d1ee
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-nogid.in
@@ -0,0 +1,82 @@
+ftp> open export.lcs.mit.edu
+Connected to ftp.x.org.
+220-Welcome to the ftp.x.org server.
+220-
+220-This server is provided and supported by The Open Group.
+220-
+220 ftp.x.org FTP server (Version wu-2.6.2(2) Mon Dec 17 13:03:41 GMT 2001) ready.
+Name (export.lcs.mit.edu:cyp):
+331 Guest login ok, send your complete e-mail address as password.
+230-
+230-Welcome to ftp.x.org, the X11 anonymous FTP archive of X.Org.
+230-
+230-PLEASE NOTE THE INCOMING FACILITY IS PRESENTLY UNAVAILABLE
+230-
+230-All activity is logged with your host name and email address.
+230-
+230-REPORTING PROBLEMS - Please report all problems to xorg_info@x.org.
+230-
+230-LOGIN PROBLEMS - If your FTP client crashes or hangs shortly after
+230-login, try using a dash (-) as the first character of your password.
+230-This turns off the informational messages that may be confusing
+230-your ftp client.
+230-
+230-
+230-Please read the file README
+230- it was last modified on Tue Apr 24 15:33:13 2001 - 444 days ago
+230 User ftp logged in. Access restrictions apply.
+Remote system type is UNIX.
+Using binary mode to transfer files.
+ftp> ls
+200 PORT command successful.
+150 Opening ASCII mode data connection for /bin/ls.
+total 5106
+-rw-r--r-- 1 X.Org 91 May 7 2001 .banner
+---------- 1 X.Org 0 May 30 2000 .notar
+-rw-r--r-- 1 X.Org 885 May 27 1999 .welcome
+-rw-r--r-- 1 X.Org 61 Jul 20 2001 30_days_changes
+-rw-r--r-- 1 X.Org 61 Jul 20 2001 7_days_changes
+-rw-r--r-- 1 X.Org 1456 Jul 20 2001 90_days_changes
+-rw-r--r-- 1 X.Org 3075 Oct 7 1998 GettingBroadway
+-rw-r--r-- 1 X.Org 3075 Oct 7 1998 GettingR6.3
+-rw-r--r-- 1 X.Org 1847 Feb 1 1999 GettingR6.4
+-rw-r--r-- 1 X.Org 1378 Aug 24 2000 GettingR6.5.1
+-rw-r--r-- 1 X.Org 1229 Apr 24 2001 GettingR6.6
+-rw-r--r-- 1 X.Org 194 Mar 11 1997 MIRROR.README
+drwxr-xr-x 56 X.Org 22016 May 4 2001 R5contrib
+-r--r--r-- 1 X.Org 1314 Apr 24 2001 README
+-rw-r--r-- 2 X.Org 479 Nov 6 2001 banner2
+lrwxrwxrwx 1 X.Org 7 Aug 8 2001 bin -> usr/bin
+drwxr-xr-x 34 X.Org 1024 Nov 6 2001 contrib
+d--x--x--x 2 X.Org 512 Aug 8 2001 dev
+drwxr-xr-x 2 X.Org 512 Oct 12 1998 digest
+d--x--x--x 3 X.Org 512 Aug 8 2001 etc
+-rw-r--r-- 1 X.Org 2135632 Jul 20 2001 ls-lR
+-rw-r--r-- 1 X.Org 376221 May 8 2001 ls-lR.Z
+drwxr-xr-x 2 X.Org 512 Sep 29 1998 private
+drwxr-xr-x 17 X.Org 512 May 4 2001 pub
+drwxr-xr-x 2 X.Org 512 May 4 2001 rcsfaq
+d--x--x--x 5 X.Org 512 Aug 8 2001 usr
+-rw-r--r-- 2 X.Org 479 Nov 6 2001 welcome.msg
+drwxr-xr-x 2 X.Org 512 May 4 2001 10R3
+drwxr-xr-x 2 X.Org 512 May 4 2001 10R4
+-rw-r--r-- 1 X.Org 9740 Mar 2 1999 Contrib.howto
+drwxr-xr-x 9 X.Org 512 Jun 2 2001 DOCS
+drwxr-xr-x 2 X.Org 512 May 4 2001 R1
+drwxr-xr-x 2 X.Org 512 May 4 2001 R2
+drwxr-xr-x 2 X.Org 512 May 4 2001 R3
+drwxr-xr-x 7 X.Org 512 May 4 2001 R4
+drwxr-xr-x 4 X.Org 512 May 4 2001 R5
+drwxr-xr-x 4 X.Org 512 May 4 2001 R6
+drwxr-xr-x 5 X.Org 512 May 4 2001 R6.1
+drwxr-xr-x 6 X.Org 512 May 4 2001 R6.3
+drwxr-xr-x 8 X.Org 512 Aug 10 2001 R6.4
+drwxr-xr-x 7 X.Org 512 Aug 9 2001 R6.5.1
+drwxr-xr-x 8 X.Org 512 May 2 2001 R6.6
+drwxr-xr-x 10 X.Org 512 May 4 2001 unsupported
+226 Transfer complete.
+ftp> close
+221-You have transferred 0 bytes in 0 files.
+221-Total traffic for this session was 2686 bytes in 1 transfers.
+221-Thank you for using the FTP service on ftp.x.org.
+221 Goodbye.
diff --git a/netwerk/streamconv/converters/parse-ftp/U-nogid.out b/netwerk/streamconv/converters/parse-ftp/U-nogid.out
new file mode 100644
index 000000000..9a31407c8
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-nogid.out
@@ -0,0 +1,47 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+05-07-2001 00:00:00 91 .banner
+05-30-2000 00:00:00 0 .notar
+05-27-1999 00:00:00 885 .welcome
+07-20-2001 00:00:00 61 30_days_changes
+07-20-2001 00:00:00 61 7_days_changes
+07-20-2001 00:00:00 1456 90_days_changes
+10-07-1998 00:00:00 3075 GettingBroadway
+10-07-1998 00:00:00 3075 GettingR6.3
+02-01-1999 00:00:00 1847 GettingR6.4
+08-24-2000 00:00:00 1378 GettingR6.5.1
+04-24-2001 00:00:00 1229 GettingR6.6
+03-11-1997 00:00:00 194 MIRROR.README
+05-04-2001 00:00:00 <DIR> R5contrib
+04-24-2001 00:00:00 1314 README
+11-06-2001 00:00:00 479 banner2
+08-08-2001 00:00:00 <JUNCTION> bin -> usr/bin
+11-06-2001 00:00:00 <DIR> contrib
+08-08-2001 00:00:00 <DIR> dev
+10-12-1998 00:00:00 <DIR> digest
+08-08-2001 00:00:00 <DIR> etc
+07-20-2001 00:00:00 2135632 ls-lR
+05-08-2001 00:00:00 376221 ls-lR.Z
+09-29-1998 00:00:00 <DIR> private
+05-04-2001 00:00:00 <DIR> pub
+05-04-2001 00:00:00 <DIR> rcsfaq
+08-08-2001 00:00:00 <DIR> usr
+11-06-2001 00:00:00 479 welcome.msg
+05-04-2001 00:00:00 <DIR> 10R3
+05-04-2001 00:00:00 <DIR> 10R4
+03-02-1999 00:00:00 9740 Contrib.howto
+06-02-2001 00:00:00 <DIR> DOCS
+05-04-2001 00:00:00 <DIR> R1
+05-04-2001 00:00:00 <DIR> R2
+05-04-2001 00:00:00 <DIR> R3
+05-04-2001 00:00:00 <DIR> R4
+05-04-2001 00:00:00 <DIR> R5
+05-04-2001 00:00:00 <DIR> R6
+05-04-2001 00:00:00 <DIR> R6.1
+05-04-2001 00:00:00 <DIR> R6.3
+08-10-2001 00:00:00 <DIR> R6.4
+08-09-2001 00:00:00 <DIR> R6.5.1
+05-02-2001 00:00:00 <DIR> R6.6
+05-04-2001 00:00:00 <DIR> unsupported
diff --git a/netwerk/streamconv/converters/parse-ftp/U-proftpd.in b/netwerk/streamconv/converters/parse-ftp/U-proftpd.in
new file mode 100644
index 000000000..0f8aa138d
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-proftpd.in
@@ -0,0 +1,21 @@
+ftp> open ftp.netmanage.com
+Connected to ftp.netmanage.com.
+220 ProFTPD 1.2.4 Server (Netmanage FTP Server) [156.27.8.3]
+Name (ftp.netmanage.com:cyp):
+331 Anonymous login ok, send your complete email address as your password.
+230 Anonymous access granted, restrictions apply.
+Remote system type is UNIX.
+Using binary mode to transfer files.
+ftp> ls
+200 PORT command successful.
+150 Opening ASCII mode data connection for file list.
+drwxr-xr-x 13 ftp ftp 344 Oct 17 2001 pub
+drwxrwxr-x 7 ftp support 304 May 14 16:56 support
+-rw-r--r-- 1 ftp ftp 508 Aug 19 1998 welcome.msg
+226-Transfer complete.
+226 Quotas off
+ftp> syst
+215 UNIX Type: L8
+ftp> close
+221 Goodbye.
+ftp> \ No newline at end of file
diff --git a/netwerk/streamconv/converters/parse-ftp/U-proftpd.out b/netwerk/streamconv/converters/parse-ftp/U-proftpd.out
new file mode 100644
index 000000000..02d7a1843
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-proftpd.out
@@ -0,0 +1,7 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+10-17-2001 00:00:00 <DIR> pub
+05-14-2002 16:56:00 <DIR> support
+08-19-1998 00:00:00 508 welcome.msg
diff --git a/netwerk/streamconv/converters/parse-ftp/U-wu.in b/netwerk/streamconv/converters/parse-ftp/U-wu.in
new file mode 100644
index 000000000..e4a822a09
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-wu.in
@@ -0,0 +1,71 @@
+ftp> open sunsite.unc.edu
+Connected to sunsite.unc.edu.
+220 divahouse.metalab.unc.edu FTP server (Version wu-2.6.1(4) Thu Nov 29 23:05:07 EST 2001) ready.
+Name (sunsite.unc.edu:cyp):
+331 Guest login ok, send your complete e-mail address as password.
+230-
+230- Welcome to ibiblio.org's FTP archives!
+230- formerly known as MetaLab.unc.edu
+230-
+230-
+230-For more information about services offered by ibiblio.org,
+230-browse to http://ibiblio.org/faq
+230-
+230-You can access this archive via HTTP with the same URL.
+230-
+230-example: ftp://ibiblio.org/pub/Linux/ becomes
+230- http://ibiblio.org/pub/Linux/, but we prefer you use FTP.
+230-
+230-You can get tarred directories if you issue a "get dirname.tar"
+230-You can also get gzipped or compressed tarred directories by following
+230-the .tar with .gz or .Z, respectively. Please don't issue either of
+230-these commands to get Linux distributions. They are already compressed,
+230-so this only generates unnecessary CPU overhead for us.
+230-
+230-************************************************************************
+230-
+230-Please use LSM documentation when submitting to the linux archive.
+230-Anything submitted without an LSM will be rejected! You'll get an
+230-email form letter about it if we can figure out who you are.
+230-
+230-To learn more about submitting an LSM,
+230-see: http://www.ibiblio.org/pub/Linux/howtosubmit.html
+230-or ftp://www.ibiblio.org/pub/Linux/HOW.TO.SUBMIT
+230-
+230-***********************************************************************
+230-
+230-If you mirror a site on ibiblio, please subscribe to our mirror list:
+230-http://lists.ibiblio.org/mailman/listinfo/ibiblio-mirrors
+230-
+230-Have suggestions or questions? Please mail ftpkeeper@ibiblio.org.
+230-
+230-
+230-Please read the file README
+230- it was last modified on Tue Feb 19 09:46:53 2002 - 140 days ago
+230 Guest login ok, access restrictions apply.
+Remote system type is UNIX.
+Using binary mode to transfer files.
+ftp> syst
+215 UNIX Type: L8
+ftp> ls
+200 PORT command successful.
+150 Opening ASCII mode data connection for /bin/ls.
+total 78744
+-r--r--r-- 1 root other 80507411 Jul 9 06:09 IAFA-LISTINGS
+-rw-r--r-- 1 root root 1393 Feb 19 14:46 README
+dr-xr-xr-x 2 root other 4096 Mar 27 2001 bin
+dr-xr-xr-x 2 root other 4096 Jul 16 1997 dev
+dr-xr-xr-x 2 root other 4096 May 30 14:35 etc
+drwxrwxrwx 18 ftp 20 4096 Jun 10 13:05 incoming
+drwxr-xr-x 2 root root 4096 Mar 27 2001 lib
+lrwxrwxrwx 1 root other 13 Mar 16 2001 ls-lR -> IAFA-LISTINGS
+dr-xr-xr-x 18 root root 4096 May 31 19:46 pub
+dr-xr-xr-x 3 root other 4096 Jun 26 2000 unc
+dr-xr-xr-x 5 root other 4096 Jul 16 1997 usr
+226 Transfer complete.
+ftp> close
+221-You have transferred 0 bytes in 0 files.
+221-Total traffic for this session was 2777 bytes in 1 transfers.
+221-Thank you for using the FTP service on divahouse.metalab.unc.edu.
+221 Goodbye.
+ftp> \ No newline at end of file
diff --git a/netwerk/streamconv/converters/parse-ftp/U-wu.out b/netwerk/streamconv/converters/parse-ftp/U-wu.out
new file mode 100644
index 000000000..1ffbf23eb
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/U-wu.out
@@ -0,0 +1,15 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+07-09-2002 06:09:00 80507411 IAFA-LISTINGS
+02-19-2002 14:46:00 1393 README
+03-27-2001 00:00:00 <DIR> bin
+07-16-1997 00:00:00 <DIR> dev
+05-30-2002 14:35:00 <DIR> etc
+06-10-2002 13:05:00 <DIR> incoming
+03-27-2001 00:00:00 <DIR> lib
+03-16-2001 00:00:00 <JUNCTION> ls-lR -> IAFA-LISTINGS
+05-31-2002 19:46:00 <DIR> pub
+06-26-2000 00:00:00 <DIR> unc
+07-16-1997 00:00:00 <DIR> usr
diff --git a/netwerk/streamconv/converters/parse-ftp/V-MultiNet.in b/netwerk/streamconv/converters/parse-ftp/V-MultiNet.in
new file mode 100644
index 000000000..04e66774e
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/V-MultiNet.in
@@ -0,0 +1,34 @@
+Connected to acavax.lynchburg.edu.
+220 acavax.lynchburg.edu MultiNet FTP Server Process V4.0(15) at Mon 1-Jul-02 10:51AM-EDT
+Name (acavax.lynchburg.edu:cyp): 331 anonymous user ok. Send real ident as password.
+230-Guest User FOO@BAR.COM logged into ACA:[ANONYMOUS] at Mon 1-Jul-02 10:51AM-EDT, job 2b69.
+230 Access restrictions apply
+Remote system type is VMS.
+ftp> passive
+Passive mode on.
+ftp> pwd
+257 "ACA:[ANONYMOUS]" is current directory.
+ftp> ls
+227 Entering passive mode; use PORT 161,115,147,1,10,31
+150 List started.
+
+ACA:[ANONYMOUS]
+
+AUTOEXEC.BAT;1 %RMS-E-PRV, insufficient privilege or file protection violation
+BOURNE.DIR;1 1 28-OCT-1994 10:05 [ANONYMOUS] (RWE,RWE,RE,RWE)
+FTP_SERVER.LOG;8171 0 1-JUL-2002 10:51 [ANONYMOUS] (RWED,RWED,,)
+LOGIN.COM;2 1 4-NOV-1994 14:09 [ANONYMOUS] (RWE,RWE,,)
+NICELY.DIR;1 1 14-NOV-1994 14:17 [501,120] (RWED,RWED,RE,RE)
+NWLINK.386;1 66 7-AUG-1995 14:32 [ANONYMOUS] (RWED,RWED,,RE)
+PUB.DIR;1 1 27-JAN-1994 14:46 [ANONYMOUS] (RWE,RWE,RE,RWE)
+README.FTP;1 %RMS-E-PRV, insufficient privilege or file protection violation
+ROUSSOS.DIR;1 1 27-JAN-1994 14:48 [CS,ROUSSOS] (RWE,RWE,RE,R)
+S67-50903.JPG;1 328 22-SEP-1998 16:19 [ANONYMOUS] (RWED,RWED,,)
+S71-43543.JPG;1 310 22-SEP-1998 16:20 [ANONYMOUS] (RWED,RWED,,)
+TEAGUE.DIR;1 1 1-JUL-1995 12:23 [ANONYMOUS] (RWE,RWE,RE,RE)
+
+
+Total of 710 blocks in 12 files.
+226 Transfer completed.
+ftp> quit
+221 QUIT command received. Goodbye.
diff --git a/netwerk/streamconv/converters/parse-ftp/V-MultiNet.out b/netwerk/streamconv/converters/parse-ftp/V-MultiNet.out
new file mode 100644
index 000000000..a6cddd619
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/V-MultiNet.out
@@ -0,0 +1,14 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+10-28-1994 10:05:00 <DIR> BOURNE
+07-01-2002 10:51:00 0 FTP_SERVER.LOG
+11-04-1994 14:09:00 512 LOGIN.COM
+11-14-1994 14:17:00 <DIR> NICELY
+08-07-1995 14:32:00 33792 NWLINK.386
+01-27-1994 14:46:00 <DIR> PUB
+01-27-1994 14:48:00 <DIR> ROUSSOS
+09-22-1998 16:19:00 167936 S67-50903.JPG
+09-22-1998 16:20:00 158720 S71-43543.JPG
+07-01-1995 12:23:00 <DIR> TEAGUE
diff --git a/netwerk/streamconv/converters/parse-ftp/V-VMS-mix.in b/netwerk/streamconv/converters/parse-ftp/V-VMS-mix.in
new file mode 100644
index 000000000..07ebd7bba
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/V-VMS-mix.in
@@ -0,0 +1,22 @@
+This is a composite of 'difficult' VMS (MultiNet/UCX/CMU) LIST lines.
+CAUTION WHILE EDITING - lines may have dangling CRs! (intentional)
+
+
+Directory DISK$VOL:[DIR1.DIR2]
+DISK$VOL:
+ACA:[ANONYMOUS]
+
+AUTOEXEC.BAT;1 %RMS-E-PRV, insufficient privilege or file protection violation
+README.FTP;1 insufficient privilege or file protection violation
+LOGIN.COM;2 1 4-NOV-1994 14:09 [ANONYMOUS] (RWE,RWE,,)
+CII-MANUAL.TEX;1 213/216 29-JAN-1996 03:33:12 [ANONYMOU,ANONYMOUS] (RWED,RWED,,)
+THIS-IS-A-LONG-VMS-FILENAME.WITH-CR-TO-NEXT-LINE 213/216 29-JAN-1996 03:33:12 [ANONYMOU,ANONYMOUS] (RWED,RWED,,)
+ANOTHER-LONG-VMS-FILENAME.WITH-LF-TO-NEXT-LINE
+ 213 29-JAN-1996 03:33 [ANONYMOU,ANONYMOUS] (RWED,RWED,,)
+[A.DIR]CMU-VMS-IP-FTP-FILE;1 1/3 5-MAR-1993 18:09
+MAX_FILESIZE.FILE;1 2199023255040/4294967295 5-MAR-1993 18:09
+
+Total of 710 blocks in 12 files.
+226 Transfer completed.
+ftp> quit
+221 QUIT command received. Goodbye.
diff --git a/netwerk/streamconv/converters/parse-ftp/V-VMS-mix.out b/netwerk/streamconv/converters/parse-ftp/V-VMS-mix.out
new file mode 100644
index 000000000..2a5a704c2
--- /dev/null
+++ b/netwerk/streamconv/converters/parse-ftp/V-VMS-mix.out
@@ -0,0 +1,10 @@
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+11-04-1994 14:09:00 LOGIN.COM
+01-29-1996 03:33:12 CII-MANUAL.TEX
+01-29-1996 03:33:12 THIS-IS-A-LONG-VMS-FILENAME.WITH-CR-TO-NEXT-LINE
+01-29-1996 03:33:00 ANOTHER-LONG-VMS-FILENAME.WITH-LF-TO-NEXT-LINE
+03-05-1993 18:09:00 CMU-VMS-IP-FTP-FILE
+03-05-1993 18:09:00 2199023255040 MAX_FILESIZE.FILE
diff --git a/netwerk/streamconv/moz.build b/netwerk/streamconv/moz.build
new file mode 100644
index 000000000..6b02ef5a7
--- /dev/null
+++ b/netwerk/streamconv/moz.build
@@ -0,0 +1,25 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DIRS += ['converters']
+TEST_DIRS += ['test']
+
+XPIDL_SOURCES += [
+ 'mozITXTToHTMLConv.idl',
+ 'nsIDirIndex.idl',
+ 'nsIDirIndexListener.idl',
+ 'nsIStreamConverter.idl',
+ 'nsIStreamConverterService.idl',
+ 'nsITXTToHTMLConv.idl',
+]
+
+SOURCES += [
+ 'nsStreamConverterService.cpp',
+]
+
+XPIDL_MODULE = 'necko_strconv'
+
+FINAL_LIBRARY = 'xul'
diff --git a/netwerk/streamconv/mozITXTToHTMLConv.idl b/netwerk/streamconv/mozITXTToHTMLConv.idl
new file mode 100644
index 000000000..e8bfb4cb4
--- /dev/null
+++ b/netwerk/streamconv/mozITXTToHTMLConv.idl
@@ -0,0 +1,88 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ Description: Currently only functions to enhance plain text with HTML tags.
+ <p>
+ Wrapper class for various parsing routines, that convert plain text to HTML.
+ They try to recognize cites, URLs, plain text formattting like *bold* etc.
+ See <http://www.bucksch.org/1/projects/mozilla/16507/> for a description.
+ */
+
+#include "nsIStreamConverter.idl"
+
+%{C++
+// {77c0e42a-1dd2-11b2-8ebf-edc6606f2f4b}
+#define MOZITXTTOHTMLCONV_CID \
+ { 0x77c0e42a, 0x1dd2, 0x11b2, \
+ { 0x8e, 0xbf, 0xed, 0xc6, 0x60, 0x6f, 0x2f, 0x4b } }
+
+#define MOZ_TXTTOHTMLCONV_CONTRACTID \
+ "@mozilla.org/txttohtmlconv;1"
+
+%}
+
+[scriptable, uuid(77c0e42a-1dd2-11b2-8ebf-edc6606f2f4b)]
+interface mozITXTToHTMLConv : nsIStreamConverter {
+ const unsigned long kEntities = 0; // just convert < & > to &lt; &amp; and &gt;
+ const unsigned long kURLs = 1 << 1;
+ const unsigned long kGlyphSubstitution = 1 << 2; // Smilies, &reg; etc.
+ const unsigned long kStructPhrase = 1 << 3; // E.g. *bold* -> <strong>
+
+/**
+ @param text: plain text to scan. May be a line, paragraph (recommended)
+ or just a substring.<p>
+ Must be non-escaped, pure unicode.<p>
+ <em>Note:</em> ScanTXT(a, o) + ScanTXT(b, o) may be !=
+ Scan(a + b, o)
+ @param whattodo: Bitfield describing the modes of operation
+ @result "<", ">" and "&" are escaped and HTML tags are inserted where
+ appropriate.
+ */
+ wstring scanTXT(in wstring text, in unsigned long whattodo);
+
+/**
+ Adds additional formatting to user edited text, that the user was too lazy
+ or "unknowledged" (DELETEME: is that a word?) to make.
+ <p>
+ <em>Note:</em> Don't use kGlyphSubstitution with this function. This option
+ generates tags, that are unuseable for UAs other than Mozilla. This would
+ be a data loss bug.
+
+ @param text: HTML source to scan. May be a line, paragraph (recommended)
+ or just a substring.<p>
+ Must be correct HTML. "<", ">" and "&" must be escaped,
+ other chars must be pure unicode.<p>
+ <em>Note:</em> ScanTXT(a, o) + ScanTXT(b, o) may be !=
+ Scan(a + b, o)
+ @param whattodo: Bitfield describing the modes of operation
+ @result Additional HTML tags are inserted where appropriate.
+ */
+ wstring scanHTML(in wstring text, in unsigned long whattodo);
+
+/**
+ @param line: line in original msg, possibly starting starting with
+ txt quote tags like ">"
+ @param logLineStart: pos in line, where the real content (logical line)
+ begins, i.e. pos after all txt quote tags.
+ E.g. position of "t" in "> > text".
+ Initial value must be 0, unless line is not real line.
+ @return Cite Level, i.e. number of txt quote tags found, i.e. number of
+ nested quotes.
+ */
+ unsigned long citeLevelTXT(in wstring line,
+ out unsigned long logLineStart);
+
+/**
+ @param a wide string to scan for the presence of a URL.
+ @param aLength --> the length of the buffer to be scanned
+ @param aPos --> the position in the buffer to start scanning for a url
+
+ aStartPos --> index into the start of a url (-1 if no url found)
+ aEndPos --> index of the last character in the url (-1 if no url found)
+ */
+
+ void findURLInPlaintext(in wstring text, in long aLength, in long aPos, out long aStartPos, out long aEndPos);
+};
diff --git a/netwerk/streamconv/nsIDirIndex.idl b/netwerk/streamconv/nsIDirIndex.idl
new file mode 100644
index 000000000..2b8d27770
--- /dev/null
+++ b/netwerk/streamconv/nsIDirIndex.idl
@@ -0,0 +1,82 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+/** A class holding information about a directory index.
+ * These have no reference back to their original source -
+ * changing these attributes won't affect the directory
+ */
+[scriptable, uuid(23bbabd0-1dd2-11b2-86b7-aad68ae7d7e0)]
+interface nsIDirIndex : nsISupports
+{
+ /**
+ * Entry's type is unknown
+ */
+ const unsigned long TYPE_UNKNOWN = 0;
+
+ /**
+ * Entry is a directory
+ */
+ const unsigned long TYPE_DIRECTORY = 1;
+
+ /**
+ * Entry is a file
+ */
+ const unsigned long TYPE_FILE = 2;
+
+ /**
+ * Entry is a symlink
+ */
+ const unsigned long TYPE_SYMLINK = 3;
+
+ /**
+ * The type of the entry - one of the constants above
+ */
+ attribute unsigned long type;
+
+ /**
+ * The content type - may be null if it is unknown.
+ * Unspecified for directories
+ */
+ attribute string contentType;
+
+ /**
+ * The fully qualified filename, expressed as a uri
+ *
+ * This is encoded with the encoding specified in
+ * the nsIDirIndexParser, and is also escaped.
+ */
+ attribute string location;
+
+ /**
+ * A description for the filename, which should be
+ * displayed by a viewer
+ */
+ attribute wstring description;
+
+ /**
+ * File size, with -1 meaning "unknown"
+ */
+ attribute long long size;
+
+ /**
+ * Last-modified time in seconds-since-epoch.
+ * -1 means unknown - this is valid, because there were no
+ * ftp servers in 1969
+ */
+ attribute PRTime lastModified;
+};
+
+%{C++
+
+#define NS_DIRINDEX_CID \
+/* { f6913e2e-1dd1-11b2-84be-f455dee342af } */ \
+{ 0xf6913e2e, \
+ 0x1dd1, \
+ 0x11b2, \
+ { 0x84, 0xbe, 0xf4, 0x55, 0xde, 0xe3, 0x42, 0xaf } \
+}
+%}
diff --git a/netwerk/streamconv/nsIDirIndexListener.idl b/netwerk/streamconv/nsIDirIndexListener.idl
new file mode 100644
index 000000000..a32aacabf
--- /dev/null
+++ b/netwerk/streamconv/nsIDirIndexListener.idl
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIStreamListener.idl"
+
+interface nsIDirIndex;
+
+/**
+ * This interface is used to receive contents of directory index listings
+ * from a protocol. They can then be transformed into an output format
+ * (such as rdf, html, etc)
+ */
+[scriptable, uuid(fae4e9a8-1dd1-11b2-b53c-8f3aa1bbf8f5)]
+interface nsIDirIndexListener : nsISupports {
+ /**
+ * Called for each directory entry
+ *
+ * @param request - the request
+ * @param ctxt - opaque parameter
+ * @param index - new index to add
+ */
+ void onIndexAvailable(in nsIRequest aRequest,
+ in nsISupports aCtxt,
+ in nsIDirIndex aIndex);
+
+ /**
+ * Called for each information line
+ *
+ * @param request - the request
+ * @param ctxt - opaque parameter
+ * @param info - new info to add
+ */
+ void onInformationAvailable(in nsIRequest aRequest,
+ in nsISupports aCtxt,
+ in AString aInfo);
+
+};
+
+%{C++
+#define NS_IDIRINDEXLISTENER_KEY "@mozilla.org/dirIndexListener;1"
+%}
+
+/**
+ * A parser for application/http-index-format
+ */
+[scriptable, uuid(38e3066c-1dd2-11b2-9b59-8be515c1ee3f)]
+interface nsIDirIndexParser : nsIStreamListener {
+ /**
+ * The interface to use as a callback for new entries
+ */
+ attribute nsIDirIndexListener listener;
+
+ /**
+ * The comment given, if any
+ * This result is only valid _after_ OnStopRequest has occurred,
+ * because it can occur anywhere in the datastream
+ */
+ readonly attribute string comment;
+
+ /**
+ * The encoding to use
+ */
+ attribute string encoding;
+};
+
+%{C++
+#define NS_DIRINDEXPARSER_CID \
+{ /* a0d6ad32-1dd1-11b2-aa55-a40187b54036 */ \
+ 0xa0d6ad32, \
+ 0x1dd1, \
+ 0x11b2, \
+ { 0xaa, 0x55, 0xa4, 0x01, 0x87, 0xb5, 0x40, 0x36 } \
+}
+
+#define NS_DIRINDEXPARSER_CONTRACTID "@mozilla.org/dirIndexParser;1"
+
+%}
diff --git a/netwerk/streamconv/nsIStreamConverter.idl b/netwerk/streamconv/nsIStreamConverter.idl
new file mode 100644
index 000000000..81cfab884
--- /dev/null
+++ b/netwerk/streamconv/nsIStreamConverter.idl
@@ -0,0 +1,100 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIStreamListener.idl"
+
+interface nsIInputStream;
+
+/**
+ * nsIStreamConverter provides an interface to implement when you have code
+ * that converts data from one type to another.
+ *
+ * Suppose you had code that converted plain text into HTML. You could implement
+ * this interface to allow everyone else to use your conversion logic using a
+ * standard api.
+ * <p>
+ * <b>STREAM CONVERTER USERS</b>
+ *
+ * There are currently two ways to use a stream converter:
+ * <ol>
+ * <li> <b>SYNCHRONOUS</b> Stream to Stream
+ * You can supply the service with a stream of type X
+ * and it will convert it to your desired output type and return
+ * a converted (blocking) stream to you.</li>
+ *
+ * <li> <b>ASYNCHRONOUS</b> nsIStreamListener to nsIStreamListener
+ * You can supply data directly to the converter by calling it's
+ * nsIStreamListener::OnDataAvailable() method. It will then
+ * convert that data from type X to your desired output type and
+ * return converted data to you via the nsIStreamListener you passed
+ * in by calling its OnDataAvailable() method.</li>
+ * </ol>
+ * <p>
+ *
+ * <b>STREAM CONVERTER SUPPLIERS</b>
+ *
+ * Registering a stream converter:
+ * Stream converter registration is a two step process. First of all the stream
+ * converter implementation must register itself with the component manager using
+ * a contractid in the format below. Second, the stream converter must add the contractid
+ * to the registry.
+ *
+ * Stream converter contractid format (the stream converter root key is defined in this
+ * file):
+ *
+ * <pre>@mozilla.org/streamconv;1?from=FROM_MIME_TYPE&to=TO_MIME_TYPE</pre>
+ *
+ * @author Jud Valeski
+ * @see nsIStreamConverterService
+ */
+
+[scriptable, uuid(0b6e2c69-5cf5-48b0-9dfd-c95950e2cc7b)]
+interface nsIStreamConverter : nsIStreamListener {
+
+ /**
+ * <b>SYNCRONOUS VERSION</b>
+ * Converts a stream of one type, to a stream of another type.
+ *
+ * Use this method when you have a stream you want to convert.
+ *
+ * @param aFromStream The stream representing the original/raw data.
+ * @param aFromType The MIME type of aFromStream.
+ * @param aToType The MIME type of the returned stream.
+ * @param aCtxt Either an opaque context, or a converter specific context
+ * (implementation specific).
+ * @return The converted stream. NOTE: The returned stream may not
+ * already be converted. An efficient stream converter
+ * implementation will converter data on demand rather than
+ * buffering the converted data until it is used.
+ */
+ nsIInputStream convert(in nsIInputStream aFromStream,
+ in string aFromType,
+ in string aToType,
+ in nsISupports aCtxt);
+
+ /**
+ * <b>ASYNCRONOUS VERSION</b>
+ * Converts data arriving via the converter's nsIStreamListener::OnDataAvailable()
+ * method from one type to another, pushing the converted data out to the caller
+ * via aListener::OnDataAvailable().
+ *
+ * Use this method when you want to proxy (and convert) nsIStreamListener callbacks
+ * asynchronously.
+ *
+ * @param aFromType The MIME type of the original/raw data.
+ * @param aToType The MIME type of the converted data.
+ * @param aListener The listener who receives the converted data.
+ * @param aCtxt Either an opaque context, or a converter specific context
+ * (implementation specific).
+ */
+ void asyncConvertData(in string aFromType,
+ in string aToType,
+ in nsIStreamListener aListener,
+ in nsISupports aCtxt);
+};
+
+%{C++
+#define NS_ISTREAMCONVERTER_KEY "@mozilla.org/streamconv;1"
+%}
diff --git a/netwerk/streamconv/nsIStreamConverterService.idl b/netwerk/streamconv/nsIStreamConverterService.idl
new file mode 100644
index 000000000..4884edf28
--- /dev/null
+++ b/netwerk/streamconv/nsIStreamConverterService.idl
@@ -0,0 +1,80 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+interface nsIInputStream;
+interface nsIStreamListener;
+
+%{C++
+#define NS_ISTREAMCONVERTER_KEY "@mozilla.org/streamconv;1"
+%}
+
+/**
+ * The nsIStreamConverterService is a higher level stream converter factory
+ * responsible for locating and creating stream converters
+ * (nsIStreamConverter).
+ *
+ * This service retrieves an interface that can convert data from a particular
+ * MIME type, to a particular MIME type. It is responsible for any intermediary
+ * conversion required in order to get from X to Z, assuming direct conversion
+ * is not possible.
+ *
+ * @author Jud Valeski
+ * @see nsIStreamConverter
+ */
+[scriptable, uuid(f2b1ab53-f0bd-4adb-9365-e59b1701a258)]
+interface nsIStreamConverterService : nsISupports {
+ /**
+ * Tests whether conversion between the two specified types is possible.
+ * This is cheaper than calling convert()/asyncConvertData(); it is not
+ * necessary to call this function before calling one of those, though.
+ */
+ boolean canConvert(in string aFromType, in string aToType);
+
+ /**
+ * <b>SYNCHRONOUS VERSION</b>
+ * Converts a stream of one type, to a stream of another type.
+ *
+ * Use this method when you have a stream you want to convert.
+ *
+ * @param aFromStream The stream representing the original/raw data.
+ * @param aFromType The MIME type of aFromStream.
+ * @param aToType The MIME type of the returned stream.
+ * @param aContext Either an opaque context, or a converter specific
+ * context (implementation specific).
+ * @return The converted stream. NOTE: The returned stream
+ * may not already be converted. An efficient stream
+ * converter implementation will convert data on
+ * demand rather than buffering the converted data
+ * until it is used.
+ */
+ nsIInputStream convert(in nsIInputStream aFromStream,
+ in string aFromType,
+ in string aToType,
+ in nsISupports aContext);
+
+ /**
+ * <b>ASYNCHRONOUS VERSION</b>
+ * Retrieves a nsIStreamListener that receives the original/raw data via its
+ * nsIStreamListener::OnDataAvailable() callback, then converts and pushes
+ * the data to aListener.
+ *
+ * Use this method when you want to proxy (and convert) nsIStreamListener
+ * callbacks asynchronously.
+ *
+ * @param aFromType The MIME type of the original/raw data.
+ * @param aToType The MIME type of the converted data.
+ * @param aListener The listener that receives the converted data.
+ * @param aCtxt Either an opaque context, or a converter specific
+ * context (implementation specific).
+ * @return A nsIStreamListener that receives data via its
+ * OnDataAvailable() method.
+ */
+ nsIStreamListener asyncConvertData(in string aFromType,
+ in string aToType,
+ in nsIStreamListener aListener,
+ in nsISupports aContext);
+};
diff --git a/netwerk/streamconv/nsITXTToHTMLConv.idl b/netwerk/streamconv/nsITXTToHTMLConv.idl
new file mode 100644
index 000000000..bfe841834
--- /dev/null
+++ b/netwerk/streamconv/nsITXTToHTMLConv.idl
@@ -0,0 +1,25 @@
+/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIStreamConverter.idl"
+
+[scriptable, uuid(933355f6-1dd2-11b2-a9b0-d335b9e35983)]
+interface nsITXTToHTMLConv : nsIStreamConverter {
+ /**
+ * @param text: Title to set for the HTML document. Only applicable if
+ * preFormatHTML(true) is called.
+ * @result The given title will be used to form an HTML document
+ * from the plain text document.
+ */
+ void setTitle(in wstring text);
+
+ /**
+ * @param value: true to use an HTML header and footer on the document,
+ * false to omit it.
+ * @result The document will use a header and footer if value is
+ * true.
+ */
+ void preFormatHTML(in boolean value);
+};
diff --git a/netwerk/streamconv/nsStreamConverterService.cpp b/netwerk/streamconv/nsStreamConverterService.cpp
new file mode 100644
index 000000000..8473461f5
--- /dev/null
+++ b/netwerk/streamconv/nsStreamConverterService.cpp
@@ -0,0 +1,558 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * This Original Code has been modified by IBM Corporation.
+ * Modifications made by IBM described herein are
+ * Copyright (c) International Business Machines
+ * Corporation, 2000
+ *
+ * Modifications to Mozilla code or documentation
+ * identified per MPL Section 3.3
+ *
+ * Date Modified by Description of modification
+ * 03/27/2000 IBM Corp. Added PR_CALLBACK for Optlink
+ * use in OS2
+ */
+
+#include "nsStreamConverterService.h"
+#include "nsIComponentRegistrar.h"
+#include "nsAutoPtr.h"
+#include "nsString.h"
+#include "nsIAtom.h"
+#include "nsDeque.h"
+#include "nsIInputStream.h"
+#include "nsIStreamConverter.h"
+#include "nsICategoryManager.h"
+#include "nsXPCOM.h"
+#include "nsISupportsPrimitives.h"
+#include "nsCOMArray.h"
+#include "nsTArray.h"
+#include "nsServiceManagerUtils.h"
+#include "nsISimpleEnumerator.h"
+
+///////////////////////////////////////////////////////////////////
+// Breadth-First-Search (BFS) algorithm state classes and types.
+
+// Used to establish discovered verticies.
+enum BFScolors {white, gray, black};
+
+// BFS hashtable data class.
+struct BFSTableData {
+ nsCString key;
+ BFScolors color;
+ int32_t distance;
+ nsAutoPtr<nsCString> predecessor;
+
+ explicit BFSTableData(const nsACString& aKey)
+ : key(aKey), color(white), distance(-1)
+ {
+ }
+};
+
+////////////////////////////////////////////////////////////
+// nsISupports methods
+NS_IMPL_ISUPPORTS(nsStreamConverterService, nsIStreamConverterService)
+
+
+////////////////////////////////////////////////////////////
+// nsIStreamConverterService methods
+
+////////////////////////////////////////////////////////////
+// nsStreamConverterService methods
+nsStreamConverterService::nsStreamConverterService()
+{
+}
+
+nsStreamConverterService::~nsStreamConverterService() = default;
+
+// Builds the graph represented as an adjacency list (and built up in
+// memory using an nsObjectHashtable and nsCOMArray combination).
+//
+// :BuildGraph() consults the category manager for all stream converter
+// CONTRACTIDS then fills the adjacency list with edges.
+// An edge in this case is comprised of a FROM and TO MIME type combination.
+//
+// CONTRACTID format:
+// @mozilla.org/streamconv;1?from=text/html&to=text/plain
+// XXX curently we only handle a single from and to combo, we should repeat the
+// XXX registration process for any series of from-to combos.
+// XXX can use nsTokenizer for this.
+//
+
+nsresult
+nsStreamConverterService::BuildGraph() {
+
+ nsresult rv;
+
+ nsCOMPtr<nsICategoryManager> catmgr(do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv));
+ if (NS_FAILED(rv)) return rv;
+
+ nsCOMPtr<nsISimpleEnumerator> entries;
+ rv = catmgr->EnumerateCategory(NS_ISTREAMCONVERTER_KEY, getter_AddRefs(entries));
+ if (NS_FAILED(rv)) return rv;
+
+ // go through each entry to build the graph
+ nsCOMPtr<nsISupports> supports;
+ nsCOMPtr<nsISupportsCString> entry;
+ rv = entries->GetNext(getter_AddRefs(supports));
+ while (NS_SUCCEEDED(rv)) {
+ entry = do_QueryInterface(supports);
+
+ // get the entry string
+ nsAutoCString entryString;
+ rv = entry->GetData(entryString);
+ if (NS_FAILED(rv)) return rv;
+
+ // cobble the entry string w/ the converter key to produce a full contractID.
+ nsAutoCString contractID(NS_ISTREAMCONVERTER_KEY);
+ contractID.Append(entryString);
+
+ // now we've got the CONTRACTID, let's parse it up.
+ rv = AddAdjacency(contractID.get());
+ if (NS_FAILED(rv)) return rv;
+
+ rv = entries->GetNext(getter_AddRefs(supports));
+ }
+
+ return NS_OK;
+}
+
+
+// XXX currently you can not add the same adjacency (i.e. you can't have multiple
+// XXX stream converters registering to handle the same from-to combination. It's
+// XXX not programatically prohibited, it's just that results are un-predictable
+// XXX right now.
+nsresult
+nsStreamConverterService::AddAdjacency(const char *aContractID) {
+ nsresult rv;
+ // first parse out the FROM and TO MIME-types.
+
+ nsAutoCString fromStr, toStr;
+ rv = ParseFromTo(aContractID, fromStr, toStr);
+ if (NS_FAILED(rv)) return rv;
+
+ // Each MIME-type is a vertex in the graph, so first lets make sure
+ // each MIME-type is represented as a key in our hashtable.
+
+ nsCOMArray<nsIAtom> *fromEdges = mAdjacencyList.Get(fromStr);
+ if (!fromEdges) {
+ // There is no fromStr vertex, create one.
+ fromEdges = new nsCOMArray<nsIAtom>();
+ mAdjacencyList.Put(fromStr, fromEdges);
+ }
+
+ if (!mAdjacencyList.Get(toStr)) {
+ // There is no toStr vertex, create one.
+ mAdjacencyList.Put(toStr, new nsCOMArray<nsIAtom>());
+ }
+
+ // Now we know the FROM and TO types are represented as keys in the hashtable.
+ // Let's "connect" the verticies, making an edge.
+
+ nsCOMPtr<nsIAtom> vertex = NS_Atomize(toStr);
+ if (!vertex) return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ASSERTION(fromEdges, "something wrong in adjacency list construction");
+ if (!fromEdges)
+ return NS_ERROR_FAILURE;
+
+ return fromEdges->AppendObject(vertex) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+nsresult
+nsStreamConverterService::ParseFromTo(const char *aContractID, nsCString &aFromRes, nsCString &aToRes) {
+
+ nsAutoCString ContractIDStr(aContractID);
+
+ int32_t fromLoc = ContractIDStr.Find("from=");
+ int32_t toLoc = ContractIDStr.Find("to=");
+ if (-1 == fromLoc || -1 == toLoc ) return NS_ERROR_FAILURE;
+
+ fromLoc = fromLoc + 5;
+ toLoc = toLoc + 3;
+
+ nsAutoCString fromStr, toStr;
+
+ ContractIDStr.Mid(fromStr, fromLoc, toLoc - 4 - fromLoc);
+ ContractIDStr.Mid(toStr, toLoc, ContractIDStr.Length() - toLoc);
+
+ aFromRes.Assign(fromStr);
+ aToRes.Assign(toStr);
+
+ return NS_OK;
+}
+
+typedef nsClassHashtable<nsCStringHashKey, BFSTableData> BFSHashTable;
+
+
+// nsObjectHashtable enumerator functions.
+
+class CStreamConvDeallocator : public nsDequeFunctor {
+public:
+ void* operator()(void* anObject) override {
+ nsCString *string = (nsCString*)anObject;
+ delete string;
+ return 0;
+ }
+};
+
+// walks the graph using a breadth-first-search algorithm which generates a discovered
+// verticies tree. This tree is then walked up (from destination vertex, to origin vertex)
+// and each link in the chain is added to an nsStringArray. A direct lookup for the given
+// CONTRACTID should be made prior to calling this method in an attempt to find a direct
+// converter rather than walking the graph.
+nsresult
+nsStreamConverterService::FindConverter(const char *aContractID, nsTArray<nsCString> **aEdgeList) {
+ nsresult rv;
+ if (!aEdgeList) return NS_ERROR_NULL_POINTER;
+ *aEdgeList = nullptr;
+
+ // walk the graph in search of the appropriate converter.
+
+ uint32_t vertexCount = mAdjacencyList.Count();
+ if (0 >= vertexCount) return NS_ERROR_FAILURE;
+
+ // Create a corresponding color table for each vertex in the graph.
+ BFSHashTable lBFSTable;
+ for (auto iter = mAdjacencyList.Iter(); !iter.Done(); iter.Next()) {
+ const nsACString &key = iter.Key();
+ MOZ_ASSERT(iter.UserData(), "no data in the table iteration");
+ lBFSTable.Put(key, new BFSTableData(key));
+ }
+
+ NS_ASSERTION(lBFSTable.Count() == vertexCount, "strmconv BFS table init problem");
+
+ // This is our source vertex; our starting point.
+ nsAutoCString fromC, toC;
+ rv = ParseFromTo(aContractID, fromC, toC);
+ if (NS_FAILED(rv)) return rv;
+
+ BFSTableData *data = lBFSTable.Get(fromC);
+ if (!data) {
+ return NS_ERROR_FAILURE;
+ }
+
+ data->color = gray;
+ data->distance = 0;
+ auto *dtorFunc = new CStreamConvDeallocator();
+
+ nsDeque grayQ(dtorFunc);
+
+ // Now generate the shortest path tree.
+ grayQ.Push(new nsCString(fromC));
+ while (0 < grayQ.GetSize()) {
+ nsCString *currentHead = (nsCString*)grayQ.PeekFront();
+ nsCOMArray<nsIAtom> *data2 = mAdjacencyList.Get(*currentHead);
+ if (!data2) return NS_ERROR_FAILURE;
+
+ // Get the state of the current head to calculate the distance of each
+ // reachable vertex in the loop.
+ BFSTableData *headVertexState = lBFSTable.Get(*currentHead);
+ if (!headVertexState) return NS_ERROR_FAILURE;
+
+ int32_t edgeCount = data2->Count();
+
+ for (int32_t i = 0; i < edgeCount; i++) {
+ nsIAtom* curVertexAtom = data2->ObjectAt(i);
+ auto *curVertex = new nsCString();
+ curVertexAtom->ToUTF8String(*curVertex);
+
+ BFSTableData *curVertexState = lBFSTable.Get(*curVertex);
+ if (!curVertexState) {
+ delete curVertex;
+ return NS_ERROR_FAILURE;
+ }
+
+ if (white == curVertexState->color) {
+ curVertexState->color = gray;
+ curVertexState->distance = headVertexState->distance + 1;
+ curVertexState->predecessor = new nsCString(*currentHead);
+ grayQ.Push(curVertex);
+ } else {
+ delete curVertex; // if this vertex has already been discovered, we don't want
+ // to leak it. (non-discovered vertex's get cleaned up when
+ // they're popped).
+ }
+ }
+ headVertexState->color = black;
+ nsCString *cur = (nsCString*)grayQ.PopFront();
+ delete cur;
+ cur = nullptr;
+ }
+ // The shortest path (if any) has been generated and is represented by the chain of
+ // BFSTableData->predecessor keys. Start at the bottom and work our way up.
+
+ // first parse out the FROM and TO MIME-types being registered.
+
+ nsAutoCString fromStr, toMIMEType;
+ rv = ParseFromTo(aContractID, fromStr, toMIMEType);
+ if (NS_FAILED(rv)) return rv;
+
+ // get the root CONTRACTID
+ nsAutoCString ContractIDPrefix(NS_ISTREAMCONVERTER_KEY);
+ auto *shortestPath = new nsTArray<nsCString>();
+
+ data = lBFSTable.Get(toMIMEType);
+ if (!data) {
+ // If this vertex isn't in the BFSTable, then no-one has registered for it,
+ // therefore we can't do the conversion.
+ delete shortestPath;
+ return NS_ERROR_FAILURE;
+ }
+
+ while (data) {
+ if (fromStr.Equals(data->key)) {
+ // found it. We're done here.
+ *aEdgeList = shortestPath;
+ return NS_OK;
+ }
+
+ // reconstruct the CONTRACTID.
+ // Get the predecessor.
+ if (!data->predecessor) break; // no predecessor
+ BFSTableData *predecessorData = lBFSTable.Get(*data->predecessor);
+
+ if (!predecessorData) break; // no predecessor, chain doesn't exist.
+
+ // build out the CONTRACTID.
+ nsAutoCString newContractID(ContractIDPrefix);
+ newContractID.AppendLiteral("?from=");
+
+ newContractID.Append(predecessorData->key);
+
+ newContractID.AppendLiteral("&to=");
+ newContractID.Append(data->key);
+
+ // Add this CONTRACTID to the chain.
+ rv = shortestPath->AppendElement(newContractID) ? NS_OK : NS_ERROR_FAILURE; // XXX this method incorrectly returns a bool
+ NS_ASSERTION(NS_SUCCEEDED(rv), "AppendElement failed");
+
+ // move up the tree.
+ data = predecessorData;
+ }
+ delete shortestPath;
+ return NS_ERROR_FAILURE; // couldn't find a stream converter or chain.
+}
+
+
+/////////////////////////////////////////////////////
+// nsIStreamConverterService methods
+NS_IMETHODIMP
+nsStreamConverterService::CanConvert(const char* aFromType,
+ const char* aToType,
+ bool* _retval) {
+ nsCOMPtr<nsIComponentRegistrar> reg;
+ nsresult rv = NS_GetComponentRegistrar(getter_AddRefs(reg));
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsAutoCString contractID;
+ contractID.AssignLiteral(NS_ISTREAMCONVERTER_KEY "?from=");
+ contractID.Append(aFromType);
+ contractID.AppendLiteral("&to=");
+ contractID.Append(aToType);
+
+ // See if we have a direct match
+ rv = reg->IsContractIDRegistered(contractID.get(), _retval);
+ if (NS_FAILED(rv))
+ return rv;
+ if (*_retval)
+ return NS_OK;
+
+ // Otherwise try the graph.
+ rv = BuildGraph();
+ if (NS_FAILED(rv))
+ return rv;
+
+ nsTArray<nsCString> *converterChain = nullptr;
+ rv = FindConverter(contractID.get(), &converterChain);
+ *_retval = NS_SUCCEEDED(rv);
+
+ delete converterChain;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsStreamConverterService::Convert(nsIInputStream *aFromStream,
+ const char *aFromType,
+ const char *aToType,
+ nsISupports *aContext,
+ nsIInputStream **_retval) {
+ if (!aFromStream || !aFromType || !aToType || !_retval) return NS_ERROR_NULL_POINTER;
+ nsresult rv;
+
+ // first determine whether we can even handle this conversion
+ // build a CONTRACTID
+ nsAutoCString contractID;
+ contractID.AssignLiteral(NS_ISTREAMCONVERTER_KEY "?from=");
+ contractID.Append(aFromType);
+ contractID.AppendLiteral("&to=");
+ contractID.Append(aToType);
+ const char *cContractID = contractID.get();
+
+ nsCOMPtr<nsIStreamConverter> converter(do_CreateInstance(cContractID, &rv));
+ if (NS_FAILED(rv)) {
+ // couldn't go direct, let's try walking the graph of converters.
+ rv = BuildGraph();
+ if (NS_FAILED(rv)) return rv;
+
+ nsTArray<nsCString> *converterChain = nullptr;
+
+ rv = FindConverter(cContractID, &converterChain);
+ if (NS_FAILED(rv)) {
+ // can't make this conversion.
+ // XXX should have a more descriptive error code.
+ return NS_ERROR_FAILURE;
+ }
+
+ int32_t edgeCount = int32_t(converterChain->Length());
+ NS_ASSERTION(edgeCount > 0, "findConverter should have failed");
+
+
+ // convert the stream using each edge of the graph as a step.
+ // this is our stream conversion traversal.
+ nsCOMPtr<nsIInputStream> dataToConvert = aFromStream;
+ nsCOMPtr<nsIInputStream> convertedData;
+
+ for (int32_t i = edgeCount-1; i >= 0; i--) {
+ const char *lContractID = converterChain->ElementAt(i).get();
+
+ converter = do_CreateInstance(lContractID, &rv);
+
+ if (NS_FAILED(rv)) {
+ delete converterChain;
+ return rv;
+ }
+
+ nsAutoCString fromStr, toStr;
+ rv = ParseFromTo(lContractID, fromStr, toStr);
+ if (NS_FAILED(rv)) {
+ delete converterChain;
+ return rv;
+ }
+
+ rv = converter->Convert(dataToConvert, fromStr.get(), toStr.get(), aContext, getter_AddRefs(convertedData));
+ dataToConvert = convertedData;
+ if (NS_FAILED(rv)) {
+ delete converterChain;
+ return rv;
+ }
+ }
+
+ delete converterChain;
+ convertedData.forget(_retval);
+ } else {
+ // we're going direct.
+ rv = converter->Convert(aFromStream, aFromType, aToType, aContext, _retval);
+ }
+
+ return rv;
+}
+
+
+NS_IMETHODIMP
+nsStreamConverterService::AsyncConvertData(const char *aFromType,
+ const char *aToType,
+ nsIStreamListener *aListener,
+ nsISupports *aContext,
+ nsIStreamListener **_retval) {
+ if (!aFromType || !aToType || !aListener || !_retval) return NS_ERROR_NULL_POINTER;
+
+ nsresult rv;
+
+ // first determine whether we can even handle this conversion
+ // build a CONTRACTID
+ nsAutoCString contractID;
+ contractID.AssignLiteral(NS_ISTREAMCONVERTER_KEY "?from=");
+ contractID.Append(aFromType);
+ contractID.AppendLiteral("&to=");
+ contractID.Append(aToType);
+ const char *cContractID = contractID.get();
+
+ nsCOMPtr<nsIStreamConverter> listener(do_CreateInstance(cContractID, &rv));
+ if (NS_FAILED(rv)) {
+ // couldn't go direct, let's try walking the graph of converters.
+ rv = BuildGraph();
+ if (NS_FAILED(rv)) return rv;
+
+ nsTArray<nsCString> *converterChain = nullptr;
+
+ rv = FindConverter(cContractID, &converterChain);
+ if (NS_FAILED(rv)) {
+ // can't make this conversion.
+ // XXX should have a more descriptive error code.
+ return NS_ERROR_FAILURE;
+ }
+
+ // aListener is the listener that wants the final, converted, data.
+ // we initialize finalListener w/ aListener so it gets put at the
+ // tail end of the chain, which in the loop below, means the *first*
+ // converter created.
+ nsCOMPtr<nsIStreamListener> finalListener = aListener;
+
+ // convert the stream using each edge of the graph as a step.
+ // this is our stream conversion traversal.
+ int32_t edgeCount = int32_t(converterChain->Length());
+ NS_ASSERTION(edgeCount > 0, "findConverter should have failed");
+ for (int i = 0; i < edgeCount; i++) {
+ const char *lContractID = converterChain->ElementAt(i).get();
+
+ // create the converter for this from/to pair
+ nsCOMPtr<nsIStreamConverter> converter(do_CreateInstance(lContractID));
+ NS_ASSERTION(converter, "graph construction problem, built a contractid that wasn't registered");
+
+ nsAutoCString fromStr, toStr;
+ rv = ParseFromTo(lContractID, fromStr, toStr);
+ if (NS_FAILED(rv)) {
+ delete converterChain;
+ return rv;
+ }
+
+ // connect the converter w/ the listener that should get the converted data.
+ rv = converter->AsyncConvertData(fromStr.get(), toStr.get(), finalListener, aContext);
+ if (NS_FAILED(rv)) {
+ delete converterChain;
+ return rv;
+ }
+
+ nsCOMPtr<nsIStreamListener> chainListener(do_QueryInterface(converter, &rv));
+ if (NS_FAILED(rv)) {
+ delete converterChain;
+ return rv;
+ }
+
+ // the last iteration of this loop will result in finalListener
+ // pointing to the converter that "starts" the conversion chain.
+ // this converter's "from" type is the original "from" type. Prior
+ // to the last iteration, finalListener will continuously be wedged
+ // into the next listener in the chain, then be updated.
+ finalListener = chainListener;
+ }
+ delete converterChain;
+ // return the first listener in the chain.
+ finalListener.forget(_retval);
+ } else {
+ // we're going direct.
+ rv = listener->AsyncConvertData(aFromType, aToType, aListener, aContext);
+ listener.forget(_retval);
+ }
+
+ return rv;
+
+}
+
+nsresult
+NS_NewStreamConv(nsStreamConverterService** aStreamConv)
+{
+ NS_PRECONDITION(aStreamConv != nullptr, "null ptr");
+ if (!aStreamConv) return NS_ERROR_NULL_POINTER;
+
+ *aStreamConv = new nsStreamConverterService();
+ NS_ADDREF(*aStreamConv);
+
+ return NS_OK;
+}
diff --git a/netwerk/streamconv/nsStreamConverterService.h b/netwerk/streamconv/nsStreamConverterService.h
new file mode 100644
index 000000000..70f419ff9
--- /dev/null
+++ b/netwerk/streamconv/nsStreamConverterService.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __nsstreamconverterservice__h___
+#define __nsstreamconverterservice__h___
+
+#include "nsIStreamConverterService.h"
+
+#include "nsClassHashtable.h"
+#include "nsCOMArray.h"
+#include "nsTArrayForwardDeclare.h"
+
+class nsCString;
+class nsIAtom;
+
+class nsStreamConverterService : public nsIStreamConverterService {
+public:
+ /////////////////////////////////////////////////////
+ // nsISupports methods
+ NS_DECL_ISUPPORTS
+
+
+ /////////////////////////////////////////////////////
+ // nsIStreamConverterService methods
+ NS_DECL_NSISTREAMCONVERTERSERVICE
+
+ /////////////////////////////////////////////////////
+ // nsStreamConverterService methods
+ nsStreamConverterService();
+
+private:
+ virtual ~nsStreamConverterService();
+
+ // Responsible for finding a converter for the given MIME-type.
+ nsresult FindConverter(const char *aContractID, nsTArray<nsCString> **aEdgeList);
+ nsresult BuildGraph(void);
+ nsresult AddAdjacency(const char *aContractID);
+ nsresult ParseFromTo(const char *aContractID, nsCString &aFromRes, nsCString &aToRes);
+
+ // member variables
+ nsClassHashtable<nsCStringHashKey, nsCOMArray<nsIAtom>> mAdjacencyList;
+};
+
+#endif // __nsstreamconverterservice__h___
diff --git a/netwerk/streamconv/test/Converters.cpp b/netwerk/streamconv/test/Converters.cpp
new file mode 100644
index 000000000..61b114d77
--- /dev/null
+++ b/netwerk/streamconv/test/Converters.cpp
@@ -0,0 +1,140 @@
+#include "Converters.h"
+#include "nsIStringStream.h"
+#include "nsCOMPtr.h"
+#include "nsComponentManagerUtils.h"
+
+#include <stdio.h>
+
+//////////////////////////////////////////////////
+// TestConverter
+//////////////////////////////////////////////////
+
+#define NS_TESTCONVERTER_CID \
+{ /* B8A067B0-4450-11d3-A16E-0050041CAF44 */ \
+ 0xb8a067b0, \
+ 0x4450, \
+ 0x11d3, \
+ {0xa1, 0x6e, 0x00, 0x50, 0x04, 0x1c, 0xaf, 0x44} \
+}
+
+NS_DEFINE_CID(kTestConverterCID, NS_TESTCONVERTER_CID);
+
+NS_IMPL_ISUPPORTS(TestConverter,
+ nsIStreamConverter,
+ nsIStreamListener,
+ nsIRequestObserver)
+
+TestConverter::TestConverter() {
+}
+
+// Convert aFromStream (of type aFromType), to _retval (nsIInputStream of type aToType).
+// This Convert method simply converts the stream byte-by-byte, to the first character
+// in the aToType "string".
+NS_IMETHODIMP
+TestConverter::Convert(nsIInputStream *aFromStream,
+ const char *aFromType,
+ const char *aToType,
+ nsISupports *ctxt,
+ nsIInputStream **_retval) {
+ char buf[1024+1];
+ uint32_t read;
+ nsresult rv = aFromStream->Read(buf, 1024, &read);
+ if (NS_FAILED(rv) || read == 0) return rv;
+
+ // verify that the data we're converting matches the from type
+ // if it doesn't then we're being handed the wrong data.
+ char fromChar = *aFromType;
+
+ if (fromChar != buf[0]) {
+ printf("We're receiving %c, but are supposed to have %c.\n", buf[0], fromChar);
+ return NS_ERROR_FAILURE;
+ }
+
+
+ // Get the first character
+ char toChar = *aToType;
+
+ for (uint32_t i = 0; i < read; i++)
+ buf[i] = toChar;
+
+ buf[read] = '\0';
+
+ nsCOMPtr<nsIStringInputStream> str
+ (do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = str->SetData(buf, read);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ NS_ADDREF(*_retval = str);
+ return NS_OK;
+}
+
+/* This method initializes any internal state before the stream converter
+ * begins asynchronous conversion */
+NS_IMETHODIMP
+TestConverter::AsyncConvertData(const char *aFromType,
+ const char *aToType,
+ nsIStreamListener *aListener,
+ nsISupports *ctxt) {
+ NS_ASSERTION(aListener, "null listener");
+
+ mListener = aListener;
+
+ // based on these types, setup internal state to handle the appropriate conversion.
+ fromType = aFromType;
+ toType = aToType;
+
+ return NS_OK;
+}
+
+// nsIStreamListener method
+/* This method handles asyncronous conversion of data. */
+NS_IMETHODIMP
+TestConverter::OnDataAvailable(nsIRequest* request,
+ nsISupports *ctxt,
+ nsIInputStream *inStr,
+ uint64_t sourceOffset,
+ uint32_t count) {
+ nsresult rv;
+ nsCOMPtr<nsIInputStream> convertedStream;
+ // just make a syncronous call to the Convert() method.
+ // Anything can happen here, I just happen to be using the sync call to
+ // do the actual conversion.
+ rv = Convert(inStr, fromType.get(), toType.get(), ctxt, getter_AddRefs(convertedStream));
+ if (NS_FAILED(rv)) return rv;
+
+ uint64_t len = 0;
+ convertedStream->Available(&len);
+
+ uint64_t offset = sourceOffset;
+ while (len > 0) {
+ uint32_t count = saturated(len);
+ rv = mListener->OnDataAvailable(request, ctxt, convertedStream, offset, count);
+ if (NS_FAILED(rv)) return rv;
+
+ offset += count;
+ len -= count;
+ }
+ return NS_OK;
+}
+
+// nsIRequestObserver methods
+/* These methods just pass through directly to the mListener */
+NS_IMETHODIMP
+TestConverter::OnStartRequest(nsIRequest* request, nsISupports *ctxt) {
+ return mListener->OnStartRequest(request, ctxt);
+}
+
+NS_IMETHODIMP
+TestConverter::OnStopRequest(nsIRequest* request, nsISupports *ctxt,
+ nsresult aStatus) {
+ return mListener->OnStopRequest(request, ctxt, aStatus);
+}
+
+nsresult
+CreateTestConverter(nsISupports* aOuter, REFNSIID aIID, void** aResult)
+{
+ nsCOMPtr<nsISupports> conv = new TestConverter();
+ return conv->QueryInterface(aIID, aResult);
+}
diff --git a/netwerk/streamconv/test/Converters.h b/netwerk/streamconv/test/Converters.h
new file mode 100644
index 000000000..d7203262c
--- /dev/null
+++ b/netwerk/streamconv/test/Converters.h
@@ -0,0 +1,52 @@
+#ifndef Converters_h___
+#define Converters_h___
+
+#include "nsIStreamConverter.h"
+#include "nsIFactory.h"
+#include "nsCOMPtr.h"
+#include "nsStringAPI.h"
+
+#include <algorithm>
+
+/* This file defines stream converter components, and their accompanying factory class.
+ * These converters implement the nsIStreamConverter interface and support both
+ * asynchronous and synchronous stream conversion.
+ */
+
+///////////////////////////////////////////////
+// TestConverter
+
+extern const nsCID kTestConverterCID;
+
+class TestConverter : public nsIStreamConverter {
+ virtual ~TestConverter() {}
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIREQUESTOBSERVER
+ NS_DECL_NSISTREAMLISTENER
+
+ TestConverter();
+
+ // nsIStreamConverter methods
+ NS_IMETHOD Convert(nsIInputStream *aFromStream, const char *aFromType,
+ const char *aToType, nsISupports *ctxt, nsIInputStream **_retval) override;
+
+
+ NS_IMETHOD AsyncConvertData(const char *aFromType, const char *aToType,
+ nsIStreamListener *aListener, nsISupports *ctxt) override;
+
+ // member data
+ nsCOMPtr<nsIStreamListener> mListener;
+ nsCString fromType;
+ nsCString toType;
+};
+
+nsresult CreateTestConverter(nsISupports* aOuter, REFNSIID aIID, void** aResult);
+
+static inline uint32_t
+saturated(uint64_t aValue)
+{
+ return (uint32_t) std::min(aValue, (uint64_t) UINT32_MAX);
+}
+
+#endif /* !Converters_h___ */
diff --git a/netwerk/streamconv/test/TestStreamConv.cpp b/netwerk/streamconv/test/TestStreamConv.cpp
new file mode 100644
index 000000000..68b85fdd7
--- /dev/null
+++ b/netwerk/streamconv/test/TestStreamConv.cpp
@@ -0,0 +1,261 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsIServiceManager.h"
+#include "nsIStreamConverterService.h"
+#include "nsIStreamConverter.h"
+#include "nsICategoryManager.h"
+#include "mozilla/Module.h"
+#include "nsXULAppAPI.h"
+#include "nsIStringStream.h"
+#include "nsCOMPtr.h"
+#include "nsThreadUtils.h"
+#include "mozilla/Attributes.h"
+#include "nsMemory.h"
+#include "nsServiceManagerUtils.h"
+#include "nsComponentManagerUtils.h"
+#include "nsIRequest.h"
+#include "nsNetCID.h"
+#include "nsNetUtil.h"
+
+#define ASYNC_TEST // undefine this if you want to test sycnronous conversion.
+
+/////////////////////////////////
+// Event pump setup
+/////////////////////////////////
+#ifdef XP_WIN
+#include <windows.h>
+#endif
+
+static int gKeepRunning = 0;
+/////////////////////////////////
+// Event pump END
+/////////////////////////////////
+
+
+/////////////////////////////////
+// Test converters include
+/////////////////////////////////
+#include "Converters.h"
+
+// CID setup
+static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
+
+////////////////////////////////////////////////////////////////////////
+// EndListener - This listener is the final one in the chain. It
+// receives the fully converted data, although it doesn't do anything with
+// the data.
+////////////////////////////////////////////////////////////////////////
+class EndListener final : public nsIStreamListener {
+ ~EndListener() {}
+public:
+ // nsISupports declaration
+ NS_DECL_ISUPPORTS
+
+ EndListener() {}
+
+ // nsIStreamListener method
+ NS_IMETHOD OnDataAvailable(nsIRequest* request, nsISupports *ctxt, nsIInputStream *inStr,
+ uint64_t sourceOffset, uint32_t count) override
+ {
+ nsresult rv;
+ uint32_t read;
+ uint64_t len64;
+ rv = inStr->Available(&len64);
+ if (NS_FAILED(rv)) return rv;
+ uint32_t len = (uint32_t)std::min(len64, (uint64_t)(UINT32_MAX - 1));
+
+ char *buffer = (char*)moz_xmalloc(len + 1);
+ if (!buffer) return NS_ERROR_OUT_OF_MEMORY;
+
+ rv = inStr->Read(buffer, len, &read);
+ buffer[len] = '\0';
+ if (NS_SUCCEEDED(rv)) {
+ printf("CONTEXT %p: Received %u bytes and the following data: \n %s\n\n",
+ static_cast<void*>(ctxt), read, buffer);
+ }
+ free(buffer);
+
+ return NS_OK;
+ }
+
+ // nsIRequestObserver methods
+ NS_IMETHOD OnStartRequest(nsIRequest* request, nsISupports *ctxt) override { return NS_OK; }
+
+ NS_IMETHOD OnStopRequest(nsIRequest* request, nsISupports *ctxt,
+ nsresult aStatus) override { return NS_OK; }
+};
+
+NS_IMPL_ISUPPORTS(EndListener,
+ nsIStreamListener,
+ nsIRequestObserver)
+
+////////////////////////////////////////////////////////////////////////
+// EndListener END
+////////////////////////////////////////////////////////////////////////
+
+nsresult SendData(const char * aData, nsIStreamListener* aListener, nsIRequest* request) {
+ nsresult rv;
+
+ nsCOMPtr<nsIStringInputStream> dataStream
+ (do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = dataStream->SetData(aData, strlen(aData));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint64_t avail = 0;
+ dataStream->Available(&avail);
+
+ uint64_t offset = 0;
+ while (avail > 0) {
+ uint32_t count = saturated(avail);
+ rv = aListener->OnDataAvailable(request, nullptr, dataStream,
+ offset, count);
+ if (NS_FAILED(rv)) return rv;
+
+ offset += count;
+ avail -= count;
+ }
+ return NS_OK;
+}
+#define SEND_DATA(x) SendData(x, converterListener, request)
+
+static const mozilla::Module::CIDEntry kTestCIDs[] = {
+ { &kTestConverterCID, false, nullptr, CreateTestConverter },
+ { nullptr }
+};
+
+static const mozilla::Module::ContractIDEntry kTestContracts[] = {
+ { NS_ISTREAMCONVERTER_KEY "?from=a/foo&to=b/foo", &kTestConverterCID },
+ { NS_ISTREAMCONVERTER_KEY "?from=b/foo&to=c/foo", &kTestConverterCID },
+ { NS_ISTREAMCONVERTER_KEY "?from=b/foo&to=d/foo", &kTestConverterCID },
+ { NS_ISTREAMCONVERTER_KEY "?from=c/foo&to=d/foo", &kTestConverterCID },
+ { NS_ISTREAMCONVERTER_KEY "?from=d/foo&to=e/foo", &kTestConverterCID },
+ { NS_ISTREAMCONVERTER_KEY "?from=d/foo&to=f/foo", &kTestConverterCID },
+ { NS_ISTREAMCONVERTER_KEY "?from=t/foo&to=k/foo", &kTestConverterCID },
+ { nullptr }
+};
+
+static const mozilla::Module::CategoryEntry kTestCategories[] = {
+ { NS_ISTREAMCONVERTER_KEY, "?from=a/foo&to=b/foo", "x" },
+ { NS_ISTREAMCONVERTER_KEY, "?from=b/foo&to=c/foo", "x" },
+ { NS_ISTREAMCONVERTER_KEY, "?from=b/foo&to=d/foo", "x" },
+ { NS_ISTREAMCONVERTER_KEY, "?from=c/foo&to=d/foo", "x" },
+ { NS_ISTREAMCONVERTER_KEY, "?from=d/foo&to=e/foo", "x" },
+ { NS_ISTREAMCONVERTER_KEY, "?from=d/foo&to=f/foo", "x" },
+ { NS_ISTREAMCONVERTER_KEY, "?from=t/foo&to=k/foo", "x" },
+ { nullptr }
+};
+
+static const mozilla::Module kTestModule = {
+ mozilla::Module::kVersion,
+ kTestCIDs,
+ kTestContracts,
+ kTestCategories
+};
+
+int
+main(int argc, char* argv[])
+{
+ nsresult rv;
+ {
+ XRE_AddStaticComponent(&kTestModule);
+
+ nsCOMPtr<nsIServiceManager> servMan;
+ NS_InitXPCOM2(getter_AddRefs(servMan), nullptr, nullptr);
+
+ nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
+
+ nsCOMPtr<nsICategoryManager> catman =
+ do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
+ if (NS_FAILED(rv)) return -1;
+ nsCString previous;
+
+ nsCOMPtr<nsIStreamConverterService> StreamConvService =
+ do_GetService(kStreamConverterServiceCID, &rv);
+ if (NS_FAILED(rv)) return -1;
+
+ // Define the *from* content type and *to* content-type for conversion.
+ static const char fromStr[] = "a/foo";
+ static const char toStr[] = "c/foo";
+
+#ifdef ASYNC_TEST
+ // ASYNCHRONOUS conversion
+
+ // Build up a channel that represents the content we're
+ // starting the transaction with.
+ //
+ // sample multipart mixed content-type string:
+ // "multipart/x-mixed-replacE;boundary=thisrandomstring"
+#if 0
+ nsCOMPtr<nsIChannel> channel;
+ nsCOMPtr<nsIURI> dummyURI;
+ rv = NS_NewURI(getter_AddRefs(dummyURI), "http://meaningless");
+ if (NS_FAILED(rv)) return -1;
+
+ rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
+ dummyURI,
+ nullptr, // inStr
+ "text/plain", // content-type
+ -1); // XXX fix contentLength
+ if (NS_FAILED(rv)) return -1;
+
+ nsCOMPtr<nsIRequest> request(do_QueryInterface(channel));
+#endif
+
+ nsCOMPtr<nsIRequest> request;
+
+ // setup a listener to receive the converted data. This guy is the end
+ // listener in the chain, he wants the fully converted (toType) data.
+ // An example of this listener in mozilla would be the DocLoader.
+ nsIStreamListener *dataReceiver = new EndListener();
+ NS_ADDREF(dataReceiver);
+
+ // setup a listener to push the data into. This listener sits inbetween the
+ // unconverted data of fromType, and the final listener in the chain (in this case
+ // the dataReceiver.
+ nsIStreamListener *converterListener = nullptr;
+ rv = StreamConvService->AsyncConvertData(fromStr, toStr,
+ dataReceiver, nullptr, &converterListener);
+ if (NS_FAILED(rv)) return -1;
+ NS_RELEASE(dataReceiver);
+
+ // at this point we have a stream listener to push data to, and the one
+ // that will receive the converted data. Let's mimic On*() calls and get the conversion
+ // going. Typically these On*() calls would be made inside their respective wrappers On*()
+ // methods.
+ rv = converterListener->OnStartRequest(request, nullptr);
+ if (NS_FAILED(rv)) return -1;
+
+ rv = SEND_DATA("aaa");
+ if (NS_FAILED(rv)) return -1;
+
+ rv = SEND_DATA("aaa");
+ if (NS_FAILED(rv)) return -1;
+
+ // Finish the request.
+ rv = converterListener->OnStopRequest(request, nullptr, rv);
+ if (NS_FAILED(rv)) return -1;
+
+ NS_RELEASE(converterListener);
+#else
+ // SYNCHRONOUS conversion
+ nsCOMPtr<nsIInputStream> convertedData;
+ rv = StreamConvService->Convert(inputData, fromStr, toStr,
+ nullptr, getter_AddRefs(convertedData));
+ if (NS_FAILED(rv)) return -1;
+#endif
+
+ // Enter the message pump to allow the URL load to proceed.
+ while ( gKeepRunning ) {
+ if (!NS_ProcessNextEvent(thread))
+ break;
+ }
+ } // this scopes the nsCOMPtrs
+ // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
+ NS_ShutdownXPCOM(nullptr);
+ return 0;
+}
diff --git a/netwerk/streamconv/test/moz.build b/netwerk/streamconv/test/moz.build
new file mode 100644
index 000000000..ea081559b
--- /dev/null
+++ b/netwerk/streamconv/test/moz.build
@@ -0,0 +1,22 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+GeckoProgram('TestStreamConv', linkage='dependent')
+
+UNIFIED_SOURCES += [
+ 'Converters.cpp',
+ 'TestStreamConv.cpp',
+]
+
+if CONFIG['OS_ARCH'] == 'WINNT':
+ DEFINES['NGPREFS'] = True
+ if CONFIG['GNU_CXX']:
+ LDFLAGS += ['-mconsole']
+ else:
+ LDFLAGS += ['-SUBSYSTEM:CONSOLE']
+
+if CONFIG['GNU_CXX']:
+ CXXFLAGS += ['-Wno-error=shadow']