LCOV - code coverage report
Current view: top level - netwerk/streamconv/converters - nsIndexedToHTML.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 345 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 19 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "nsIndexedToHTML.h"
       7             : 
       8             : #include "DateTimeFormat.h"
       9             : #include "mozilla/Encoding.h"
      10             : #include "mozilla/intl/LocaleService.h"
      11             : #include "nsNetUtil.h"
      12             : #include "netCore.h"
      13             : #include "nsStringStream.h"
      14             : #include "nsIFile.h"
      15             : #include "nsIFileURL.h"
      16             : #include "nsEscape.h"
      17             : #include "nsIDirIndex.h"
      18             : #include "nsURLHelper.h"
      19             : #include "nsIPlatformCharset.h"
      20             : #include "nsIPrefService.h"
      21             : #include "nsIPrefBranch.h"
      22             : #include "nsIPrefLocalizedString.h"
      23             : #include "nsIStringBundle.h"
      24             : #include "nsITextToSubURI.h"
      25             : #include "nsXPIDLString.h"
      26             : #include <algorithm>
      27             : #include "nsIChannel.h"
      28             : 
      29             : using mozilla::intl::LocaleService;
      30             : 
      31           0 : NS_IMPL_ISUPPORTS(nsIndexedToHTML,
      32             :                   nsIDirIndexListener,
      33             :                   nsIStreamConverter,
      34             :                   nsIRequestObserver,
      35             :                   nsIStreamListener)
      36             : 
      37           0 : static void AppendNonAsciiToNCR(const nsAString& in, nsCString& out)
      38             : {
      39           0 :   nsAString::const_iterator start, end;
      40             : 
      41           0 :   in.BeginReading(start);
      42           0 :   in.EndReading(end);
      43             : 
      44           0 :   while (start != end) {
      45           0 :     if (*start < 128) {
      46           0 :       out.Append(*start++);
      47             :     } else {
      48           0 :       out.AppendLiteral("&#x");
      49           0 :       out.AppendInt(*start++, 16);
      50           0 :       out.Append(';');
      51             :     }
      52             :   }
      53           0 : }
      54             : 
      55             : nsresult
      56           0 : nsIndexedToHTML::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) {
      57             :     nsresult rv;
      58           0 :     if (aOuter)
      59           0 :         return NS_ERROR_NO_AGGREGATION;
      60             : 
      61           0 :     nsIndexedToHTML* _s = new nsIndexedToHTML();
      62           0 :     if (_s == nullptr)
      63           0 :         return NS_ERROR_OUT_OF_MEMORY;
      64             : 
      65           0 :     rv = _s->QueryInterface(aIID, aResult);
      66           0 :     return rv;
      67             : }
      68             : 
      69             : nsresult
      70           0 : nsIndexedToHTML::Init(nsIStreamListener* aListener) {
      71           0 :     nsresult rv = NS_OK;
      72             : 
      73           0 :     mListener = aListener;
      74             : 
      75             :     nsCOMPtr<nsIStringBundleService> sbs =
      76           0 :         do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
      77           0 :     if (NS_FAILED(rv)) return rv;
      78           0 :     rv = sbs->CreateBundle(NECKO_MSGS_URL, getter_AddRefs(mBundle));
      79             : 
      80           0 :     mExpectAbsLoc = false;
      81             : 
      82           0 :     return rv;
      83             : }
      84             : 
      85             : NS_IMETHODIMP
      86           0 : nsIndexedToHTML::Convert(nsIInputStream* aFromStream,
      87             :                          const char* aFromType,
      88             :                          const char* aToType,
      89             :                          nsISupports* aCtxt,
      90             :                          nsIInputStream** res) {
      91           0 :     return NS_ERROR_NOT_IMPLEMENTED;
      92             : }
      93             : 
      94             : NS_IMETHODIMP
      95           0 : nsIndexedToHTML::AsyncConvertData(const char *aFromType,
      96             :                                   const char *aToType,
      97             :                                   nsIStreamListener *aListener,
      98             :                                   nsISupports *aCtxt) {
      99           0 :     return Init(aListener);
     100             : }
     101             : 
     102             : NS_IMETHODIMP
     103           0 : nsIndexedToHTML::OnStartRequest(nsIRequest* request, nsISupports *aContext) {
     104           0 :     nsCString buffer;
     105           0 :     nsresult rv = DoOnStartRequest(request, aContext, buffer);
     106           0 :     if (NS_FAILED(rv)) {
     107           0 :         request->Cancel(rv);
     108             :     }
     109             : 
     110           0 :     rv = mListener->OnStartRequest(request, aContext);
     111           0 :     if (NS_FAILED(rv)) return rv;
     112             : 
     113             :     // The request may have been canceled, and if that happens, we want to
     114             :     // suppress calls to OnDataAvailable.
     115           0 :     request->GetStatus(&rv);
     116           0 :     if (NS_FAILED(rv)) return rv;
     117             : 
     118             :     // Push our buffer to the listener.
     119             : 
     120           0 :     rv = SendToListener(request, aContext, buffer);
     121           0 :     return rv;
     122             : }
     123             : 
     124             : nsresult
     125           0 : nsIndexedToHTML::DoOnStartRequest(nsIRequest* request, nsISupports *aContext,
     126             :                                   nsCString& aBuffer) {
     127             :     nsresult rv;
     128             : 
     129           0 :     nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
     130           0 :     nsCOMPtr<nsIURI> uri;
     131           0 :     rv = channel->GetOriginalURI(getter_AddRefs(uri));
     132           0 :     if (NS_FAILED(rv)) return rv;
     133             : 
     134           0 :     bool isResource = false;
     135           0 :     rv = uri->SchemeIs("resource", &isResource);
     136           0 :     if (NS_FAILED(rv)) return rv;
     137             : 
     138             :     // We use the original URI for the title and parent link when it's a
     139             :     // resource:// url, instead of the jar:file:// url it resolves to.
     140           0 :     if (!isResource) {
     141           0 :         rv = channel->GetURI(getter_AddRefs(uri));
     142           0 :         if (NS_FAILED(rv)) return rv;
     143             :     }
     144             : 
     145           0 :     channel->SetContentType(NS_LITERAL_CSTRING("text/html"));
     146             : 
     147           0 :     mParser = do_CreateInstance("@mozilla.org/dirIndexParser;1",&rv);
     148           0 :     if (NS_FAILED(rv)) return rv;
     149             : 
     150           0 :     rv = mParser->SetListener(this);
     151           0 :     if (NS_FAILED(rv)) return rv;
     152             : 
     153           0 :     rv = mParser->OnStartRequest(request, aContext);
     154           0 :     if (NS_FAILED(rv)) return rv;
     155             : 
     156           0 :     nsAutoCString baseUri, titleUri;
     157           0 :     rv = uri->GetAsciiSpec(baseUri);
     158           0 :     if (NS_FAILED(rv)) return rv;
     159           0 :     titleUri = baseUri;
     160             : 
     161           0 :     nsCString parentStr;
     162             : 
     163           0 :     nsCString buffer;
     164           0 :     buffer.AppendLiteral("<!DOCTYPE html>\n<html>\n<head>\n");
     165             : 
     166             :     // XXX - should be using the 300: line from the parser.
     167             :     // We can't guarantee that that comes before any entry, so we'd have to
     168             :     // buffer, and do other painful stuff.
     169             :     // I'll deal with this when I make the changes to handle welcome messages
     170             :     // The .. stuff should also come from the lower level protocols, but that
     171             :     // would muck up the XUL display
     172             :     // - bbaetz
     173             : 
     174           0 :     bool isScheme = false;
     175           0 :     bool isSchemeFile = false;
     176           0 :     if (NS_SUCCEEDED(uri->SchemeIs("ftp", &isScheme)) && isScheme) {
     177             : 
     178             :         // strip out the password here, so it doesn't show in the page title
     179             :         // This is done by the 300: line generation in ftp, but we don't use
     180             :         // that - see above
     181             : 
     182           0 :         nsAutoCString pw;
     183           0 :         rv = uri->GetPassword(pw);
     184           0 :         if (NS_FAILED(rv)) return rv;
     185           0 :         if (!pw.IsEmpty()) {
     186           0 :              nsCOMPtr<nsIURI> newUri;
     187           0 :              rv = uri->Clone(getter_AddRefs(newUri));
     188           0 :              if (NS_FAILED(rv)) return rv;
     189           0 :              rv = newUri->SetPassword(EmptyCString());
     190           0 :              if (NS_FAILED(rv)) return rv;
     191           0 :              rv = newUri->GetAsciiSpec(titleUri);
     192           0 :              if (NS_FAILED(rv)) return rv;
     193             :         }
     194             : 
     195           0 :         nsAutoCString path;
     196           0 :         rv = uri->GetPath(path);
     197           0 :         if (NS_FAILED(rv)) return rv;
     198             : 
     199           0 :         if (!path.EqualsLiteral("//") && !path.LowerCaseEqualsLiteral("/%2f")) {
     200           0 :             rv = uri->Resolve(NS_LITERAL_CSTRING(".."),parentStr);
     201           0 :             if (NS_FAILED(rv)) return rv;
     202             :         }
     203           0 :     } else if (NS_SUCCEEDED(uri->SchemeIs("file", &isSchemeFile)) && isSchemeFile) {
     204           0 :         nsCOMPtr<nsIFileURL> fileUrl = do_QueryInterface(uri);
     205           0 :         nsCOMPtr<nsIFile> file;
     206           0 :         rv = fileUrl->GetFile(getter_AddRefs(file));
     207           0 :         if (NS_FAILED(rv)) return rv;
     208           0 :         file->SetFollowLinks(true);
     209             : 
     210           0 :         nsAutoCString url;
     211           0 :         rv = net_GetURLSpecFromFile(file, url);
     212           0 :         if (NS_FAILED(rv)) return rv;
     213           0 :         baseUri.Assign(url);
     214             : 
     215           0 :         nsCOMPtr<nsIFile> parent;
     216           0 :         rv = file->GetParent(getter_AddRefs(parent));
     217             : 
     218           0 :         if (parent && NS_SUCCEEDED(rv)) {
     219           0 :             net_GetURLSpecFromDir(parent, url);
     220           0 :             if (NS_FAILED(rv)) return rv;
     221           0 :             parentStr.Assign(url);
     222             :         }
     223             : 
     224             :         // Directory index will be always encoded in UTF-8 if this is file url
     225           0 :         buffer.AppendLiteral("<meta charset=\"UTF-8\">\n");
     226             : 
     227           0 :     } else if (NS_SUCCEEDED(uri->SchemeIs("jar", &isScheme)) && isScheme) {
     228           0 :         nsAutoCString path;
     229           0 :         rv = uri->GetPath(path);
     230           0 :         if (NS_FAILED(rv)) return rv;
     231             : 
     232             :         // a top-level jar directory URL is of the form jar:foo.zip!/
     233             :         // path will be of the form foo.zip!/, and its last two characters
     234             :         // will be "!/"
     235             :         //XXX this won't work correctly when the name of the directory being
     236             :         //XXX displayed ends with "!", but then again, jar: URIs don't deal
     237             :         //XXX particularly well with such directories anyway
     238           0 :         if (!StringEndsWith(path, NS_LITERAL_CSTRING("!/"))) {
     239           0 :             rv = uri->Resolve(NS_LITERAL_CSTRING(".."), parentStr);
     240           0 :             if (NS_FAILED(rv)) return rv;
     241             :         }
     242             :     }
     243             :     else {
     244             :         // default behavior for other protocols is to assume the channel's
     245             :         // URL references a directory ending in '/' -- fixup if necessary.
     246           0 :         nsAutoCString path;
     247           0 :         rv = uri->GetPath(path);
     248           0 :         if (NS_FAILED(rv)) return rv;
     249           0 :         if (baseUri.Last() != '/') {
     250           0 :             baseUri.Append('/');
     251           0 :             path.Append('/');
     252           0 :             uri->SetPath(path);
     253             :         }
     254           0 :         if (!path.EqualsLiteral("/")) {
     255           0 :             rv = uri->Resolve(NS_LITERAL_CSTRING(".."), parentStr);
     256           0 :             if (NS_FAILED(rv)) return rv;
     257             :         }
     258             :     }
     259             : 
     260             :     buffer.AppendLiteral("<style type=\"text/css\">\n"
     261             :                          ":root {\n"
     262             :                          "  font-family: sans-serif;\n"
     263             :                          "}\n"
     264             :                          "img {\n"
     265             :                          "  border: 0;\n"
     266             :                          "}\n"
     267             :                          "th {\n"
     268             :                          "  text-align: start;\n"
     269             :                          "  white-space: nowrap;\n"
     270             :                          "}\n"
     271             :                          "th > a {\n"
     272             :                          "  color: inherit;\n"
     273             :                          "}\n"
     274             :                          "table[order] > thead > tr > th {\n"
     275             :                          "  cursor: pointer;\n"
     276             :                          "}\n"
     277             :                          "table[order] > thead > tr > th::after {\n"
     278             :                          "  display: none;\n"
     279             :                          "  width: .8em;\n"
     280             :                          "  margin-inline-end: -.8em;\n"
     281             :                          "  text-align: end;\n"
     282             :                          "}\n"
     283             :                          "table[order=\"asc\"] > thead > tr > th::after {\n"
     284             :                          "  content: \"\\2193\"; /* DOWNWARDS ARROW (U+2193) */\n"
     285             :                          "}\n"
     286             :                          "table[order=\"desc\"] > thead > tr > th::after {\n"
     287             :                          "  content: \"\\2191\"; /* UPWARDS ARROW (U+2191) */\n"
     288             :                          "}\n"
     289             :                          "table[order][order-by=\"0\"] > thead > tr > th:first-child > a ,\n"
     290             :                          "table[order][order-by=\"1\"] > thead > tr > th:first-child + th > a ,\n"
     291             :                          "table[order][order-by=\"2\"] > thead > tr > th:first-child + th + th > a {\n"
     292             :                          "  text-decoration: underline;\n"
     293             :                          "}\n"
     294             :                          "table[order][order-by=\"0\"] > thead > tr > th:first-child::after ,\n"
     295             :                          "table[order][order-by=\"1\"] > thead > tr > th:first-child + th::after ,\n"
     296             :                          "table[order][order-by=\"2\"] > thead > tr > th:first-child + th + th::after {\n"
     297             :                          "  display: inline-block;\n"
     298             :                          "}\n"
     299             :                          "table.remove-hidden > tbody > tr.hidden-object {\n"
     300             :                          "  display: none;\n"
     301             :                          "}\n"
     302             :                          "td {\n"
     303             :                          "  white-space: nowrap;\n"
     304             :                          "}\n"
     305             :                          "table.ellipsis {\n"
     306             :                          "  width: 100%;\n"
     307             :                          "  table-layout: fixed;\n"
     308             :                          "  border-spacing: 0;\n"
     309             :                          "}\n"
     310             :                          "table.ellipsis > tbody > tr > td {\n"
     311             :                          "  padding: 0;\n"
     312             :                          "  overflow: hidden;\n"
     313             :                          "  text-overflow: ellipsis;\n"
     314             :                          "}\n"
     315             :                          "/* name */\n"
     316             :                          "/* name */\n"
     317             :                          "th:first-child {\n"
     318             :                          "  padding-inline-end: 2em;\n"
     319             :                          "}\n"
     320             :                          "/* size */\n"
     321             :                          "th:first-child + th {\n"
     322             :                          "  padding-inline-end: 1em;\n"
     323             :                          "}\n"
     324             :                          "td:first-child + td {\n"
     325             :                          "  text-align: end;\n"
     326             :                          "  padding-inline-end: 1em;\n"
     327             :                          "}\n"
     328             :                          "/* date */\n"
     329             :                          "td:first-child + td + td {\n"
     330             :                          "  padding-inline-start: 1em;\n"
     331             :                          "  padding-inline-end: .5em;\n"
     332             :                          "}\n"
     333             :                          "/* time */\n"
     334             :                          "td:first-child + td + td + td {\n"
     335             :                          "  padding-inline-start: .5em;\n"
     336             :                          "}\n"
     337             :                          ".symlink {\n"
     338             :                          "  font-style: italic;\n"
     339             :                          "}\n"
     340             :                          ".dir ,\n"
     341             :                          ".symlink ,\n"
     342             :                          ".file {\n"
     343             :                          "  margin-inline-start: 20px;\n"
     344             :                          "}\n"
     345             :                          ".dir::before ,\n"
     346             :                          ".file > img {\n"
     347             :                          "  margin-inline-end: 4px;\n"
     348             :                          "  margin-inline-start: -20px;\n"
     349             :                          "  max-width: 16px;\n"
     350             :                          "  max-height: 16px;\n"
     351             :                          "  vertical-align: middle;\n"
     352             :                          "}\n"
     353             :                          ".dir::before {\n"
     354             :                          "  content: url(resource://gre/res/html/folder.png);\n"
     355             :                          "}\n"
     356             :                          "</style>\n"
     357             :                          "<link rel=\"stylesheet\" media=\"screen, projection\" type=\"text/css\""
     358             :                          " href=\"chrome://global/skin/dirListing/dirListing.css\">\n"
     359             :                          "<script type=\"application/javascript\">\n"
     360             :                          "'use strict';\n"
     361             :                          "var gTable, gOrderBy, gTBody, gRows, gUI_showHidden;\n"
     362             :                          "document.addEventListener(\"DOMContentLoaded\", function() {\n"
     363             :                          "  gTable = document.getElementsByTagName(\"table\")[0];\n"
     364             :                          "  gTBody = gTable.tBodies[0];\n"
     365             :                          "  if (gTBody.rows.length < 2)\n"
     366             :                          "    return;\n"
     367             :                          "  gUI_showHidden = document.getElementById(\"UI_showHidden\");\n"
     368             :                          "  var headCells = gTable.tHead.rows[0].cells,\n"
     369             :                          "      hiddenObjects = false;\n"
     370             :                          "  function rowAction(i) {\n"
     371             :                          "    return function(event) {\n"
     372             :                          "      event.preventDefault();\n"
     373             :                          "      orderBy(i);\n"
     374             :                          "    }\n"
     375             :                          "  }\n"
     376             :                          "  for (var i = headCells.length - 1; i >= 0; i--) {\n"
     377             :                          "    var anchor = document.createElement(\"a\");\n"
     378             :                          "    anchor.href = \"\";\n"
     379             :                          "    anchor.appendChild(headCells[i].firstChild);\n"
     380             :                          "    headCells[i].appendChild(anchor);\n"
     381             :                          "    headCells[i].addEventListener(\"click\", rowAction(i), true);\n"
     382             :                          "  }\n"
     383             :                          "  if (gUI_showHidden) {\n"
     384             :                          "    gRows = Array.slice(gTBody.rows);\n"
     385             :                          "    hiddenObjects = gRows.some(row => row.className == \"hidden-object\");\n"
     386             :                          "  }\n"
     387             :                          "  gTable.setAttribute(\"order\", \"\");\n"
     388             :                          "  if (hiddenObjects) {\n"
     389             :                          "    gUI_showHidden.style.display = \"block\";\n"
     390             :                          "    updateHidden();\n"
     391             :                          "  }\n"
     392             :                          "}, \"false\");\n"
     393             :                          "function compareRows(rowA, rowB) {\n"
     394             :                          "  var a = rowA.cells[gOrderBy].getAttribute(\"sortable-data\") || \"\";\n"
     395             :                          "  var b = rowB.cells[gOrderBy].getAttribute(\"sortable-data\") || \"\";\n"
     396             :                          "  var intA = +a;\n"
     397             :                          "  var intB = +b;\n"
     398             :                          "  if (a == intA && b == intB) {\n"
     399             :                          "    a = intA;\n"
     400             :                          "    b = intB;\n"
     401             :                          "  } else {\n"
     402             :                          "    a = a.toLowerCase();\n"
     403             :                          "    b = b.toLowerCase();\n"
     404             :                          "  }\n"
     405             :                          "  if (a < b)\n"
     406             :                          "    return -1;\n"
     407             :                          "  if (a > b)\n"
     408             :                          "    return 1;\n"
     409             :                          "  return 0;\n"
     410             :                          "}\n"
     411             :                          "function orderBy(column) {\n"
     412             :                          "  if (!gRows)\n"
     413             :                          "    gRows = Array.slice(gTBody.rows);\n"
     414             :                          "  var order;\n"
     415             :                          "  if (gOrderBy == column) {\n"
     416             :                          "    order = gTable.getAttribute(\"order\") == \"asc\" ? \"desc\" : \"asc\";\n"
     417             :                          "  } else {\n"
     418             :                          "    order = \"asc\";\n"
     419             :                          "    gOrderBy = column;\n"
     420             :                          "    gTable.setAttribute(\"order-by\", column);\n"
     421             :                          "    gRows.sort(compareRows);\n"
     422             :                          "  }\n"
     423             :                          "  gTable.removeChild(gTBody);\n"
     424             :                          "  gTable.setAttribute(\"order\", order);\n"
     425             :                          "  if (order == \"asc\")\n"
     426             :                          "    for (var i = 0; i < gRows.length; i++)\n"
     427             :                          "      gTBody.appendChild(gRows[i]);\n"
     428             :                          "  else\n"
     429             :                          "    for (var i = gRows.length - 1; i >= 0; i--)\n"
     430             :                          "      gTBody.appendChild(gRows[i]);\n"
     431             :                          "  gTable.appendChild(gTBody);\n"
     432             :                          "}\n"
     433             :                          "function updateHidden() {\n"
     434             :                          "  gTable.className = gUI_showHidden.getElementsByTagName(\"input\")[0].checked ?\n"
     435             :                          "                     \"\" :\n"
     436             :                          "                     \"remove-hidden\";\n"
     437             :                          "}\n"
     438           0 :                          "</script>\n");
     439             : 
     440           0 :     buffer.AppendLiteral("<link rel=\"icon\" type=\"image/png\" href=\"");
     441           0 :     nsCOMPtr<nsIURI> innerUri = NS_GetInnermostURI(uri);
     442           0 :     if (!innerUri)
     443           0 :         return NS_ERROR_UNEXPECTED;
     444           0 :     nsCOMPtr<nsIFileURL> fileURL(do_QueryInterface(innerUri));
     445             :     //XXX bug 388553: can't use skinnable icons here due to security restrictions
     446           0 :     if (fileURL) {
     447             :         buffer.AppendLiteral("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB"
     448             :                              "AAAAAQCAYAAAAf8%2F9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
     449             :                              "ZSBJbWFnZVJlYWR5ccllPAAAAjFJREFUeNqsU8uOElEQPffR"
     450             :                              "3XQ3ONASdBJCSBxHos5%2B3Bg3rvkCv8PElS78gPkO%2FATj"
     451             :                              "QoUdO2ftrJiRh6aneTb9sOpC4weMN6lcuFV16pxDIfI8x12O"
     452             :                              "YIDhcPiu2Wx%2B%2FHF5CW1Z6Jyegt%2FTNEWSJIjjGFEUIQ"
     453             :                              "xDrFYrWFSzXC4%2FdLvd95pRKpXKy%2BpRFZ7nwaWo1%2BsG"
     454             :                              "nQG2260BKJfLKJVKGI1GEEJw7ateryd0v993W63WEwjgxfn5"
     455             :                              "obGYzgCbzcaEbdsIggDj8Riu6z6iUk9SYZMSx8W0LMsM%2FS"
     456             :                              "KK75xnJlIq80anQXdbEp0OhcPJ0eiaJnGRMEyyPDsAKKUM9c"
     457             :                              "lkYoDo3SZJzzSdp0VSKYmfV1co%2Bz580kw5KDIM8RbRfEnU"
     458             :                              "f1HzxtQyMAGcaGruTKczMzEIaqhKifV6jd%2BzGQQB5llunF"
     459             :                              "%2FM52BizC2K5sYPYvZcu653tjOM9O93wnYc08gmkgg4VAxi"
     460             :                              "xfqFUJT36AYBZGd6PJkFCZnnlBxMp38gqIgLpZB0y4Nph18l"
     461             :                              "yWh5FFbrOSxbl3V4G%2BVB7T4ajYYxTyuLtO%2BCvWGgJE1M"
     462             :                              "c7JNsJEhvgw%2FQV4fo%2F24nbEsX2u1d5sVyn8sJO0ZAQiI"
     463             :                              "YnFh%2BxrfLz%2Fj29cBS%2FO14zg3i8XigW3ZkErDtmKoeM"
     464             :                              "%2BAJGRMnXeEPGKf0nCD1ydvkDzU9Jbc6OpR7WIw6L8lQ%2B"
     465             :                              "4pQ1%2FlPF0RGM9Ns91Wmptk0GfB4EJkt77vXYj%2F8m%2B8"
     466           0 :                              "y%2FkrwABHbz2H9V68DQAAAABJRU5ErkJggg%3D%3D");
     467             :     } else {
     468             :         buffer.AppendLiteral("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB"
     469             :                              "AAAAAQCAYAAAAf8%2F9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
     470             :                              "ZSBJbWFnZVJlYWR5ccllPAAAAeBJREFUeNqcU81O20AQ%2Ft"
     471             :                              "Z2AgQSYQRqL1UPVG2hAUQkxLEStz4DrXpLpD5Drz31Cajax%"
     472             :                              "2Bghhx6qHIJURBTxIwQRwopCBbZjHMcOTrzermPipsSt1Iw0"
     473             :                              "3p3ZmW%2B%2B2R0TxhgOD34wjCHZlQ0iDYz9yvEfhxMTCYhE"
     474             :                              "QDIZhkxKd2sqzX2TOD2vBQCQhpPefng1ZP2dVPlLLdpL8SEM"
     475             :                              "cxng%2Fbs0RIHhtgs4twxOh%2BHjZxvzDx%2F3GQQiDFISiR"
     476             :                              "BLFMPKTRMollzcWECrDVhtxtdRVsL9youPxGj%2FbdfFlUZh"
     477             :                              "tDyYbYqWRUdai1oQRZ5oHeHl2gNM%2B01Uqio8RlH%2Bnsaz"
     478             :                              "JzNwXcq1B%2BiXPHprlEEymeBfXs1w8XxxihfyuXqoHqpoGj"
     479             :                              "ZM04bddgG%2F9%2B8WGj87qDdsrK9m%2BoA%2BpbhQTDh2l1"
     480             :                              "%2Bi2weNbSHMZyjvNXmVbqh9Fj5Oz27uEoP%2BSTxANruJs9"
     481             :                              "L%2FT6P0ewqPx5nmiAG5f6AoCtN1PbJzuRyJAyDBzzSQYvEr"
     482             :                              "f06yYxhGXlEa8H2KVGoasjwLx3Ewk858opQWXm%2B%2Fib9E"
     483             :                              "QrBzclLLLy89xYvlpchvtixcX6uo1y%2FzsiwHrkIsgKbp%2"
     484             :                              "BYWFOWicuqppoNTnStHzPFCPQhBEBOyGAX4JMADFetubi4BS"
     485           0 :                              "YAAAAABJRU5ErkJggg%3D%3D");
     486             :     }
     487           0 :     buffer.AppendLiteral("\">\n<title>");
     488             : 
     489             :     // Everything needs to end in a /,
     490             :     // otherwise we end up linking to file:///foo/dirfile
     491             : 
     492           0 :     if (!mTextToSubURI) {
     493           0 :         mTextToSubURI = do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
     494           0 :         if (NS_FAILED(rv)) return rv;
     495             :     }
     496             : 
     497           0 :     nsXPIDLCString encoding;
     498           0 :     rv = uri->GetOriginCharset(encoding);
     499           0 :     if (NS_FAILED(rv)) return rv;
     500           0 :     if (encoding.IsEmpty()) {
     501           0 :       encoding.AssignLiteral("UTF-8");
     502             :     }
     503             : 
     504           0 :     nsAutoString unEscapeSpec;
     505           0 :     rv = mTextToSubURI->UnEscapeAndConvert(encoding, titleUri, unEscapeSpec);
     506             :     // unescape may fail because
     507             :     // 1. file URL may be encoded in platform charset for backward compatibility
     508             :     // 2. query part may not be encoded in UTF-8 (see bug 261929)
     509             :     // so try the platform's default if this is file url
     510           0 :     if (NS_FAILED(rv) && isSchemeFile) {
     511           0 :         nsCOMPtr<nsIPlatformCharset> platformCharset(do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv));
     512           0 :         NS_ENSURE_SUCCESS(rv, rv);
     513           0 :         nsAutoCString charset;
     514           0 :         rv = platformCharset->GetCharset(kPlatformCharsetSel_FileName, charset);
     515           0 :         NS_ENSURE_SUCCESS(rv, rv);
     516             : 
     517           0 :         rv = mTextToSubURI->UnEscapeAndConvert(charset, titleUri, unEscapeSpec);
     518             :     }
     519           0 :     if (NS_FAILED(rv)) return rv;
     520             : 
     521           0 :     nsXPIDLString htmlEscSpec;
     522           0 :     htmlEscSpec.Adopt(nsEscapeHTML2(unEscapeSpec.get(),
     523           0 :                                     unEscapeSpec.Length()));
     524             : 
     525           0 :     nsXPIDLString title;
     526             :     const char16_t* formatTitle[] = {
     527           0 :         htmlEscSpec.get()
     528           0 :     };
     529             : 
     530           0 :     rv = mBundle->FormatStringFromName(u"DirTitle",
     531             :                                        formatTitle,
     532             :                                        sizeof(formatTitle)/sizeof(char16_t*),
     533           0 :                                        getter_Copies(title));
     534           0 :     if (NS_FAILED(rv)) return rv;
     535             : 
     536             :     // we want to convert string bundle to NCR
     537             :     // to ensure they're shown in any charsets
     538           0 :     AppendNonAsciiToNCR(title, buffer);
     539             : 
     540           0 :     buffer.AppendLiteral("</title>\n");
     541             : 
     542             :     // If there is a quote character in the baseUri, then
     543             :     // lets not add a base URL.  The reason for this is that
     544             :     // if we stick baseUri containing a quote into a quoted
     545             :     // string, the quote character will prematurely close
     546             :     // the base href string.  This is a fall-back check;
     547             :     // that's why it is OK to not use a base rather than
     548             :     // trying to play nice and escaping the quotes.  See bug
     549             :     // 358128.
     550             : 
     551           0 :     if (!baseUri.Contains('"'))
     552             :     {
     553             :         // Great, the baseUri does not contain a char that
     554             :         // will prematurely close the string.  Go ahead an
     555             :         // add a base href, but only do so if we're not
     556             :         // dealing with a resource URI.
     557           0 :         if (!isResource) {
     558           0 :             buffer.AppendLiteral("<base href=\"");
     559           0 :             nsAdoptingCString htmlEscapedUri(nsEscapeHTML(baseUri.get()));
     560           0 :             buffer.Append(htmlEscapedUri);
     561           0 :             buffer.AppendLiteral("\" />\n");
     562             :         }
     563             :     }
     564             :     else
     565             :     {
     566           0 :         NS_ERROR("broken protocol handler didn't escape double-quote.");
     567             :     }
     568             : 
     569           0 :     nsCString direction(NS_LITERAL_CSTRING("ltr"));
     570           0 :     if (LocaleService::GetInstance()->IsAppLocaleRTL()) {
     571           0 :       direction.AssignLiteral("rtl");
     572             :     }
     573             : 
     574           0 :     buffer.AppendLiteral("</head>\n<body dir=\"");
     575           0 :     buffer.Append(direction);
     576           0 :     buffer.AppendLiteral("\">\n<h1>");
     577             : 
     578             :     const char16_t* formatHeading[] = {
     579           0 :         htmlEscSpec.get()
     580           0 :     };
     581             : 
     582           0 :     rv = mBundle->FormatStringFromName(u"DirTitle",
     583             :                                        formatHeading,
     584             :                                        sizeof(formatHeading)/sizeof(char16_t*),
     585           0 :                                        getter_Copies(title));
     586           0 :     if (NS_FAILED(rv)) return rv;
     587             : 
     588           0 :     AppendNonAsciiToNCR(title, buffer);
     589           0 :     buffer.AppendLiteral("</h1>\n");
     590             : 
     591           0 :     if (!parentStr.IsEmpty()) {
     592           0 :         nsXPIDLString parentText;
     593           0 :         rv = mBundle->GetStringFromName(u"DirGoUp",
     594           0 :                                         getter_Copies(parentText));
     595           0 :         if (NS_FAILED(rv)) return rv;
     596             : 
     597           0 :         buffer.AppendLiteral("<p id=\"UI_goUp\"><a class=\"up\" href=\"");
     598             : 
     599           0 :         nsAdoptingCString htmlParentStr(nsEscapeHTML(parentStr.get()));
     600           0 :         buffer.Append(htmlParentStr);
     601           0 :         buffer.AppendLiteral("\">");
     602           0 :         AppendNonAsciiToNCR(parentText, buffer);
     603           0 :         buffer.AppendLiteral("</a></p>\n");
     604             :     }
     605             : 
     606           0 :     if (isSchemeFile) {
     607           0 :         nsXPIDLString showHiddenText;
     608           0 :         rv = mBundle->GetStringFromName(u"ShowHidden",
     609           0 :                                         getter_Copies(showHiddenText));
     610           0 :         if (NS_FAILED(rv)) return rv;
     611             : 
     612           0 :         buffer.AppendLiteral("<p id=\"UI_showHidden\" style=\"display:none\"><label><input type=\"checkbox\" checked onchange=\"updateHidden()\">");
     613           0 :         AppendNonAsciiToNCR(showHiddenText, buffer);
     614           0 :         buffer.AppendLiteral("</label></p>\n");
     615             :     }
     616             : 
     617           0 :     buffer.AppendLiteral("<table>\n");
     618             : 
     619           0 :     nsXPIDLString columnText;
     620             : 
     621             :     buffer.AppendLiteral(" <thead>\n"
     622             :                          "  <tr>\n"
     623           0 :                          "   <th>");
     624             : 
     625           0 :     rv = mBundle->GetStringFromName(u"DirColName",
     626           0 :                                     getter_Copies(columnText));
     627           0 :     if (NS_FAILED(rv)) return rv;
     628           0 :     AppendNonAsciiToNCR(columnText, buffer);
     629             :     buffer.AppendLiteral("</th>\n"
     630           0 :                          "   <th>");
     631             : 
     632           0 :     rv = mBundle->GetStringFromName(u"DirColSize",
     633           0 :                                     getter_Copies(columnText));
     634           0 :     if (NS_FAILED(rv)) return rv;
     635           0 :     AppendNonAsciiToNCR(columnText, buffer);
     636             :     buffer.AppendLiteral("</th>\n"
     637           0 :                          "   <th colspan=\"2\">");
     638             : 
     639           0 :     rv = mBundle->GetStringFromName(u"DirColMTime",
     640           0 :                                     getter_Copies(columnText));
     641           0 :     if (NS_FAILED(rv)) return rv;
     642           0 :     AppendNonAsciiToNCR(columnText, buffer);
     643             :     buffer.AppendLiteral("</th>\n"
     644             :                          "  </tr>\n"
     645           0 :                          " </thead>\n");
     646           0 :     buffer.AppendLiteral(" <tbody>\n");
     647             : 
     648           0 :     aBuffer = buffer;
     649           0 :     return rv;
     650             : }
     651             : 
     652             : NS_IMETHODIMP
     653           0 : nsIndexedToHTML::OnStopRequest(nsIRequest* request, nsISupports *aContext,
     654             :                                nsresult aStatus) {
     655           0 :     if (NS_SUCCEEDED(aStatus)) {
     656           0 :         nsCString buffer;
     657           0 :         buffer.AssignLiteral("</tbody></table></body></html>\n");
     658             : 
     659           0 :         aStatus = SendToListener(request, aContext, buffer);
     660             :     }
     661             : 
     662           0 :     mParser->OnStopRequest(request, aContext, aStatus);
     663           0 :     mParser = nullptr;
     664             : 
     665           0 :     return mListener->OnStopRequest(request, aContext, aStatus);
     666             : }
     667             : 
     668             : nsresult
     669           0 : nsIndexedToHTML::SendToListener(nsIRequest* aRequest, nsISupports *aContext, const nsACString &aBuffer)
     670             : {
     671           0 :     nsCOMPtr<nsIInputStream> inputData;
     672           0 :     nsresult rv = NS_NewCStringInputStream(getter_AddRefs(inputData), aBuffer);
     673           0 :     NS_ENSURE_SUCCESS(rv, rv);
     674           0 :     return mListener->OnDataAvailable(aRequest, aContext,
     675           0 :                                       inputData, 0, aBuffer.Length());
     676             : }
     677             : 
     678             : NS_IMETHODIMP
     679           0 : nsIndexedToHTML::OnDataAvailable(nsIRequest *aRequest,
     680             :                                  nsISupports *aCtxt,
     681             :                                  nsIInputStream* aInput,
     682             :                                  uint64_t aOffset,
     683             :                                  uint32_t aCount) {
     684           0 :     return mParser->OnDataAvailable(aRequest, aCtxt, aInput, aOffset, aCount);
     685             : }
     686             : 
     687             : NS_IMETHODIMP
     688           0 : nsIndexedToHTML::OnIndexAvailable(nsIRequest *aRequest,
     689             :                                   nsISupports *aCtxt,
     690             :                                   nsIDirIndex *aIndex) {
     691             :     nsresult rv;
     692           0 :     if (!aIndex)
     693           0 :         return NS_ERROR_NULL_POINTER;
     694             : 
     695           0 :     nsCString pushBuffer;
     696           0 :     pushBuffer.AppendLiteral("<tr");
     697             : 
     698             :     // We don't know the file's character set yet, so retrieve the raw bytes
     699             :     // which will be decoded by the HTML parser.
     700           0 :     nsXPIDLCString loc;
     701           0 :     aIndex->GetLocation(getter_Copies(loc));
     702             : 
     703             :     // Adjust the length in case unescaping shortened the string.
     704           0 :     loc.Truncate(nsUnescapeCount(loc.BeginWriting()));
     705             : 
     706           0 :     if (loc.IsEmpty()) {
     707           0 :         return NS_ERROR_ILLEGAL_VALUE;
     708             :     }
     709           0 :     if (loc.First() == char16_t('.'))
     710           0 :         pushBuffer.AppendLiteral(" class=\"hidden-object\"");
     711             : 
     712           0 :     pushBuffer.AppendLiteral(">\n <td sortable-data=\"");
     713             : 
     714             :     // The sort key is the name of the item, prepended by either 0, 1 or 2
     715             :     // in order to group items.
     716             :     uint32_t type;
     717           0 :     aIndex->GetType(&type);
     718           0 :     switch (type) {
     719             :         case nsIDirIndex::TYPE_SYMLINK:
     720           0 :             pushBuffer.Append('0');
     721           0 :             break;
     722             :         case nsIDirIndex::TYPE_DIRECTORY:
     723           0 :             pushBuffer.Append('1');
     724           0 :             break;
     725             :         default:
     726           0 :             pushBuffer.Append('2');
     727           0 :             break;
     728             :     }
     729           0 :     nsAdoptingCString escaped(nsEscapeHTML(loc));
     730           0 :     pushBuffer.Append(escaped);
     731             : 
     732           0 :     pushBuffer.AppendLiteral("\"><table class=\"ellipsis\"><tbody><tr><td><a class=\"");
     733           0 :     switch (type) {
     734             :         case nsIDirIndex::TYPE_DIRECTORY:
     735           0 :             pushBuffer.AppendLiteral("dir");
     736           0 :             break;
     737             :         case nsIDirIndex::TYPE_SYMLINK:
     738           0 :             pushBuffer.AppendLiteral("symlink");
     739           0 :             break;
     740             :         default:
     741           0 :             pushBuffer.AppendLiteral("file");
     742           0 :             break;
     743             :     }
     744             : 
     745           0 :     pushBuffer.AppendLiteral("\" href=\"");
     746             : 
     747             :     // need to escape links
     748           0 :     nsAutoCString locEscaped;
     749             : 
     750             :     // Adding trailing slash helps to recognize whether the URL points to a file
     751             :     // or a directory (bug #214405).
     752           0 :     if ((type == nsIDirIndex::TYPE_DIRECTORY) && (loc.Last() != '/')) {
     753           0 :         loc.Append('/');
     754             :     }
     755             : 
     756             :     // now minimally re-escape the location...
     757             :     uint32_t escFlags;
     758             :     // for some protocols, we expect the location to be absolute.
     759             :     // if so, and if the location indeed appears to be a valid URI, then go
     760             :     // ahead and treat it like one.
     761             : 
     762           0 :     nsAutoCString scheme;
     763           0 :     if (mExpectAbsLoc &&
     764           0 :         NS_SUCCEEDED(net_ExtractURLScheme(loc, scheme))) {
     765             :         // escape as absolute
     766           0 :         escFlags = esc_Forced | esc_AlwaysCopy | esc_Minimal;
     767             :     }
     768             :     else {
     769             :         // escape as relative
     770             :         // esc_Directory is needed because directories have a trailing slash.
     771             :         // Without it, the trailing '/' will be escaped, and links from within
     772             :         // that directory will be incorrect
     773           0 :         escFlags = esc_Forced | esc_AlwaysCopy | esc_FileBaseName | esc_Colon | esc_Directory;
     774             :     }
     775           0 :     NS_EscapeURL(loc.get(), loc.Length(), escFlags, locEscaped);
     776             :     // esc_Directory does not escape the semicolons, so if a filename
     777             :     // contains semicolons we need to manually escape them.
     778             :     // This replacement should be removed in bug #473280
     779           0 :     locEscaped.ReplaceSubstring(";", "%3b");
     780           0 :     nsAdoptingCString htmlEscapedURL(nsEscapeHTML(locEscaped.get()));
     781           0 :     pushBuffer.Append(htmlEscapedURL);
     782             : 
     783           0 :     pushBuffer.AppendLiteral("\">");
     784             : 
     785           0 :     if (type == nsIDirIndex::TYPE_FILE || type == nsIDirIndex::TYPE_UNKNOWN) {
     786           0 :         pushBuffer.AppendLiteral("<img src=\"moz-icon://");
     787           0 :         int32_t lastDot = locEscaped.RFindChar('.');
     788           0 :         if (lastDot != kNotFound) {
     789           0 :             locEscaped.Cut(0, lastDot);
     790           0 :             nsAdoptingCString htmlFileExt(nsEscapeHTML(locEscaped.get()));
     791           0 :             pushBuffer.Append(htmlFileExt);
     792             :         } else {
     793           0 :             pushBuffer.AppendLiteral("unknown");
     794             :         }
     795           0 :         pushBuffer.AppendLiteral("?size=16\" alt=\"");
     796             : 
     797           0 :         nsXPIDLString altText;
     798           0 :         rv = mBundle->GetStringFromName(u"DirFileLabel",
     799           0 :                                         getter_Copies(altText));
     800           0 :         if (NS_FAILED(rv)) return rv;
     801           0 :         AppendNonAsciiToNCR(altText, pushBuffer);
     802           0 :         pushBuffer.AppendLiteral("\">");
     803             :     }
     804             : 
     805           0 :     pushBuffer.Append(escaped);
     806           0 :     pushBuffer.AppendLiteral("</a></td></tr></tbody></table></td>\n <td");
     807             : 
     808           0 :     if (type == nsIDirIndex::TYPE_DIRECTORY || type == nsIDirIndex::TYPE_SYMLINK) {
     809           0 :         pushBuffer.Append('>');
     810             :     } else {
     811             :         int64_t size;
     812           0 :         aIndex->GetSize(&size);
     813             : 
     814           0 :         if (uint64_t(size) != UINT64_MAX) {
     815           0 :             pushBuffer.AppendLiteral(" sortable-data=\"");
     816           0 :             pushBuffer.AppendInt(size);
     817           0 :             pushBuffer.AppendLiteral("\">");
     818           0 :             nsAutoCString sizeString;
     819           0 :             FormatSizeString(size, sizeString);
     820           0 :             pushBuffer.Append(sizeString);
     821             :         } else {
     822           0 :             pushBuffer.Append('>');
     823             :         }
     824             :     }
     825           0 :     pushBuffer.AppendLiteral("</td>\n <td");
     826             : 
     827             :     PRTime t;
     828           0 :     aIndex->GetLastModified(&t);
     829             : 
     830           0 :     if (t == -1LL) {
     831           0 :         pushBuffer.AppendLiteral("></td>\n <td>");
     832             :     } else {
     833           0 :         pushBuffer.AppendLiteral(" sortable-data=\"");
     834           0 :         pushBuffer.AppendInt(static_cast<int64_t>(t));
     835           0 :         pushBuffer.AppendLiteral("\">");
     836           0 :         nsAutoString formatted;
     837             :         mozilla::DateTimeFormat::FormatPRTime(kDateFormatShort,
     838             :                                               kTimeFormatNone,
     839             :                                               t,
     840           0 :                                               formatted);
     841           0 :         AppendNonAsciiToNCR(formatted, pushBuffer);
     842           0 :         pushBuffer.AppendLiteral("</td>\n <td>");
     843             :         mozilla::DateTimeFormat::FormatPRTime(kDateFormatNone,
     844             :                                               kTimeFormatSeconds,
     845             :                                               t,
     846           0 :                                               formatted);
     847             :         // use NCR to show date in any doc charset
     848           0 :         AppendNonAsciiToNCR(formatted, pushBuffer);
     849             :     }
     850             : 
     851           0 :     pushBuffer.AppendLiteral("</td>\n</tr>");
     852             : 
     853           0 :     return SendToListener(aRequest, aCtxt, pushBuffer);
     854             : }
     855             : 
     856             : NS_IMETHODIMP
     857           0 : nsIndexedToHTML::OnInformationAvailable(nsIRequest *aRequest,
     858             :                                         nsISupports *aCtxt,
     859             :                                         const nsAString& aInfo) {
     860           0 :     nsAutoCString pushBuffer;
     861           0 :     nsAdoptingString escaped(nsEscapeHTML2(PromiseFlatString(aInfo).get()));
     862           0 :     if (!escaped)
     863           0 :         return NS_ERROR_OUT_OF_MEMORY;
     864           0 :     pushBuffer.AppendLiteral("<tr>\n <td>");
     865             :     // escaped is provided in Unicode, so write hex NCRs as necessary
     866             :     // to prevent the HTML parser from applying a character set.
     867           0 :     AppendNonAsciiToNCR(escaped, pushBuffer);
     868           0 :     pushBuffer.AppendLiteral("</td>\n <td></td>\n <td></td>\n <td></td>\n</tr>\n");
     869             : 
     870           0 :     return SendToListener(aRequest, aCtxt, pushBuffer);
     871             : }
     872             : 
     873           0 : void nsIndexedToHTML::FormatSizeString(int64_t inSize, nsCString& outSizeString)
     874             : {
     875           0 :     outSizeString.Truncate();
     876           0 :     if (inSize > int64_t(0)) {
     877             :         // round up to the nearest Kilobyte
     878           0 :         int64_t  upperSize = (inSize + int64_t(1023)) / int64_t(1024);
     879           0 :         outSizeString.AppendInt(upperSize);
     880           0 :         outSizeString.AppendLiteral(" KB");
     881             :     }
     882           0 : }
     883             : 
     884           0 : nsIndexedToHTML::nsIndexedToHTML() {
     885           0 : }
     886             : 
     887           0 : nsIndexedToHTML::~nsIndexedToHTML() {
     888           0 : }

Generated by: LCOV version 1.13