LCOV - app.info - netwerk/streamconv/converters/nsIndexedToHTML.cpp

LCOV - code coverage report
| Current view: | directory - netwerk/streamconv/converters - nsIndexedToHTML.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 449 | 0 | 0.0 %
| Date: | 2012-07-07 | Functions: | 19 | 0 | 0.0 %

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

Generated by: LCOV version 1.7