diff --git a/netwerk/streamconv/converters/ParseFTPList.cpp b/netwerk/streamconv/converters/ParseFTPList.cpp
index 8a19b80ca8c6b957708cf4d1f00a59990c2904df..d9b20275719f764c10e340ca33e28c749125306a 100644
--- a/netwerk/streamconv/converters/ParseFTPList.cpp
+++ b/netwerk/streamconv/converters/ParseFTPList.cpp
@@ -40,11 +40,19 @@
 #include <string.h>
 #include <ctype.h>
 #include "plstr.h"
+#include "nsDebug.h"
 
 #include "ParseFTPList.h"
 
 /* ==================================================================== */
 
+static inline int ParseFTPListDetermineRetval(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 )
 {
@@ -123,6 +131,9 @@ int ParseFTPList(const char *line, struct list_state *state,
       }
     }    
 
+    if (!numtoks)
+      return ParseFTPListDetermineRetval(state);
+
     linelen_sans_wsp = &(tokens[numtoks-1][toklen[numtoks-1]]) - tokens[0];
     if (numtoks == (sizeof(tokens)/sizeof(tokens[0])) )
     {
@@ -356,11 +367,16 @@ int ParseFTPList(const char *line, struct list_state *state,
               pos++;
               p++;
             }
-            if (lstyle && pos < (toklen[0]-1) && *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 != ';')
@@ -387,7 +403,7 @@ int ParseFTPList(const char *line, struct list_state *state,
           pos -= tokmarker;      /* => fnlength sans "[DIR1.DIR2.etc]" */
           p = &(tokens[0][tokmarker]); /* offset of basename */
 
-          if (!lstyle || pos > 80) /* VMS filenames can't be longer than that */
+          if (!lstyle || pos == 0 || pos > 80) /* VMS filenames can't be longer than that */
           {
             lstyle = 0;
           }
@@ -1684,9 +1700,7 @@ int ParseFTPList(const char *line, struct list_state *state,
 
   } /* if (linelen > 0) */
 
-  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 */
+  return ParseFTPListDetermineRetval(state);
 }
 
 /* ==================================================================== */
@@ -1705,7 +1719,7 @@ static int do_it(FILE *outfile,
   char *p;
   int rc;
 
-  rc = ParseFTPLIST( line, state, &result );
+  rc = ParseFTPList( line, state, &result );
 
   if (!outfile)
   {
diff --git a/netwerk/test/unit/test_bug515583.js b/netwerk/test/unit/test_bug515583.js
new file mode 100644
index 0000000000000000000000000000000000000000..2fea545e09785cd7da0d56988ce7e7db7d6747b8
--- /dev/null
+++ b/netwerk/test/unit/test_bug515583.js
@@ -0,0 +1,72 @@
+function getURLContent(aURL) {
+  var ios = Components.classes["@mozilla.org/network/io-service;1"].
+            getService(Components.interfaces.nsIIOService);
+
+  var uri = ios.newURI(aURL, null, null);
+  var chan = ios.newChannelFromURI(uri);
+  var inp = chan.open();
+  var scinp = Components.classes["@mozilla.org/scriptableinputstream;1"].
+              createInstance(Components.interfaces.nsIScriptableInputStream);
+  scinp.init(inp);
+  var result = "";
+  var avail = scinp.available();
+  while (avail) {
+    result += scinp.read(avail);
+    avail = scinp.available();
+  }
+  return result;
+}
+
+function storeCache(aURL, aContent) {
+  const nsICache = Components.interfaces.nsICache;
+
+  var cache = Components.classes["@mozilla.org/network/cache-service;1"].
+              getService(Components.interfaces.nsICacheService);
+
+  var session = cache.createSession("FTP", nsICache.STORE_ANYWHERE, nsICache.STREAM_BASED);
+
+  var cacheEntry = session.openCacheEntry(aURL, nsICache.ACCESS_READ_WRITE, false);
+
+  cacheEntry.setMetaDataElement("servertype", "0");
+  var oStream = cacheEntry.openOutputStream(0);
+
+  var written = oStream.write(aContent, aContent.length);
+  if (written != aContent.length) {
+    do_throw("oStream.write has not written all data!\n" +
+             "  Expected: " + written  + "\n" +
+             "  Actual: " + aContent.length + "\n");
+  }
+  oStream.close();
+  cacheEntry.close();
+}
+
+const URL = "ftp://localhost/bug515583/";
+
+const tests = [
+  ["[RWCEM1 4 1-MAR-1993 18:09:01.12\r\n" +
+   "[RWCEM1] 4 2-MAR-1993 18:09:01.12\r\n" +
+   "[RWCEM1]A 4 3-MAR-1993 18:09:01.12\r\n" +
+   "[RWCEM1]B; 4 4-MAR-1993 18:09:01.12\r\n" +
+   "[RWCEM1];1 4 5-MAR-1993 18:09:01.12\r\n" +
+   "[RWCEM1]; 4 6-MAR-1993 18:09:01.12\r\n" +
+   "[RWCEM1]C;1D 4 7-MAR-1993 18:09:01.12\r\n" +
+   "[RWCEM1]E;1 4 8-MAR-1993 18:09:01.12\r\n"
+  ,
+   "300: " + URL + "\n" +
+   "200: filename content-length last-modified file-type\n" +
+   "201: \"A\" 2048 Sun%2C%2003%20Mar%201993%2018%3A09%3A01 FILE \n" +
+   "201: \"E\" 2048 Sun%2C%2008%20Mar%201993%2018%3A09%3A01 FILE \n"]
+   ,
+   ["\r\r\r\n"
+   ,
+   "300: " + URL + "\n" +
+   "200: filename content-length last-modified file-type\n"]
+]
+
+function run_test() {
+  for (var i = 0; i < tests.length; i++) {
+    storeCache(URL, tests[i][0]);
+    var parsedData = getURLContent(URL);
+    do_check_eq(parsedData, tests[i][1]);
+  }
+}