netwerk/streamconv/converters/nsIndexedToHTML.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/netwerk/streamconv/converters/nsIndexedToHTML.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,880 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "nsIndexedToHTML.h"
    1.10 +#include "mozilla/dom/EncodingUtils.h"
    1.11 +#include "nsNetUtil.h"
    1.12 +#include "netCore.h"
    1.13 +#include "nsStringStream.h"
    1.14 +#include "nsIFileURL.h"
    1.15 +#include "nsEscape.h"
    1.16 +#include "nsIDirIndex.h"
    1.17 +#include "nsDateTimeFormatCID.h"
    1.18 +#include "nsURLHelper.h"
    1.19 +#include "nsIPlatformCharset.h"
    1.20 +#include "nsIPrefService.h"
    1.21 +#include "nsIPrefBranch.h"
    1.22 +#include "nsIPrefLocalizedString.h"
    1.23 +#include "nsIChromeRegistry.h"
    1.24 +#include "nsICharsetConverterManager.h"
    1.25 +#include "nsIDateTimeFormat.h"
    1.26 +#include "nsIStringBundle.h"
    1.27 +#include "nsITextToSubURI.h"
    1.28 +#include "nsXPIDLString.h"
    1.29 +#include <algorithm>
    1.30 +
    1.31 +NS_IMPL_ISUPPORTS(nsIndexedToHTML,
    1.32 +                  nsIDirIndexListener,
    1.33 +                  nsIStreamConverter,
    1.34 +                  nsIRequestObserver,
    1.35 +                  nsIStreamListener)
    1.36 +
    1.37 +static void AppendNonAsciiToNCR(const nsAString& in, nsCString& out)
    1.38 +{
    1.39 +  nsAString::const_iterator start, end;
    1.40 +
    1.41 +  in.BeginReading(start);
    1.42 +  in.EndReading(end);
    1.43 +
    1.44 +  while (start != end) {
    1.45 +    if (*start < 128) {
    1.46 +      out.Append(*start++);
    1.47 +    } else {
    1.48 +      out.AppendLiteral("&#x");
    1.49 +      out.AppendInt(*start++, 16);
    1.50 +      out.Append(';');
    1.51 +    }
    1.52 +  }
    1.53 +}
    1.54 +
    1.55 +nsresult
    1.56 +nsIndexedToHTML::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult) {
    1.57 +    nsresult rv;
    1.58 +    if (aOuter)
    1.59 +        return NS_ERROR_NO_AGGREGATION;
    1.60 +    
    1.61 +    nsIndexedToHTML* _s = new nsIndexedToHTML();
    1.62 +    if (_s == nullptr)
    1.63 +        return NS_ERROR_OUT_OF_MEMORY;
    1.64 +    
    1.65 +    rv = _s->QueryInterface(aIID, aResult);
    1.66 +    return rv;
    1.67 +}
    1.68 +
    1.69 +nsresult
    1.70 +nsIndexedToHTML::Init(nsIStreamListener* aListener) {
    1.71 +    nsresult rv = NS_OK;
    1.72 +
    1.73 +    mListener = aListener;
    1.74 +
    1.75 +    mDateTime = do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID, &rv);
    1.76 +    if (NS_FAILED(rv))
    1.77 +      return rv;
    1.78 +
    1.79 +    nsCOMPtr<nsIStringBundleService> sbs =
    1.80 +        do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
    1.81 +    if (NS_FAILED(rv)) return rv;
    1.82 +    rv = sbs->CreateBundle(NECKO_MSGS_URL, getter_AddRefs(mBundle));
    1.83 +
    1.84 +    mExpectAbsLoc = false;
    1.85 +
    1.86 +    return rv;
    1.87 +}
    1.88 +
    1.89 +NS_IMETHODIMP
    1.90 +nsIndexedToHTML::Convert(nsIInputStream* aFromStream,
    1.91 +                         const char* aFromType,
    1.92 +                         const char* aToType,
    1.93 +                         nsISupports* aCtxt,
    1.94 +                         nsIInputStream** res) {
    1.95 +    return NS_ERROR_NOT_IMPLEMENTED;
    1.96 +}
    1.97 +
    1.98 +NS_IMETHODIMP
    1.99 +nsIndexedToHTML::AsyncConvertData(const char *aFromType,
   1.100 +                                  const char *aToType,
   1.101 +                                  nsIStreamListener *aListener,
   1.102 +                                  nsISupports *aCtxt) {
   1.103 +    return Init(aListener);
   1.104 +}
   1.105 +
   1.106 +NS_IMETHODIMP
   1.107 +nsIndexedToHTML::OnStartRequest(nsIRequest* request, nsISupports *aContext) {
   1.108 +    nsCString buffer;
   1.109 +    nsresult rv = DoOnStartRequest(request, aContext, buffer);
   1.110 +    if (NS_FAILED(rv)) {
   1.111 +        request->Cancel(rv);
   1.112 +    }
   1.113 +    
   1.114 +    rv = mListener->OnStartRequest(request, aContext);
   1.115 +    if (NS_FAILED(rv)) return rv;
   1.116 +
   1.117 +    // The request may have been canceled, and if that happens, we want to
   1.118 +    // suppress calls to OnDataAvailable.
   1.119 +    request->GetStatus(&rv);
   1.120 +    if (NS_FAILED(rv)) return rv;
   1.121 +
   1.122 +    // Push our buffer to the listener.
   1.123 +
   1.124 +    rv = SendToListener(request, aContext, buffer);
   1.125 +    return rv;
   1.126 +}
   1.127 +
   1.128 +nsresult
   1.129 +nsIndexedToHTML::DoOnStartRequest(nsIRequest* request, nsISupports *aContext,
   1.130 +                                  nsCString& aBuffer) {
   1.131 +    nsresult rv;
   1.132 +
   1.133 +    nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
   1.134 +    nsCOMPtr<nsIURI> uri;
   1.135 +    rv = channel->GetURI(getter_AddRefs(uri));
   1.136 +    if (NS_FAILED(rv)) return rv;
   1.137 +
   1.138 +    channel->SetContentType(NS_LITERAL_CSTRING("text/html"));
   1.139 +
   1.140 +    mParser = do_CreateInstance("@mozilla.org/dirIndexParser;1",&rv);
   1.141 +    if (NS_FAILED(rv)) return rv;
   1.142 +
   1.143 +    rv = mParser->SetListener(this);
   1.144 +    if (NS_FAILED(rv)) return rv;
   1.145 +    
   1.146 +    rv = mParser->OnStartRequest(request, aContext);
   1.147 +    if (NS_FAILED(rv)) return rv;
   1.148 +
   1.149 +    nsAutoCString baseUri, titleUri;
   1.150 +    rv = uri->GetAsciiSpec(baseUri);
   1.151 +    if (NS_FAILED(rv)) return rv;
   1.152 +    titleUri = baseUri;
   1.153 +
   1.154 +    nsCString parentStr;
   1.155 +
   1.156 +    nsCString buffer;
   1.157 +    buffer.AppendLiteral("<!DOCTYPE html>\n<html>\n<head>\n");
   1.158 +
   1.159 +    // XXX - should be using the 300: line from the parser.
   1.160 +    // We can't guarantee that that comes before any entry, so we'd have to
   1.161 +    // buffer, and do other painful stuff.
   1.162 +    // I'll deal with this when I make the changes to handle welcome messages
   1.163 +    // The .. stuff should also come from the lower level protocols, but that
   1.164 +    // would muck up the XUL display
   1.165 +    // - bbaetz
   1.166 +
   1.167 +    bool isScheme = false;
   1.168 +    bool isSchemeFile = false;
   1.169 +    if (NS_SUCCEEDED(uri->SchemeIs("ftp", &isScheme)) && isScheme) {
   1.170 +
   1.171 +        // strip out the password here, so it doesn't show in the page title
   1.172 +        // This is done by the 300: line generation in ftp, but we don't use
   1.173 +        // that - see above
   1.174 +        
   1.175 +        nsAutoCString pw;
   1.176 +        rv = uri->GetPassword(pw);
   1.177 +        if (NS_FAILED(rv)) return rv;
   1.178 +        if (!pw.IsEmpty()) {
   1.179 +             nsCOMPtr<nsIURI> newUri;
   1.180 +             rv = uri->Clone(getter_AddRefs(newUri));
   1.181 +             if (NS_FAILED(rv)) return rv;
   1.182 +             rv = newUri->SetPassword(EmptyCString());
   1.183 +             if (NS_FAILED(rv)) return rv;
   1.184 +             rv = newUri->GetAsciiSpec(titleUri);
   1.185 +             if (NS_FAILED(rv)) return rv;
   1.186 +        }
   1.187 +
   1.188 +        nsAutoCString path;
   1.189 +        rv = uri->GetPath(path);
   1.190 +        if (NS_FAILED(rv)) return rv;
   1.191 +
   1.192 +        if (!path.EqualsLiteral("//") && !path.LowerCaseEqualsLiteral("/%2f")) {
   1.193 +            rv = uri->Resolve(NS_LITERAL_CSTRING(".."),parentStr);
   1.194 +            if (NS_FAILED(rv)) return rv;
   1.195 +        }
   1.196 +    } else if (NS_SUCCEEDED(uri->SchemeIs("file", &isSchemeFile)) && isSchemeFile) {
   1.197 +        nsCOMPtr<nsIFileURL> fileUrl = do_QueryInterface(uri);
   1.198 +        nsCOMPtr<nsIFile> file;
   1.199 +        rv = fileUrl->GetFile(getter_AddRefs(file));
   1.200 +        if (NS_FAILED(rv)) return rv;
   1.201 +        file->SetFollowLinks(true);
   1.202 +        
   1.203 +        nsAutoCString url;
   1.204 +        rv = net_GetURLSpecFromFile(file, url);
   1.205 +        if (NS_FAILED(rv)) return rv;
   1.206 +        baseUri.Assign(url);
   1.207 +        
   1.208 +        nsCOMPtr<nsIFile> parent;
   1.209 +        rv = file->GetParent(getter_AddRefs(parent));
   1.210 +        
   1.211 +        if (parent && NS_SUCCEEDED(rv)) {
   1.212 +            net_GetURLSpecFromDir(parent, url);
   1.213 +            if (NS_FAILED(rv)) return rv;
   1.214 +            parentStr.Assign(url);
   1.215 +        }
   1.216 +
   1.217 +        // Directory index will be always encoded in UTF-8 if this is file url
   1.218 +        buffer.AppendLiteral("<meta charset=\"UTF-8\">\n");
   1.219 +
   1.220 +    } else if (NS_SUCCEEDED(uri->SchemeIs("jar", &isScheme)) && isScheme) {
   1.221 +        nsAutoCString path;
   1.222 +        rv = uri->GetPath(path);
   1.223 +        if (NS_FAILED(rv)) return rv;
   1.224 +
   1.225 +        // a top-level jar directory URL is of the form jar:foo.zip!/
   1.226 +        // path will be of the form foo.zip!/, and its last two characters
   1.227 +        // will be "!/"
   1.228 +        //XXX this won't work correctly when the name of the directory being
   1.229 +        //XXX displayed ends with "!", but then again, jar: URIs don't deal
   1.230 +        //XXX particularly well with such directories anyway
   1.231 +        if (!StringEndsWith(path, NS_LITERAL_CSTRING("!/"))) {
   1.232 +            rv = uri->Resolve(NS_LITERAL_CSTRING(".."), parentStr);
   1.233 +            if (NS_FAILED(rv)) return rv;
   1.234 +        }
   1.235 +    }
   1.236 +    else {
   1.237 +        // default behavior for other protocols is to assume the channel's
   1.238 +        // URL references a directory ending in '/' -- fixup if necessary.
   1.239 +        nsAutoCString path;
   1.240 +        rv = uri->GetPath(path);
   1.241 +        if (NS_FAILED(rv)) return rv;
   1.242 +        if (baseUri.Last() != '/') {
   1.243 +            baseUri.Append('/');
   1.244 +            path.Append('/');
   1.245 +            uri->SetPath(path);
   1.246 +        }
   1.247 +        if (!path.EqualsLiteral("/")) {
   1.248 +            rv = uri->Resolve(NS_LITERAL_CSTRING(".."), parentStr);
   1.249 +            if (NS_FAILED(rv)) return rv;
   1.250 +        }
   1.251 +    }
   1.252 +
   1.253 +    buffer.AppendLiteral("<style type=\"text/css\">\n"
   1.254 +                         ":root {\n"
   1.255 +                         "  font-family: sans-serif;\n"
   1.256 +                         "}\n"
   1.257 +                         "img {\n"
   1.258 +                         "  border: 0;\n"
   1.259 +                         "}\n"
   1.260 +                         "th {\n"
   1.261 +                         "  text-align: start;\n"
   1.262 +                         "  white-space: nowrap;\n"
   1.263 +                         "}\n"
   1.264 +                         "th > a {\n"
   1.265 +                         "  color: inherit;\n"
   1.266 +                         "}\n"
   1.267 +                         "table[order] > thead > tr > th {\n"
   1.268 +                         "  cursor: pointer;\n"
   1.269 +                         "}\n"
   1.270 +                         "table[order] > thead > tr > th::after {\n"
   1.271 +                         "  display: none;\n"
   1.272 +                         "  width: .8em;\n"
   1.273 +                         "  -moz-margin-end: -.8em;\n"
   1.274 +                         "  text-align: end;\n"
   1.275 +                         "}\n"
   1.276 +                         "table[order=\"asc\"] > thead > tr > th::after {\n"
   1.277 +                         "  content: \"\\2193\"; /* DOWNWARDS ARROW (U+2193) */\n"
   1.278 +                         "}\n"
   1.279 +                         "table[order=\"desc\"] > thead > tr > th::after {\n"
   1.280 +                         "  content: \"\\2191\"; /* UPWARDS ARROW (U+2191) */\n"
   1.281 +                         "}\n"
   1.282 +                         "table[order][order-by=\"0\"] > thead > tr > th:first-child > a ,\n"
   1.283 +                         "table[order][order-by=\"1\"] > thead > tr > th:first-child + th > a ,\n"
   1.284 +                         "table[order][order-by=\"2\"] > thead > tr > th:first-child + th + th > a {\n"
   1.285 +                         "  text-decoration: underline;\n"
   1.286 +                         "}\n"
   1.287 +                         "table[order][order-by=\"0\"] > thead > tr > th:first-child::after ,\n"
   1.288 +                         "table[order][order-by=\"1\"] > thead > tr > th:first-child + th::after ,\n"
   1.289 +                         "table[order][order-by=\"2\"] > thead > tr > th:first-child + th + th::after {\n"
   1.290 +                         "  display: inline-block;\n"
   1.291 +                         "}\n"
   1.292 +                         "table.remove-hidden > tbody > tr.hidden-object {\n"
   1.293 +                         "  display: none;\n"
   1.294 +                         "}\n"
   1.295 +                         "td {\n"
   1.296 +                         "  white-space: nowrap;\n"
   1.297 +                         "}\n"
   1.298 +                         "table.ellipsis {\n"
   1.299 +                         "  width: 100%;\n"
   1.300 +                         "  table-layout: fixed;\n"
   1.301 +                         "  border-spacing: 0;\n"
   1.302 +                         "}\n"
   1.303 +                         "table.ellipsis > tbody > tr > td {\n"
   1.304 +                         "  padding: 0;\n"
   1.305 +                         "  overflow: hidden;\n"
   1.306 +                         "  text-overflow: ellipsis;\n"
   1.307 +                         "}\n"
   1.308 +                         "/* name */\n"
   1.309 +                         "/* name */\n"
   1.310 +                         "th:first-child {\n"
   1.311 +                         "  -moz-padding-end: 2em;\n"
   1.312 +                         "}\n"
   1.313 +                         "/* size */\n"
   1.314 +                         "th:first-child + th {\n"
   1.315 +                         "  -moz-padding-end: 1em;\n"
   1.316 +                         "}\n"
   1.317 +                         "td:first-child + td {\n"
   1.318 +                         "  text-align: end;\n"
   1.319 +                         "  -moz-padding-end: 1em;\n"
   1.320 +                         "}\n"
   1.321 +                         "/* date */\n"
   1.322 +                         "td:first-child + td + td {\n"
   1.323 +                         "  -moz-padding-start: 1em;\n"
   1.324 +                         "  -moz-padding-end: .5em;\n"
   1.325 +                         "}\n"
   1.326 +                         "/* time */\n"
   1.327 +                         "td:first-child + td + td + td {\n"
   1.328 +                         "  -moz-padding-start: .5em;\n"
   1.329 +                         "}\n"
   1.330 +                         ".symlink {\n"
   1.331 +                         "  font-style: italic;\n"
   1.332 +                         "}\n"
   1.333 +                         ".dir ,\n"
   1.334 +                         ".symlink ,\n"
   1.335 +                         ".file {\n"
   1.336 +                         "  -moz-margin-start: 20px;\n"
   1.337 +                         "}\n"
   1.338 +                         ".dir::before ,\n"
   1.339 +                         ".file > img {\n"
   1.340 +                         "  -moz-margin-end: 4px;\n"
   1.341 +                         "  -moz-margin-start: -20px;\n"
   1.342 +                         "  max-width: 16px;\n"
   1.343 +                         "  max-height: 16px;\n"
   1.344 +                         "  vertical-align: middle;\n"
   1.345 +                         "}\n"
   1.346 +                         ".dir::before {\n"
   1.347 +                         "  content: url(resource://gre/res/html/folder.png);\n"
   1.348 +                         "}\n"
   1.349 +                         "</style>\n"
   1.350 +                         "<link rel=\"stylesheet\" media=\"screen, projection\" type=\"text/css\""
   1.351 +                         " href=\"chrome://global/skin/dirListing/dirListing.css\">\n"
   1.352 +                         "<script type=\"application/javascript\">\n"
   1.353 +                         "var gTable, gOrderBy, gTBody, gRows, gUI_showHidden;\n"
   1.354 +                         "document.addEventListener(\"DOMContentLoaded\", function() {\n"
   1.355 +                         "  gTable = document.getElementsByTagName(\"table\")[0];\n"
   1.356 +                         "  gTBody = gTable.tBodies[0];\n"
   1.357 +                         "  if (gTBody.rows.length < 2)\n"
   1.358 +                         "    return;\n"
   1.359 +                         "  gUI_showHidden = document.getElementById(\"UI_showHidden\");\n"
   1.360 +                         "  var headCells = gTable.tHead.rows[0].cells,\n"
   1.361 +                         "      hiddenObjects = false;\n"
   1.362 +                         "  function rowAction(i) {\n"
   1.363 +                         "    return function(event) {\n"
   1.364 +                         "      event.preventDefault();\n"
   1.365 +                         "      orderBy(i);\n"
   1.366 +                         "    }\n"
   1.367 +                         "  }\n"
   1.368 +                         "  for (var i = headCells.length - 1; i >= 0; i--) {\n"
   1.369 +                         "    var anchor = document.createElement(\"a\");\n"
   1.370 +                         "    anchor.href = \"\";\n"
   1.371 +                         "    anchor.appendChild(headCells[i].firstChild);\n"
   1.372 +                         "    headCells[i].appendChild(anchor);\n"
   1.373 +                         "    headCells[i].addEventListener(\"click\", rowAction(i), true);\n"
   1.374 +                         "  }\n"
   1.375 +                         "  if (gUI_showHidden) {\n"
   1.376 +                         "    gRows = Array.slice(gTBody.rows);\n"
   1.377 +                         "    hiddenObjects = gRows.some(function (row) row.className == \"hidden-object\");\n"
   1.378 +                         "  }\n"
   1.379 +                         "  gTable.setAttribute(\"order\", \"\");\n"
   1.380 +                         "  if (hiddenObjects) {\n"
   1.381 +                         "    gUI_showHidden.style.display = \"block\";\n"
   1.382 +                         "    updateHidden();\n"
   1.383 +                         "  }\n"
   1.384 +                         "}, \"false\");\n"
   1.385 +                         "function compareRows(rowA, rowB) {\n"
   1.386 +                         "  var a = rowA.cells[gOrderBy].getAttribute(\"sortable-data\") || \"\";\n"
   1.387 +                         "  var b = rowB.cells[gOrderBy].getAttribute(\"sortable-data\") || \"\";\n"
   1.388 +                         "  var intA = +a;\n"
   1.389 +                         "  var intB = +b;\n"
   1.390 +                         "  if (a == intA && b == intB) {\n"
   1.391 +                         "    a = intA;\n"
   1.392 +                         "    b = intB;\n"
   1.393 +                         "  } else {\n"
   1.394 +                         "    a = a.toLowerCase();\n"
   1.395 +                         "    b = b.toLowerCase();\n"
   1.396 +                         "  }\n"
   1.397 +                         "  if (a < b)\n"
   1.398 +                         "    return -1;\n"
   1.399 +                         "  if (a > b)\n"
   1.400 +                         "    return 1;\n"
   1.401 +                         "  return 0;\n"
   1.402 +                         "}\n"
   1.403 +                         "function orderBy(column) {\n"
   1.404 +                         "  if (!gRows)\n"
   1.405 +                         "    gRows = Array.slice(gTBody.rows);\n"
   1.406 +                         "  var order;\n"
   1.407 +                         "  if (gOrderBy == column) {\n"
   1.408 +                         "    order = gTable.getAttribute(\"order\") == \"asc\" ? \"desc\" : \"asc\";\n"
   1.409 +                         "  } else {\n"
   1.410 +                         "    order = \"asc\";\n"
   1.411 +                         "    gOrderBy = column;\n"
   1.412 +                         "    gTable.setAttribute(\"order-by\", column);\n"
   1.413 +                         "    gRows.sort(compareRows);\n"
   1.414 +                         "  }\n"
   1.415 +                         "  gTable.removeChild(gTBody);\n"
   1.416 +                         "  gTable.setAttribute(\"order\", order);\n"
   1.417 +                         "  if (order == \"asc\")\n"
   1.418 +                         "    for (var i = 0; i < gRows.length; i++)\n"
   1.419 +                         "      gTBody.appendChild(gRows[i]);\n"
   1.420 +                         "  else\n"
   1.421 +                         "    for (var i = gRows.length - 1; i >= 0; i--)\n"
   1.422 +                         "      gTBody.appendChild(gRows[i]);\n"
   1.423 +                         "  gTable.appendChild(gTBody);\n"
   1.424 +                         "}\n"
   1.425 +                         "function updateHidden() {\n"
   1.426 +                         "  gTable.className = gUI_showHidden.getElementsByTagName(\"input\")[0].checked ?\n"
   1.427 +                         "                     \"\" :\n"
   1.428 +                         "                     \"remove-hidden\";\n"
   1.429 +                         "}\n"
   1.430 +                         "</script>\n");
   1.431 +
   1.432 +    buffer.AppendLiteral("<link rel=\"icon\" type=\"image/png\" href=\"");
   1.433 +    nsCOMPtr<nsIURI> innerUri = NS_GetInnermostURI(uri);
   1.434 +    if (!innerUri)
   1.435 +        return NS_ERROR_UNEXPECTED;
   1.436 +    nsCOMPtr<nsIFileURL> fileURL(do_QueryInterface(innerUri));
   1.437 +    //XXX bug 388553: can't use skinnable icons here due to security restrictions
   1.438 +    if (fileURL) {
   1.439 +        //buffer.AppendLiteral("chrome://global/skin/dirListing/local.png");
   1.440 +        buffer.AppendLiteral("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB"
   1.441 +                             "AAAAAQCAYAAAAf8%2F9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
   1.442 +                             "ZSBJbWFnZVJlYWR5ccllPAAAAjFJREFUeNqsU8uOElEQPffR"
   1.443 +                             "3XQ3ONASdBJCSBxHos5%2B3Bg3rvkCv8PElS78gPkO%2FATj"
   1.444 +                             "QoUdO2ftrJiRh6aneTb9sOpC4weMN6lcuFV16pxDIfI8x12O"
   1.445 +                             "YIDhcPiu2Wx%2B%2FHF5CW1Z6Jyegt%2FTNEWSJIjjGFEUIQ"
   1.446 +                             "xDrFYrWFSzXC4%2FdLvd95pRKpXKy%2BpRFZ7nwaWo1%2BsG"
   1.447 +                             "nQG2260BKJfLKJVKGI1GEEJw7ateryd0v993W63WEwjgxfn5"
   1.448 +                             "obGYzgCbzcaEbdsIggDj8Riu6z6iUk9SYZMSx8W0LMsM%2FS"
   1.449 +                             "KK75xnJlIq80anQXdbEp0OhcPJ0eiaJnGRMEyyPDsAKKUM9c"
   1.450 +                             "lkYoDo3SZJzzSdp0VSKYmfV1co%2Bz580kw5KDIM8RbRfEnU"
   1.451 +                             "f1HzxtQyMAGcaGruTKczMzEIaqhKifV6jd%2BzGQQB5llunF"
   1.452 +                             "%2FM52BizC2K5sYPYvZcu653tjOM9O93wnYc08gmkgg4VAxi"
   1.453 +                             "xfqFUJT36AYBZGd6PJkFCZnnlBxMp38gqIgLpZB0y4Nph18l"
   1.454 +                             "yWh5FFbrOSxbl3V4G%2BVB7T4ajYYxTyuLtO%2BCvWGgJE1M"
   1.455 +                             "c7JNsJEhvgw%2FQV4fo%2F24nbEsX2u1d5sVyn8sJO0ZAQiI"
   1.456 +                             "YnFh%2BxrfLz%2Fj29cBS%2FO14zg3i8XigW3ZkErDtmKoeM"
   1.457 +                             "%2BAJGRMnXeEPGKf0nCD1ydvkDzU9Jbc6OpR7WIw6L8lQ%2B"
   1.458 +                             "4pQ1%2FlPF0RGM9Ns91Wmptk0GfB4EJkt77vXYj%2F8m%2B8"
   1.459 +                             "y%2FkrwABHbz2H9V68DQAAAABJRU5ErkJggg%3D%3D");
   1.460 +    } else {
   1.461 +        //buffer.AppendLiteral("chrome://global/skin/dirListing/remote.png");
   1.462 +        buffer.AppendLiteral("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB"
   1.463 +                             "AAAAAQCAYAAAAf8%2F9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9i"
   1.464 +                             "ZSBJbWFnZVJlYWR5ccllPAAAAeBJREFUeNqcU81O20AQ%2Ft"
   1.465 +                             "Z2AgQSYQRqL1UPVG2hAUQkxLEStz4DrXpLpD5Drz31Cajax%"
   1.466 +                             "2Bghhx6qHIJURBTxIwQRwopCBbZjHMcOTrzermPipsSt1Iw0"
   1.467 +                             "3p3ZmW%2B%2B2R0TxhgOD34wjCHZlQ0iDYz9yvEfhxMTCYhE"
   1.468 +                             "QDIZhkxKd2sqzX2TOD2vBQCQhpPefng1ZP2dVPlLLdpL8SEM"
   1.469 +                             "cxng%2Fbs0RIHhtgs4twxOh%2BHjZxvzDx%2F3GQQiDFISiR"
   1.470 +                             "BLFMPKTRMollzcWECrDVhtxtdRVsL9youPxGj%2FbdfFlUZh"
   1.471 +                             "tDyYbYqWRUdai1oQRZ5oHeHl2gNM%2B01Uqio8RlH%2Bnsaz"
   1.472 +                             "JzNwXcq1B%2BiXPHprlEEymeBfXs1w8XxxihfyuXqoHqpoGj"
   1.473 +                             "ZM04bddgG%2F9%2B8WGj87qDdsrK9m%2BoA%2BpbhQTDh2l1"
   1.474 +                             "%2Bi2weNbSHMZyjvNXmVbqh9Fj5Oz27uEoP%2BSTxANruJs9"
   1.475 +                             "L%2FT6P0ewqPx5nmiAG5f6AoCtN1PbJzuRyJAyDBzzSQYvEr"
   1.476 +                             "f06yYxhGXlEa8H2KVGoasjwLx3Ewk858opQWXm%2B%2Fib9E"
   1.477 +                             "QrBzclLLLy89xYvlpchvtixcX6uo1y%2FzsiwHrkIsgKbp%2"
   1.478 +                             "BYWFOWicuqppoNTnStHzPFCPQhBEBOyGAX4JMADFetubi4BS"
   1.479 +                             "YAAAAABJRU5ErkJggg%3D%3D");
   1.480 +    }
   1.481 +    buffer.AppendLiteral("\">\n<title>");
   1.482 +
   1.483 +    // Everything needs to end in a /,
   1.484 +    // otherwise we end up linking to file:///foo/dirfile
   1.485 +
   1.486 +    if (!mTextToSubURI) {
   1.487 +        mTextToSubURI = do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
   1.488 +        if (NS_FAILED(rv)) return rv;
   1.489 +    }
   1.490 +
   1.491 +    nsXPIDLCString encoding;
   1.492 +    rv = uri->GetOriginCharset(encoding);
   1.493 +    if (NS_FAILED(rv)) return rv;
   1.494 +    if (encoding.IsEmpty()) {
   1.495 +      encoding.AssignLiteral("UTF-8");
   1.496 +    }
   1.497 +
   1.498 +    nsXPIDLString unEscapeSpec;
   1.499 +    rv = mTextToSubURI->UnEscapeAndConvert(encoding, titleUri.get(),
   1.500 +                                           getter_Copies(unEscapeSpec));
   1.501 +    // unescape may fail because
   1.502 +    // 1. file URL may be encoded in platform charset for backward compatibility
   1.503 +    // 2. query part may not be encoded in UTF-8 (see bug 261929)
   1.504 +    // so try the platform's default if this is file url
   1.505 +    if (NS_FAILED(rv) && isSchemeFile) {
   1.506 +        nsCOMPtr<nsIPlatformCharset> platformCharset(do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv));
   1.507 +        NS_ENSURE_SUCCESS(rv, rv);
   1.508 +        nsAutoCString charset;
   1.509 +        rv = platformCharset->GetCharset(kPlatformCharsetSel_FileName, charset);
   1.510 +        NS_ENSURE_SUCCESS(rv, rv);
   1.511 +
   1.512 +        rv = mTextToSubURI->UnEscapeAndConvert(charset.get(), titleUri.get(),
   1.513 +                                               getter_Copies(unEscapeSpec));
   1.514 +    }
   1.515 +    if (NS_FAILED(rv)) return rv;
   1.516 +
   1.517 +    nsXPIDLString htmlEscSpec;
   1.518 +    htmlEscSpec.Adopt(nsEscapeHTML2(unEscapeSpec.get(),
   1.519 +                                    unEscapeSpec.Length()));
   1.520 +
   1.521 +    nsXPIDLString title;
   1.522 +    const char16_t* formatTitle[] = {
   1.523 +        htmlEscSpec.get()
   1.524 +    };
   1.525 +
   1.526 +    rv = mBundle->FormatStringFromName(MOZ_UTF16("DirTitle"),
   1.527 +                                       formatTitle,
   1.528 +                                       sizeof(formatTitle)/sizeof(char16_t*),
   1.529 +                                       getter_Copies(title));
   1.530 +    if (NS_FAILED(rv)) return rv;
   1.531 +
   1.532 +    // we want to convert string bundle to NCR
   1.533 +    // to ensure they're shown in any charsets
   1.534 +    AppendNonAsciiToNCR(title, buffer);
   1.535 +
   1.536 +    buffer.AppendLiteral("</title>\n");    
   1.537 +
   1.538 +    // If there is a quote character in the baseUri, then
   1.539 +    // lets not add a base URL.  The reason for this is that
   1.540 +    // if we stick baseUri containing a quote into a quoted
   1.541 +    // string, the quote character will prematurely close
   1.542 +    // the base href string.  This is a fall-back check;
   1.543 +    // that's why it is OK to not use a base rather than
   1.544 +    // trying to play nice and escaping the quotes.  See bug
   1.545 +    // 358128.
   1.546 +
   1.547 +    if (baseUri.FindChar('"') == kNotFound)
   1.548 +    {
   1.549 +        // Great, the baseUri does not contain a char that
   1.550 +        // will prematurely close the string.  Go ahead an
   1.551 +        // add a base href.
   1.552 +        buffer.AppendLiteral("<base href=\"");
   1.553 +        nsAdoptingCString htmlEscapedUri(nsEscapeHTML(baseUri.get()));
   1.554 +        buffer.Append(htmlEscapedUri);
   1.555 +        buffer.AppendLiteral("\" />\n");
   1.556 +    }
   1.557 +    else
   1.558 +    {
   1.559 +        NS_ERROR("broken protocol handler didn't escape double-quote.");
   1.560 +    }
   1.561 +
   1.562 +    nsCString direction(NS_LITERAL_CSTRING("ltr"));
   1.563 +    nsCOMPtr<nsIXULChromeRegistry> reg =
   1.564 +      mozilla::services::GetXULChromeRegistryService();
   1.565 +    if (reg) {
   1.566 +      bool isRTL = false;
   1.567 +      reg->IsLocaleRTL(NS_LITERAL_CSTRING("global"), &isRTL);
   1.568 +      if (isRTL) {
   1.569 +        direction.AssignLiteral("rtl");
   1.570 +      }
   1.571 +    }
   1.572 +
   1.573 +    buffer.AppendLiteral("</head>\n<body dir=\"");
   1.574 +    buffer.Append(direction);
   1.575 +    buffer.AppendLiteral("\">\n<h1>");
   1.576 +    
   1.577 +    const char16_t* formatHeading[] = {
   1.578 +        htmlEscSpec.get()
   1.579 +    };
   1.580 +
   1.581 +    rv = mBundle->FormatStringFromName(MOZ_UTF16("DirTitle"),
   1.582 +                                       formatHeading,
   1.583 +                                       sizeof(formatHeading)/sizeof(char16_t*),
   1.584 +                                       getter_Copies(title));
   1.585 +    if (NS_FAILED(rv)) return rv;
   1.586 +    
   1.587 +    AppendNonAsciiToNCR(title, buffer);
   1.588 +    buffer.AppendLiteral("</h1>\n");
   1.589 +
   1.590 +    if (!parentStr.IsEmpty()) {
   1.591 +        nsXPIDLString parentText;
   1.592 +        rv = mBundle->GetStringFromName(MOZ_UTF16("DirGoUp"),
   1.593 +                                        getter_Copies(parentText));
   1.594 +        if (NS_FAILED(rv)) return rv;
   1.595 +
   1.596 +        buffer.AppendLiteral("<p id=\"UI_goUp\"><a class=\"up\" href=\"");
   1.597 +
   1.598 +        nsAdoptingCString htmlParentStr(nsEscapeHTML(parentStr.get()));
   1.599 +        buffer.Append(htmlParentStr);
   1.600 +        buffer.AppendLiteral("\">");
   1.601 +        AppendNonAsciiToNCR(parentText, buffer);
   1.602 +        buffer.AppendLiteral("</a></p>\n");
   1.603 +    }
   1.604 +
   1.605 +    if (isSchemeFile) {
   1.606 +        nsXPIDLString showHiddenText;
   1.607 +        rv = mBundle->GetStringFromName(MOZ_UTF16("ShowHidden"),
   1.608 +                                        getter_Copies(showHiddenText));
   1.609 +        if (NS_FAILED(rv)) return rv;
   1.610 +
   1.611 +        buffer.AppendLiteral("<p id=\"UI_showHidden\" style=\"display:none\"><label><input type=\"checkbox\" checked onchange=\"updateHidden()\">");
   1.612 +        AppendNonAsciiToNCR(showHiddenText, buffer);
   1.613 +        buffer.AppendLiteral("</label></p>\n");
   1.614 +    }
   1.615 +
   1.616 +    buffer.AppendLiteral("<table>\n");
   1.617 +
   1.618 +    nsXPIDLString columnText;
   1.619 +
   1.620 +    buffer.AppendLiteral(" <thead>\n"
   1.621 +                         "  <tr>\n"
   1.622 +                         "   <th>");
   1.623 +
   1.624 +    rv = mBundle->GetStringFromName(MOZ_UTF16("DirColName"),
   1.625 +                                    getter_Copies(columnText));
   1.626 +    if (NS_FAILED(rv)) return rv;
   1.627 +    AppendNonAsciiToNCR(columnText, buffer);
   1.628 +    buffer.AppendLiteral("</th>\n"
   1.629 +                         "   <th>");
   1.630 +
   1.631 +    rv = mBundle->GetStringFromName(MOZ_UTF16("DirColSize"),
   1.632 +                                    getter_Copies(columnText));
   1.633 +    if (NS_FAILED(rv)) return rv;
   1.634 +    AppendNonAsciiToNCR(columnText, buffer);
   1.635 +    buffer.AppendLiteral("</th>\n"
   1.636 +                         "   <th colspan=\"2\">");
   1.637 +
   1.638 +    rv = mBundle->GetStringFromName(MOZ_UTF16("DirColMTime"),
   1.639 +                                    getter_Copies(columnText));
   1.640 +    if (NS_FAILED(rv)) return rv;
   1.641 +    AppendNonAsciiToNCR(columnText, buffer);
   1.642 +    buffer.AppendLiteral("</th>\n"
   1.643 +                         "  </tr>\n"
   1.644 +                         " </thead>\n");
   1.645 +    buffer.AppendLiteral(" <tbody>\n");
   1.646 +
   1.647 +    aBuffer = buffer;
   1.648 +    return rv;
   1.649 +}
   1.650 +
   1.651 +NS_IMETHODIMP
   1.652 +nsIndexedToHTML::OnStopRequest(nsIRequest* request, nsISupports *aContext,
   1.653 +                               nsresult aStatus) {
   1.654 +    if (NS_SUCCEEDED(aStatus)) {
   1.655 +        nsCString buffer;
   1.656 +        buffer.AssignLiteral("</tbody></table></body></html>\n");
   1.657 +
   1.658 +        aStatus = SendToListener(request, aContext, buffer);
   1.659 +    }
   1.660 +
   1.661 +    mParser->OnStopRequest(request, aContext, aStatus);
   1.662 +    mParser = 0;
   1.663 +    
   1.664 +    return mListener->OnStopRequest(request, aContext, aStatus);
   1.665 +}
   1.666 +
   1.667 +nsresult
   1.668 +nsIndexedToHTML::SendToListener(nsIRequest* aRequest, nsISupports *aContext, const nsACString &aBuffer)
   1.669 +{
   1.670 +    nsCOMPtr<nsIInputStream> inputData;
   1.671 +    nsresult rv = NS_NewCStringInputStream(getter_AddRefs(inputData), aBuffer);
   1.672 +    NS_ENSURE_SUCCESS(rv, rv);
   1.673 +    return mListener->OnDataAvailable(aRequest, aContext,
   1.674 +                                      inputData, 0, aBuffer.Length());
   1.675 +}
   1.676 +
   1.677 +NS_IMETHODIMP
   1.678 +nsIndexedToHTML::OnDataAvailable(nsIRequest *aRequest,
   1.679 +                                 nsISupports *aCtxt,
   1.680 +                                 nsIInputStream* aInput,
   1.681 +                                 uint64_t aOffset,
   1.682 +                                 uint32_t aCount) {
   1.683 +    return mParser->OnDataAvailable(aRequest, aCtxt, aInput, aOffset, aCount);
   1.684 +}
   1.685 +
   1.686 +NS_IMETHODIMP
   1.687 +nsIndexedToHTML::OnIndexAvailable(nsIRequest *aRequest,
   1.688 +                                  nsISupports *aCtxt,
   1.689 +                                  nsIDirIndex *aIndex) {
   1.690 +    nsresult rv;
   1.691 +    if (!aIndex)
   1.692 +        return NS_ERROR_NULL_POINTER;
   1.693 +
   1.694 +    nsCString pushBuffer;
   1.695 +    pushBuffer.AppendLiteral("<tr");
   1.696 +
   1.697 +    // We don't know the file's character set yet, so retrieve the raw bytes
   1.698 +    // which will be decoded by the HTML parser.
   1.699 +    nsXPIDLCString loc;
   1.700 +    aIndex->GetLocation(getter_Copies(loc));
   1.701 +
   1.702 +    // Adjust the length in case unescaping shortened the string.
   1.703 +    loc.Truncate(nsUnescapeCount(loc.BeginWriting()));
   1.704 +    if (loc.First() == PRUnichar('.'))
   1.705 +        pushBuffer.AppendLiteral(" class=\"hidden-object\"");
   1.706 +
   1.707 +    pushBuffer.AppendLiteral(">\n <td sortable-data=\"");
   1.708 +
   1.709 +    // The sort key is the name of the item, prepended by either 0, 1 or 2
   1.710 +    // in order to group items.
   1.711 +    uint32_t type;
   1.712 +    aIndex->GetType(&type);
   1.713 +    switch (type) {
   1.714 +        case nsIDirIndex::TYPE_SYMLINK:
   1.715 +            pushBuffer.Append('0');
   1.716 +            break;
   1.717 +        case nsIDirIndex::TYPE_DIRECTORY:
   1.718 +            pushBuffer.Append('1');
   1.719 +            break;
   1.720 +        default:
   1.721 +            pushBuffer.Append('2');
   1.722 +            break;
   1.723 +    }
   1.724 +    nsAdoptingCString escaped(nsEscapeHTML(loc));
   1.725 +    pushBuffer.Append(escaped);
   1.726 +
   1.727 +    pushBuffer.AppendLiteral("\"><table class=\"ellipsis\"><tbody><tr><td><a class=\"");
   1.728 +    switch (type) {
   1.729 +        case nsIDirIndex::TYPE_DIRECTORY:
   1.730 +            pushBuffer.AppendLiteral("dir");
   1.731 +            break;
   1.732 +        case nsIDirIndex::TYPE_SYMLINK:
   1.733 +            pushBuffer.AppendLiteral("symlink");
   1.734 +            break;
   1.735 +        default:
   1.736 +            pushBuffer.AppendLiteral("file");
   1.737 +            break;
   1.738 +    }
   1.739 +
   1.740 +    pushBuffer.AppendLiteral("\" href=\"");
   1.741 +
   1.742 +    // need to escape links
   1.743 +    nsAutoCString locEscaped;
   1.744 +
   1.745 +    // Adding trailing slash helps to recognize whether the URL points to a file
   1.746 +    // or a directory (bug #214405).
   1.747 +    if ((type == nsIDirIndex::TYPE_DIRECTORY) && (loc.Last() != '/')) {
   1.748 +        loc.Append('/');
   1.749 +    }
   1.750 +
   1.751 +    // now minimally re-escape the location...
   1.752 +    uint32_t escFlags;
   1.753 +    // for some protocols, we expect the location to be absolute.
   1.754 +    // if so, and if the location indeed appears to be a valid URI, then go
   1.755 +    // ahead and treat it like one.
   1.756 +    if (mExpectAbsLoc &&
   1.757 +        NS_SUCCEEDED(net_ExtractURLScheme(loc, nullptr, nullptr, nullptr))) {
   1.758 +        // escape as absolute 
   1.759 +        escFlags = esc_Forced | esc_AlwaysCopy | esc_Minimal;
   1.760 +    }
   1.761 +    else {
   1.762 +        // escape as relative
   1.763 +        // esc_Directory is needed because directories have a trailing slash.
   1.764 +        // Without it, the trailing '/' will be escaped, and links from within
   1.765 +        // that directory will be incorrect
   1.766 +        escFlags = esc_Forced | esc_AlwaysCopy | esc_FileBaseName | esc_Colon | esc_Directory;
   1.767 +    }
   1.768 +    NS_EscapeURL(loc.get(), loc.Length(), escFlags, locEscaped);
   1.769 +    // esc_Directory does not escape the semicolons, so if a filename
   1.770 +    // contains semicolons we need to manually escape them.
   1.771 +    // This replacement should be removed in bug #473280
   1.772 +    locEscaped.ReplaceSubstring(";", "%3b");
   1.773 +    nsAdoptingCString htmlEscapedURL(nsEscapeHTML(locEscaped.get()));
   1.774 +    pushBuffer.Append(htmlEscapedURL);
   1.775 +
   1.776 +    pushBuffer.AppendLiteral("\">");
   1.777 +
   1.778 +    if (type == nsIDirIndex::TYPE_FILE || type == nsIDirIndex::TYPE_UNKNOWN) {
   1.779 +        pushBuffer.AppendLiteral("<img src=\"moz-icon://");
   1.780 +        int32_t lastDot = locEscaped.RFindChar('.');
   1.781 +        if (lastDot != kNotFound) {
   1.782 +            locEscaped.Cut(0, lastDot);
   1.783 +            nsAdoptingCString htmlFileExt(nsEscapeHTML(locEscaped.get()));
   1.784 +            pushBuffer.Append(htmlFileExt);
   1.785 +        } else {
   1.786 +            pushBuffer.AppendLiteral("unknown");
   1.787 +        }
   1.788 +        pushBuffer.AppendLiteral("?size=16\" alt=\"");
   1.789 +
   1.790 +        nsXPIDLString altText;
   1.791 +        rv = mBundle->GetStringFromName(MOZ_UTF16("DirFileLabel"),
   1.792 +                                        getter_Copies(altText));
   1.793 +        if (NS_FAILED(rv)) return rv;
   1.794 +        AppendNonAsciiToNCR(altText, pushBuffer);
   1.795 +        pushBuffer.AppendLiteral("\">");
   1.796 +    }
   1.797 +
   1.798 +    pushBuffer.Append(escaped);
   1.799 +    pushBuffer.AppendLiteral("</a></td></tr></tbody></table></td>\n <td");
   1.800 +
   1.801 +    if (type == nsIDirIndex::TYPE_DIRECTORY || type == nsIDirIndex::TYPE_SYMLINK) {
   1.802 +        pushBuffer.AppendLiteral(">");
   1.803 +    } else {
   1.804 +        int64_t size;
   1.805 +        aIndex->GetSize(&size);
   1.806 +
   1.807 +        if (uint64_t(size) != UINT64_MAX) {
   1.808 +            pushBuffer.AppendLiteral(" sortable-data=\"");
   1.809 +            pushBuffer.AppendInt(size);
   1.810 +            pushBuffer.AppendLiteral("\">");
   1.811 +            nsAutoCString sizeString;
   1.812 +            FormatSizeString(size, sizeString);
   1.813 +            pushBuffer.Append(sizeString);
   1.814 +        } else {
   1.815 +            pushBuffer.AppendLiteral(">");
   1.816 +        }
   1.817 +    }
   1.818 +    pushBuffer.AppendLiteral("</td>\n <td");
   1.819 +
   1.820 +    PRTime t;
   1.821 +    aIndex->GetLastModified(&t);
   1.822 +
   1.823 +    if (t == -1) {
   1.824 +        pushBuffer.AppendLiteral("></td>\n <td>");
   1.825 +    } else {
   1.826 +        pushBuffer.AppendLiteral(" sortable-data=\"");
   1.827 +        pushBuffer.AppendInt(static_cast<int64_t>(t));
   1.828 +        pushBuffer.AppendLiteral("\">");
   1.829 +        nsAutoString formatted;
   1.830 +        mDateTime->FormatPRTime(nullptr,
   1.831 +                                kDateFormatShort,
   1.832 +                                kTimeFormatNone,
   1.833 +                                t,
   1.834 +                                formatted);
   1.835 +        AppendNonAsciiToNCR(formatted, pushBuffer);
   1.836 +        pushBuffer.AppendLiteral("</td>\n <td>");
   1.837 +        mDateTime->FormatPRTime(nullptr,
   1.838 +                                kDateFormatNone,
   1.839 +                                kTimeFormatSeconds,
   1.840 +                                t,
   1.841 +                                formatted);
   1.842 +        // use NCR to show date in any doc charset
   1.843 +        AppendNonAsciiToNCR(formatted, pushBuffer);
   1.844 +    }
   1.845 +
   1.846 +    pushBuffer.AppendLiteral("</td>\n</tr>");
   1.847 +
   1.848 +    return SendToListener(aRequest, aCtxt, pushBuffer);
   1.849 +}
   1.850 +
   1.851 +NS_IMETHODIMP
   1.852 +nsIndexedToHTML::OnInformationAvailable(nsIRequest *aRequest,
   1.853 +                                        nsISupports *aCtxt,
   1.854 +                                        const nsAString& aInfo) {
   1.855 +    nsAutoCString pushBuffer;
   1.856 +    nsAdoptingString escaped(nsEscapeHTML2(PromiseFlatString(aInfo).get()));
   1.857 +    if (!escaped)
   1.858 +        return NS_ERROR_OUT_OF_MEMORY;
   1.859 +    pushBuffer.AppendLiteral("<tr>\n <td>");
   1.860 +    // escaped is provided in Unicode, so write hex NCRs as necessary
   1.861 +    // to prevent the HTML parser from applying a character set.
   1.862 +    AppendNonAsciiToNCR(escaped, pushBuffer);
   1.863 +    pushBuffer.AppendLiteral("</td>\n <td></td>\n <td></td>\n <td></td>\n</tr>\n");
   1.864 +    
   1.865 +    return SendToListener(aRequest, aCtxt, pushBuffer);
   1.866 +}
   1.867 +
   1.868 +void nsIndexedToHTML::FormatSizeString(int64_t inSize, nsCString& outSizeString)
   1.869 +{
   1.870 +    outSizeString.Truncate();
   1.871 +    if (inSize > int64_t(0)) {
   1.872 +        // round up to the nearest Kilobyte
   1.873 +        int64_t  upperSize = (inSize + int64_t(1023)) / int64_t(1024);
   1.874 +        outSizeString.AppendInt(upperSize);
   1.875 +        outSizeString.AppendLiteral(" KB");
   1.876 +    }
   1.877 +}
   1.878 +
   1.879 +nsIndexedToHTML::nsIndexedToHTML() {
   1.880 +}
   1.881 +
   1.882 +nsIndexedToHTML::~nsIndexedToHTML() {
   1.883 +}

mercurial