NS_IMETHODIMP nsParserUtils::ParseFragment(const nsAString& aFragment, PRUint32 aFlags, bool aIsXML, nsIURI* aBaseURI, nsIDOMElement* aContextElement, nsIDOMDocumentFragment** aReturn) { NS_ENSURE_ARG(aContextElement); *aReturn = nsnull; nsresult rv; nsCOMPtr<nsIParser> parser = do_CreateInstance(kCParserCID, &rv); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIDocument> document; nsCOMPtr<nsIDOMDocument> domDocument; nsCOMPtr<nsIDOMNode> contextNode; contextNode = do_QueryInterface(aContextElement); contextNode->GetOwnerDocument(getter_AddRefs(domDocument)); document = do_QueryInterface(domDocument); NS_ENSURE_TRUE(document, NS_ERROR_NOT_AVAILABLE); // stop scripts nsRefPtr<nsScriptLoader> loader; bool scripts_enabled = false; if (document) { loader = document->ScriptLoader(); scripts_enabled = loader->GetEnabled(); } if (scripts_enabled) { loader->SetEnabled(false); } // Wrap things in a div or body for parsing, but it won't show up in // the fragment. nsAutoTArray<nsString, 2> tagStack; nsCAutoString base, spec; if (aIsXML) { // XHTML if (aBaseURI) { base.Append(NS_LITERAL_CSTRING(XHTML_DIV_TAG)); base.Append(NS_LITERAL_CSTRING(" xml:base=\"")); aBaseURI->GetSpec(spec); // nsEscapeHTML is good enough, because we only need to get // quotes, ampersands, and angle brackets char* escapedSpec = nsEscapeHTML(spec.get()); if (escapedSpec) base += escapedSpec; NS_Free(escapedSpec); base.Append(NS_LITERAL_CSTRING("\"")); tagStack.AppendElement(NS_ConvertUTF8toUTF16(base)); } else { tagStack.AppendElement(NS_LITERAL_STRING(XHTML_DIV_TAG)); } } if (NS_SUCCEEDED(rv)) { nsCOMPtr<nsIContent> fragment; if (aIsXML) { rv = nsContentUtils::ParseFragmentXML(aFragment, document, tagStack, true, aReturn); fragment = do_QueryInterface(*aReturn); } else { NS_NewDocumentFragment(aReturn, document->NodeInfoManager()); fragment = do_QueryInterface(*aReturn); rv = nsContentUtils::ParseFragmentHTML(aFragment, fragment, nsGkAtoms::body, kNameSpaceID_XHTML, false, true); // Now, set the base URI on all subtree roots. if (aBaseURI) { aBaseURI->GetSpec(spec); nsAutoString spec16; CopyUTF8toUTF16(spec, spec16); nsIContent* node = fragment->GetFirstChild(); while (node) { if (node->IsElement()) { node->SetAttr(kNameSpaceID_XML, nsGkAtoms::base, nsGkAtoms::xml, spec16, false); } node = node->GetNextSibling(); } } } if (fragment) { nsTreeSanitizer sanitizer(aFlags); sanitizer.Sanitize(fragment); } } if (scripts_enabled) loader->SetEnabled(true); return rv; }
NS_IMETHODIMP nsIndexedToHTML::OnIndexAvailable(nsIRequest *aRequest, nsISupports *aCtxt, nsIDirIndex *aIndex) { nsresult rv; if (!aIndex) return NS_ERROR_NULL_POINTER; nsCString pushBuffer; pushBuffer.AppendLiteral("<tr"); // We don't know the file's character set yet, so retrieve the raw bytes // which will be decoded by the HTML parser. nsXPIDLCString loc; aIndex->GetLocation(getter_Copies(loc)); // Adjust the length in case unescaping shortened the string. loc.Truncate(nsUnescapeCount(loc.BeginWriting())); if (loc.First() == char16_t('.')) pushBuffer.AppendLiteral(" class=\"hidden-object\""); pushBuffer.AppendLiteral(">\n <td sortable-data=\""); // The sort key is the name of the item, prepended by either 0, 1 or 2 // in order to group items. uint32_t type; aIndex->GetType(&type); switch (type) { case nsIDirIndex::TYPE_SYMLINK: pushBuffer.Append('0'); break; case nsIDirIndex::TYPE_DIRECTORY: pushBuffer.Append('1'); break; default: pushBuffer.Append('2'); break; } nsAdoptingCString escaped(nsEscapeHTML(loc)); pushBuffer.Append(escaped); pushBuffer.AppendLiteral("\"><table class=\"ellipsis\"><tbody><tr><td><a class=\""); switch (type) { case nsIDirIndex::TYPE_DIRECTORY: pushBuffer.AppendLiteral("dir"); break; case nsIDirIndex::TYPE_SYMLINK: pushBuffer.AppendLiteral("symlink"); break; default: pushBuffer.AppendLiteral("file"); break; } pushBuffer.AppendLiteral("\" href=\""); // need to escape links nsAutoCString locEscaped; // Adding trailing slash helps to recognize whether the URL points to a file // or a directory (bug #214405). if ((type == nsIDirIndex::TYPE_DIRECTORY) && (loc.Last() != '/')) { loc.Append('/'); } // now minimally re-escape the location... uint32_t escFlags; // for some protocols, we expect the location to be absolute. // if so, and if the location indeed appears to be a valid URI, then go // ahead and treat it like one. nsAutoCString scheme; if (mExpectAbsLoc && NS_SUCCEEDED(net_ExtractURLScheme(loc, scheme))) { // escape as absolute escFlags = esc_Forced | esc_AlwaysCopy | esc_Minimal; } else { // escape as relative // esc_Directory is needed because directories have a trailing slash. // Without it, the trailing '/' will be escaped, and links from within // that directory will be incorrect escFlags = esc_Forced | esc_AlwaysCopy | esc_FileBaseName | esc_Colon | esc_Directory; } NS_EscapeURL(loc.get(), loc.Length(), escFlags, locEscaped); // esc_Directory does not escape the semicolons, so if a filename // contains semicolons we need to manually escape them. // This replacement should be removed in bug #473280 locEscaped.ReplaceSubstring(";", "%3b"); nsAdoptingCString htmlEscapedURL(nsEscapeHTML(locEscaped.get())); pushBuffer.Append(htmlEscapedURL); pushBuffer.AppendLiteral("\">"); if (type == nsIDirIndex::TYPE_FILE || type == nsIDirIndex::TYPE_UNKNOWN) { pushBuffer.AppendLiteral("<img src=\"moz-icon://"); int32_t lastDot = locEscaped.RFindChar('.'); if (lastDot != kNotFound) { locEscaped.Cut(0, lastDot); nsAdoptingCString htmlFileExt(nsEscapeHTML(locEscaped.get())); pushBuffer.Append(htmlFileExt); } else { pushBuffer.AppendLiteral("unknown"); } pushBuffer.AppendLiteral("?size=16\" alt=\""); nsXPIDLString altText; rv = mBundle->GetStringFromName(u"DirFileLabel", getter_Copies(altText)); if (NS_FAILED(rv)) return rv; AppendNonAsciiToNCR(altText, pushBuffer); pushBuffer.AppendLiteral("\">"); } pushBuffer.Append(escaped); pushBuffer.AppendLiteral("</a></td></tr></tbody></table></td>\n <td"); if (type == nsIDirIndex::TYPE_DIRECTORY || type == nsIDirIndex::TYPE_SYMLINK) { pushBuffer.Append('>'); } else { int64_t size; aIndex->GetSize(&size); if (uint64_t(size) != UINT64_MAX) { pushBuffer.AppendLiteral(" sortable-data=\""); pushBuffer.AppendInt(size); pushBuffer.AppendLiteral("\">"); nsAutoCString sizeString; FormatSizeString(size, sizeString); pushBuffer.Append(sizeString); } else { pushBuffer.Append('>'); } } pushBuffer.AppendLiteral("</td>\n <td"); PRTime t; aIndex->GetLastModified(&t); if (t == -1LL) { pushBuffer.AppendLiteral("></td>\n <td>"); } else { pushBuffer.AppendLiteral(" sortable-data=\""); pushBuffer.AppendInt(static_cast<int64_t>(t)); pushBuffer.AppendLiteral("\">"); nsAutoString formatted; mozilla::DateTimeFormat::FormatPRTime(kDateFormatShort, kTimeFormatNone, t, formatted); AppendNonAsciiToNCR(formatted, pushBuffer); pushBuffer.AppendLiteral("</td>\n <td>"); mozilla::DateTimeFormat::FormatPRTime(kDateFormatNone, kTimeFormatSeconds, t, formatted); // use NCR to show date in any doc charset AppendNonAsciiToNCR(formatted, pushBuffer); } pushBuffer.AppendLiteral("</td>\n</tr>"); return SendToListener(aRequest, aCtxt, pushBuffer); }
nsresult nsAboutCacheEntry::WriteCacheEntryDescription(nsICacheEntryDescriptor *descriptor) { nsresult rv; nsCString buffer; uint32_t n; nsAutoCString str; rv = descriptor->GetKey(str); if (NS_FAILED(rv)) return rv; buffer.SetCapacity(4096); buffer.AssignLiteral("<table>\n" " <tr>\n" " <th>key:</th>\n" " <td id=\"td-key\">"); // Test if the key is actually a URI nsCOMPtr<nsIURI> uri; bool isJS = false; bool isData = false; rv = NS_NewURI(getter_AddRefs(uri), str); // javascript: and data: URLs should not be linkified // since clicking them can cause scripts to run - bug 162584 if (NS_SUCCEEDED(rv)) { uri->SchemeIs("javascript", &isJS); uri->SchemeIs("data", &isData); } char* escapedStr = nsEscapeHTML(str.get()); if (NS_SUCCEEDED(rv) && !(isJS || isData)) { buffer.AppendLiteral("<a href=\""); buffer.Append(escapedStr); buffer.AppendLiteral("\">"); buffer.Append(escapedStr); buffer.AppendLiteral("</a>"); uri = 0; } else buffer.Append(escapedStr); nsMemory::Free(escapedStr); buffer.AppendLiteral("</td>\n" " </tr>\n"); // temp vars for reporting char timeBuf[255]; uint32_t u = 0; int32_t i = 0; nsAutoCString s; // Fetch Count s.Truncate(); descriptor->GetFetchCount(&i); s.AppendInt(i); APPEND_ROW("fetch count", s); // Last Fetched descriptor->GetLastFetched(&u); if (u) { PrintTimeString(timeBuf, sizeof(timeBuf), u); APPEND_ROW("last fetched", timeBuf); } else { APPEND_ROW("last fetched", "No last fetch time"); } // Last Modified descriptor->GetLastModified(&u); if (u) { PrintTimeString(timeBuf, sizeof(timeBuf), u); APPEND_ROW("last modified", timeBuf); } else { APPEND_ROW("last modified", "No last modified time"); } // Expiration Time descriptor->GetExpirationTime(&u); if (u < 0xFFFFFFFF) { PrintTimeString(timeBuf, sizeof(timeBuf), u); APPEND_ROW("expires", timeBuf); } else { APPEND_ROW("expires", "No expiration time"); } // Data Size s.Truncate(); uint32_t dataSize; descriptor->GetStorageDataSize(&dataSize); s.AppendInt((int32_t)dataSize); // XXX nsICacheEntryInfo interfaces should be fixed. APPEND_ROW("Data size", s); // Storage Policy // XXX Stream Based? // XXX Cache Device // File on disk nsCOMPtr<nsIFile> cacheFile; rv = descriptor->GetFile(getter_AddRefs(cacheFile)); if (NS_SUCCEEDED(rv)) { nsAutoString filePath; cacheFile->GetPath(filePath); APPEND_ROW("file on disk", NS_ConvertUTF16toUTF8(filePath)); } else APPEND_ROW("file on disk", "none"); // Security Info nsCOMPtr<nsISupports> securityInfo; descriptor->GetSecurityInfo(getter_AddRefs(securityInfo)); if (securityInfo) { APPEND_ROW("Security", "This is a secure document."); } else { APPEND_ROW("Security", "This document does not have any security info associated with it."); } buffer.AppendLiteral("</table>\n" "<hr/>\n" "<table>\n"); // Meta Data // let's just look for some well known (HTTP) meta data tags, for now. // Client ID nsXPIDLCString str2; descriptor->GetClientID(getter_Copies(str2)); if (!str2.IsEmpty()) APPEND_ROW("Client", str2); mBuffer = &buffer; // make it available for VisitMetaDataElement(). // nsCacheEntryDescriptor::VisitMetaData calls // nsCacheEntry.h VisitMetaDataElements, which returns // nsCacheMetaData::VisitElements, which calls // nsAboutCacheEntry::VisitMetaDataElement (below) in a loop. descriptor->VisitMetaData(this); mBuffer = nullptr; buffer.AppendLiteral("</table>\n"); mOutputStream->Write(buffer.get(), buffer.Length(), &n); buffer.Truncate(); // Provide a hexdump of the data if (dataSize) { // don't draw an <hr> if the Data Size is 0. nsCOMPtr<nsIInputStream> stream; descriptor->OpenInputStream(0, getter_AddRefs(stream)); if (stream) { buffer.AssignLiteral("<hr/>\n" "<pre>"); uint32_t hexDumpState = 0; char chunk[4096]; while(NS_SUCCEEDED(stream->Read(chunk, sizeof(chunk), &n)) && n > 0) { HexDump(&hexDumpState, chunk, n, buffer); mOutputStream->Write(buffer.get(), buffer.Length(), &n); buffer.Truncate(); } buffer.AssignLiteral("</pre>\n"); mOutputStream->Write(buffer.get(), buffer.Length(), &n); } } return NS_OK; }
nsresult nsIndexedToHTML::DoOnStartRequest(nsIRequest* request, nsISupports *aContext, nsCString& aBuffer) { nsresult rv; nsCOMPtr<nsIChannel> channel = do_QueryInterface(request); nsCOMPtr<nsIURI> uri; rv = channel->GetURI(getter_AddRefs(uri)); if (NS_FAILED(rv)) return rv; channel->SetContentType(NS_LITERAL_CSTRING("text/html")); mParser = do_CreateInstance("@mozilla.org/dirIndexParser;1",&rv); if (NS_FAILED(rv)) return rv; rv = mParser->SetListener(this); if (NS_FAILED(rv)) return rv; rv = mParser->OnStartRequest(request, aContext); if (NS_FAILED(rv)) return rv; nsAutoCString baseUri, titleUri; rv = uri->GetAsciiSpec(baseUri); if (NS_FAILED(rv)) return rv; titleUri = baseUri; nsCString parentStr; nsCString buffer; buffer.AppendLiteral("<!DOCTYPE html>\n<html>\n<head>\n"); // XXX - should be using the 300: line from the parser. // We can't guarantee that that comes before any entry, so we'd have to // buffer, and do other painful stuff. // I'll deal with this when I make the changes to handle welcome messages // The .. stuff should also come from the lower level protocols, but that // would muck up the XUL display // - bbaetz bool isScheme = false; bool isSchemeFile = false; if (NS_SUCCEEDED(uri->SchemeIs("ftp", &isScheme)) && isScheme) { // strip out the password here, so it doesn't show in the page title // This is done by the 300: line generation in ftp, but we don't use // that - see above nsAutoCString pw; rv = uri->GetPassword(pw); if (NS_FAILED(rv)) return rv; if (!pw.IsEmpty()) { nsCOMPtr<nsIURI> newUri; rv = uri->Clone(getter_AddRefs(newUri)); if (NS_FAILED(rv)) return rv; rv = newUri->SetPassword(EmptyCString()); if (NS_FAILED(rv)) return rv; rv = newUri->GetAsciiSpec(titleUri); if (NS_FAILED(rv)) return rv; } nsAutoCString path; rv = uri->GetPath(path); if (NS_FAILED(rv)) return rv; if (!path.EqualsLiteral("//") && !path.LowerCaseEqualsLiteral("/%2f")) { rv = uri->Resolve(NS_LITERAL_CSTRING(".."),parentStr); if (NS_FAILED(rv)) return rv; } } else if (NS_SUCCEEDED(uri->SchemeIs("file", &isSchemeFile)) && isSchemeFile) { nsCOMPtr<nsIFileURL> fileUrl = do_QueryInterface(uri); nsCOMPtr<nsIFile> file; rv = fileUrl->GetFile(getter_AddRefs(file)); if (NS_FAILED(rv)) return rv; file->SetFollowLinks(true); nsAutoCString url; rv = net_GetURLSpecFromFile(file, url); if (NS_FAILED(rv)) return rv; baseUri.Assign(url); nsCOMPtr<nsIFile> parent; rv = file->GetParent(getter_AddRefs(parent)); if (parent && NS_SUCCEEDED(rv)) { net_GetURLSpecFromDir(parent, url); if (NS_FAILED(rv)) return rv; parentStr.Assign(url); } // Directory index will be always encoded in UTF-8 if this is file url buffer.AppendLiteral("<meta charset=\"UTF-8\">\n"); } else if (NS_SUCCEEDED(uri->SchemeIs("jar", &isScheme)) && isScheme) { nsAutoCString path; rv = uri->GetPath(path); if (NS_FAILED(rv)) return rv; // a top-level jar directory URL is of the form jar:foo.zip!/ // path will be of the form foo.zip!/, and its last two characters // will be "!/" //XXX this won't work correctly when the name of the directory being //XXX displayed ends with "!", but then again, jar: URIs don't deal //XXX particularly well with such directories anyway if (!StringEndsWith(path, NS_LITERAL_CSTRING("!/"))) { rv = uri->Resolve(NS_LITERAL_CSTRING(".."), parentStr); if (NS_FAILED(rv)) return rv; } } else { // default behavior for other protocols is to assume the channel's // URL references a directory ending in '/' -- fixup if necessary. nsAutoCString path; rv = uri->GetPath(path); if (NS_FAILED(rv)) return rv; if (baseUri.Last() != '/') { baseUri.Append('/'); path.Append('/'); uri->SetPath(path); } if (!path.EqualsLiteral("/")) { rv = uri->Resolve(NS_LITERAL_CSTRING(".."), parentStr); if (NS_FAILED(rv)) return rv; } } buffer.AppendLiteral("<style type=\"text/css\">\n" ":root {\n" " font-family: sans-serif;\n" "}\n" "img {\n" " border: 0;\n" "}\n" "th {\n" " text-align: start;\n" " white-space: nowrap;\n" "}\n" "th > a {\n" " color: inherit;\n" "}\n" "table[order] > thead > tr > th {\n" " cursor: pointer;\n" "}\n" "table[order] > thead > tr > th::after {\n" " display: none;\n" " width: .8em;\n" " margin-inline-end: -.8em;\n" " text-align: end;\n" "}\n" "table[order=\"asc\"] > thead > tr > th::after {\n" " content: \"\\2193\"; /* DOWNWARDS ARROW (U+2193) */\n" "}\n" "table[order=\"desc\"] > thead > tr > th::after {\n" " content: \"\\2191\"; /* UPWARDS ARROW (U+2191) */\n" "}\n" "table[order][order-by=\"0\"] > thead > tr > th:first-child > a ,\n" "table[order][order-by=\"1\"] > thead > tr > th:first-child + th > a ,\n" "table[order][order-by=\"2\"] > thead > tr > th:first-child + th + th > a {\n" " text-decoration: underline;\n" "}\n" "table[order][order-by=\"0\"] > thead > tr > th:first-child::after ,\n" "table[order][order-by=\"1\"] > thead > tr > th:first-child + th::after ,\n" "table[order][order-by=\"2\"] > thead > tr > th:first-child + th + th::after {\n" " display: inline-block;\n" "}\n" "table.remove-hidden > tbody > tr.hidden-object {\n" " display: none;\n" "}\n" "td {\n" " white-space: nowrap;\n" "}\n" "table.ellipsis {\n" " width: 100%;\n" " table-layout: fixed;\n" " border-spacing: 0;\n" "}\n" "table.ellipsis > tbody > tr > td {\n" " padding: 0;\n" " overflow: hidden;\n" " text-overflow: ellipsis;\n" "}\n" "/* name */\n" "/* name */\n" "th:first-child {\n" " padding-inline-end: 2em;\n" "}\n" "/* size */\n" "th:first-child + th {\n" " padding-inline-end: 1em;\n" "}\n" "td:first-child + td {\n" " text-align: end;\n" " padding-inline-end: 1em;\n" "}\n" "/* date */\n" "td:first-child + td + td {\n" " padding-inline-start: 1em;\n" " padding-inline-end: .5em;\n" "}\n" "/* time */\n" "td:first-child + td + td + td {\n" " padding-inline-start: .5em;\n" "}\n" ".symlink {\n" " font-style: italic;\n" "}\n" ".dir ,\n" ".symlink ,\n" ".file {\n" " margin-inline-start: 20px;\n" "}\n" ".dir::before ,\n" ".file > img {\n" " margin-inline-end: 4px;\n" " margin-inline-start: -20px;\n" " max-width: 16px;\n" " max-height: 16px;\n" " vertical-align: middle;\n" "}\n" ".dir::before {\n" " content: url(resource://gre/res/html/folder.png);\n" "}\n" "</style>\n" "<link rel=\"stylesheet\" media=\"screen, projection\" type=\"text/css\"" " href=\"chrome://global/skin/dirListing/dirListing.css\">\n" "<script type=\"application/javascript\">\n" "'use strict';\n" "var gTable, gOrderBy, gTBody, gRows, gUI_showHidden;\n" "document.addEventListener(\"DOMContentLoaded\", function() {\n" " gTable = document.getElementsByTagName(\"table\")[0];\n" " gTBody = gTable.tBodies[0];\n" " if (gTBody.rows.length < 2)\n" " return;\n" " gUI_showHidden = document.getElementById(\"UI_showHidden\");\n" " var headCells = gTable.tHead.rows[0].cells,\n" " hiddenObjects = false;\n" " function rowAction(i) {\n" " return function(event) {\n" " event.preventDefault();\n" " orderBy(i);\n" " }\n" " }\n" " for (var i = headCells.length - 1; i >= 0; i--) {\n" " var anchor = document.createElement(\"a\");\n" " anchor.href = \"\";\n" " anchor.appendChild(headCells[i].firstChild);\n" " headCells[i].appendChild(anchor);\n" " headCells[i].addEventListener(\"click\", rowAction(i), true);\n" " }\n" " if (gUI_showHidden) {\n" " gRows = Array.slice(gTBody.rows);\n" " hiddenObjects = gRows.some(row => row.className == \"hidden-object\");\n" " }\n" " gTable.setAttribute(\"order\", \"\");\n" " if (hiddenObjects) {\n" " gUI_showHidden.style.display = \"block\";\n" " updateHidden();\n" " }\n" "}, \"false\");\n" "function compareRows(rowA, rowB) {\n" " var a = rowA.cells[gOrderBy].getAttribute(\"sortable-data\") || \"\";\n" " var b = rowB.cells[gOrderBy].getAttribute(\"sortable-data\") || \"\";\n" " var intA = +a;\n" " var intB = +b;\n" " if (a == intA && b == intB) {\n" " a = intA;\n" " b = intB;\n" " } else {\n" " a = a.toLowerCase();\n" " b = b.toLowerCase();\n" " }\n" " if (a < b)\n" " return -1;\n" " if (a > b)\n" " return 1;\n" " return 0;\n" "}\n" "function orderBy(column) {\n" " if (!gRows)\n" " gRows = Array.slice(gTBody.rows);\n" " var order;\n" " if (gOrderBy == column) {\n" " order = gTable.getAttribute(\"order\") == \"asc\" ? \"desc\" : \"asc\";\n" " } else {\n" " order = \"asc\";\n" " gOrderBy = column;\n" " gTable.setAttribute(\"order-by\", column);\n" " gRows.sort(compareRows);\n" " }\n" " gTable.removeChild(gTBody);\n" " gTable.setAttribute(\"order\", order);\n" " if (order == \"asc\")\n" " for (var i = 0; i < gRows.length; i++)\n" " gTBody.appendChild(gRows[i]);\n" " else\n" " for (var i = gRows.length - 1; i >= 0; i--)\n" " gTBody.appendChild(gRows[i]);\n" " gTable.appendChild(gTBody);\n" "}\n" "function updateHidden() {\n" " gTable.className = gUI_showHidden.getElementsByTagName(\"input\")[0].checked ?\n" " \"\" :\n" " \"remove-hidden\";\n" "}\n" "</script>\n"); buffer.AppendLiteral("<link rel=\"icon\" type=\"image/png\" href=\""); nsCOMPtr<nsIURI> innerUri = NS_GetInnermostURI(uri); if (!innerUri) return NS_ERROR_UNEXPECTED; nsCOMPtr<nsIFileURL> fileURL(do_QueryInterface(innerUri)); //XXX bug 388553: can't use skinnable icons here due to security restrictions if (fileURL) { //buffer.AppendLiteral("chrome://global/skin/dirListing/local.png"); buffer.AppendLiteral("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB" "AAAAAQCAYAAAAf8%2F9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9i" "ZSBJbWFnZVJlYWR5ccllPAAAAjFJREFUeNqsU8uOElEQPffR" "3XQ3ONASdBJCSBxHos5%2B3Bg3rvkCv8PElS78gPkO%2FATj" "QoUdO2ftrJiRh6aneTb9sOpC4weMN6lcuFV16pxDIfI8x12O" "YIDhcPiu2Wx%2B%2FHF5CW1Z6Jyegt%2FTNEWSJIjjGFEUIQ" "xDrFYrWFSzXC4%2FdLvd95pRKpXKy%2BpRFZ7nwaWo1%2BsG" "nQG2260BKJfLKJVKGI1GEEJw7ateryd0v993W63WEwjgxfn5" "obGYzgCbzcaEbdsIggDj8Riu6z6iUk9SYZMSx8W0LMsM%2FS" "KK75xnJlIq80anQXdbEp0OhcPJ0eiaJnGRMEyyPDsAKKUM9c" "lkYoDo3SZJzzSdp0VSKYmfV1co%2Bz580kw5KDIM8RbRfEnU" "f1HzxtQyMAGcaGruTKczMzEIaqhKifV6jd%2BzGQQB5llunF" "%2FM52BizC2K5sYPYvZcu653tjOM9O93wnYc08gmkgg4VAxi" "xfqFUJT36AYBZGd6PJkFCZnnlBxMp38gqIgLpZB0y4Nph18l" "yWh5FFbrOSxbl3V4G%2BVB7T4ajYYxTyuLtO%2BCvWGgJE1M" "c7JNsJEhvgw%2FQV4fo%2F24nbEsX2u1d5sVyn8sJO0ZAQiI" "YnFh%2BxrfLz%2Fj29cBS%2FO14zg3i8XigW3ZkErDtmKoeM" "%2BAJGRMnXeEPGKf0nCD1ydvkDzU9Jbc6OpR7WIw6L8lQ%2B" "4pQ1%2FlPF0RGM9Ns91Wmptk0GfB4EJkt77vXYj%2F8m%2B8" "y%2FkrwABHbz2H9V68DQAAAABJRU5ErkJggg%3D%3D"); } else { //buffer.AppendLiteral("chrome://global/skin/dirListing/remote.png"); buffer.AppendLiteral("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB" "AAAAAQCAYAAAAf8%2F9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9i" "ZSBJbWFnZVJlYWR5ccllPAAAAeBJREFUeNqcU81O20AQ%2Ft" "Z2AgQSYQRqL1UPVG2hAUQkxLEStz4DrXpLpD5Drz31Cajax%" "2Bghhx6qHIJURBTxIwQRwopCBbZjHMcOTrzermPipsSt1Iw0" "3p3ZmW%2B%2B2R0TxhgOD34wjCHZlQ0iDYz9yvEfhxMTCYhE" "QDIZhkxKd2sqzX2TOD2vBQCQhpPefng1ZP2dVPlLLdpL8SEM" "cxng%2Fbs0RIHhtgs4twxOh%2BHjZxvzDx%2F3GQQiDFISiR" "BLFMPKTRMollzcWECrDVhtxtdRVsL9youPxGj%2FbdfFlUZh" "tDyYbYqWRUdai1oQRZ5oHeHl2gNM%2B01Uqio8RlH%2Bnsaz" "JzNwXcq1B%2BiXPHprlEEymeBfXs1w8XxxihfyuXqoHqpoGj" "ZM04bddgG%2F9%2B8WGj87qDdsrK9m%2BoA%2BpbhQTDh2l1" "%2Bi2weNbSHMZyjvNXmVbqh9Fj5Oz27uEoP%2BSTxANruJs9" "L%2FT6P0ewqPx5nmiAG5f6AoCtN1PbJzuRyJAyDBzzSQYvEr" "f06yYxhGXlEa8H2KVGoasjwLx3Ewk858opQWXm%2B%2Fib9E" "QrBzclLLLy89xYvlpchvtixcX6uo1y%2FzsiwHrkIsgKbp%2" "BYWFOWicuqppoNTnStHzPFCPQhBEBOyGAX4JMADFetubi4BS" "YAAAAABJRU5ErkJggg%3D%3D"); } buffer.AppendLiteral("\">\n<title>"); // Everything needs to end in a /, // otherwise we end up linking to file:///foo/dirfile if (!mTextToSubURI) { mTextToSubURI = do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; } nsXPIDLCString encoding; rv = uri->GetOriginCharset(encoding); if (NS_FAILED(rv)) return rv; if (encoding.IsEmpty()) { encoding.AssignLiteral("UTF-8"); } nsXPIDLString unEscapeSpec; rv = mTextToSubURI->UnEscapeAndConvert(encoding, titleUri.get(), getter_Copies(unEscapeSpec)); // unescape may fail because // 1. file URL may be encoded in platform charset for backward compatibility // 2. query part may not be encoded in UTF-8 (see bug 261929) // so try the platform's default if this is file url if (NS_FAILED(rv) && isSchemeFile) { nsCOMPtr<nsIPlatformCharset> platformCharset(do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv)); NS_ENSURE_SUCCESS(rv, rv); nsAutoCString charset; rv = platformCharset->GetCharset(kPlatformCharsetSel_FileName, charset); NS_ENSURE_SUCCESS(rv, rv); rv = mTextToSubURI->UnEscapeAndConvert(charset.get(), titleUri.get(), getter_Copies(unEscapeSpec)); } if (NS_FAILED(rv)) return rv; nsXPIDLString htmlEscSpec; htmlEscSpec.Adopt(nsEscapeHTML2(unEscapeSpec.get(), unEscapeSpec.Length())); nsXPIDLString title; const char16_t* formatTitle[] = { htmlEscSpec.get() }; rv = mBundle->FormatStringFromName(u"DirTitle", formatTitle, sizeof(formatTitle)/sizeof(char16_t*), getter_Copies(title)); if (NS_FAILED(rv)) return rv; // we want to convert string bundle to NCR // to ensure they're shown in any charsets AppendNonAsciiToNCR(title, buffer); buffer.AppendLiteral("</title>\n"); // If there is a quote character in the baseUri, then // lets not add a base URL. The reason for this is that // if we stick baseUri containing a quote into a quoted // string, the quote character will prematurely close // the base href string. This is a fall-back check; // that's why it is OK to not use a base rather than // trying to play nice and escaping the quotes. See bug // 358128. if (!baseUri.Contains('"')) { // Great, the baseUri does not contain a char that // will prematurely close the string. Go ahead an // add a base href, but only do so if we're not // dealing with a resource URI. nsCOMPtr<nsIURI> originalUri; rv = channel->GetOriginalURI(getter_AddRefs(originalUri)); bool wasResource = false; if (NS_FAILED(rv) || NS_FAILED(originalUri->SchemeIs("resource", &wasResource)) || !wasResource) { buffer.AppendLiteral("<base href=\""); nsAdoptingCString htmlEscapedUri(nsEscapeHTML(baseUri.get())); buffer.Append(htmlEscapedUri); buffer.AppendLiteral("\" />\n"); } } else { NS_ERROR("broken protocol handler didn't escape double-quote."); } nsCString direction(NS_LITERAL_CSTRING("ltr")); nsCOMPtr<nsIXULChromeRegistry> reg = mozilla::services::GetXULChromeRegistryService(); if (reg) { bool isRTL = false; reg->IsLocaleRTL(NS_LITERAL_CSTRING("global"), &isRTL); if (isRTL) { direction.AssignLiteral("rtl"); } } buffer.AppendLiteral("</head>\n<body dir=\""); buffer.Append(direction); buffer.AppendLiteral("\">\n<h1>"); const char16_t* formatHeading[] = { htmlEscSpec.get() }; rv = mBundle->FormatStringFromName(u"DirTitle", formatHeading, sizeof(formatHeading)/sizeof(char16_t*), getter_Copies(title)); if (NS_FAILED(rv)) return rv; AppendNonAsciiToNCR(title, buffer); buffer.AppendLiteral("</h1>\n"); if (!parentStr.IsEmpty()) { nsXPIDLString parentText; rv = mBundle->GetStringFromName(u"DirGoUp", getter_Copies(parentText)); if (NS_FAILED(rv)) return rv; buffer.AppendLiteral("<p id=\"UI_goUp\"><a class=\"up\" href=\""); nsAdoptingCString htmlParentStr(nsEscapeHTML(parentStr.get())); buffer.Append(htmlParentStr); buffer.AppendLiteral("\">"); AppendNonAsciiToNCR(parentText, buffer); buffer.AppendLiteral("</a></p>\n"); } if (isSchemeFile) { nsXPIDLString showHiddenText; rv = mBundle->GetStringFromName(u"ShowHidden", getter_Copies(showHiddenText)); if (NS_FAILED(rv)) return rv; buffer.AppendLiteral("<p id=\"UI_showHidden\" style=\"display:none\"><label><input type=\"checkbox\" checked onchange=\"updateHidden()\">"); AppendNonAsciiToNCR(showHiddenText, buffer); buffer.AppendLiteral("</label></p>\n"); } buffer.AppendLiteral("<table>\n"); nsXPIDLString columnText; buffer.AppendLiteral(" <thead>\n" " <tr>\n" " <th>"); rv = mBundle->GetStringFromName(u"DirColName", getter_Copies(columnText)); if (NS_FAILED(rv)) return rv; AppendNonAsciiToNCR(columnText, buffer); buffer.AppendLiteral("</th>\n" " <th>"); rv = mBundle->GetStringFromName(u"DirColSize", getter_Copies(columnText)); if (NS_FAILED(rv)) return rv; AppendNonAsciiToNCR(columnText, buffer); buffer.AppendLiteral("</th>\n" " <th colspan=\"2\">"); rv = mBundle->GetStringFromName(u"DirColMTime", getter_Copies(columnText)); if (NS_FAILED(rv)) return rv; AppendNonAsciiToNCR(columnText, buffer); buffer.AppendLiteral("</th>\n" " </tr>\n" " </thead>\n"); buffer.AppendLiteral(" <tbody>\n"); aBuffer = buffer; return rv; }
// The feed version of nsContentUtils::CreateContextualFragment It // creates a fragment, but doesn't go to all the effort to preserve // context like innerHTML does, because feed DOMs shouldn't have that. NS_IMETHODIMP nsScriptableUnescapeHTML::ParseFragment(const nsAString &aFragment, PRBool aIsXML, nsIURI* aBaseURI, nsIDOMElement* aContextElement, nsIDOMDocumentFragment** aReturn) { NS_ENSURE_ARG(aContextElement); *aReturn = nsnull; nsresult rv; nsCOMPtr<nsIParser> parser = do_CreateInstance(kCParserCID, &rv); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIDocument> document; nsCOMPtr<nsIDOMDocument> domDocument; nsCOMPtr<nsIDOMNode> contextNode; contextNode = do_QueryInterface(aContextElement); contextNode->GetOwnerDocument(getter_AddRefs(domDocument)); document = do_QueryInterface(domDocument); NS_ENSURE_TRUE(document, NS_ERROR_NOT_AVAILABLE); // stop scripts nsRefPtr<nsScriptLoader> loader; PRBool scripts_enabled = PR_FALSE; if (document) { loader = document->ScriptLoader(); scripts_enabled = loader->GetEnabled(); } if (scripts_enabled) { loader->SetEnabled(PR_FALSE); } // Wrap things in a div or body for parsing, but it won't show up in // the fragment. nsAutoTArray<nsString, 2> tagStack; nsCAutoString base, spec; if (aIsXML) { // XHTML if (aBaseURI) { base.Append(NS_LITERAL_CSTRING(XHTML_DIV_TAG)); base.Append(NS_LITERAL_CSTRING(" xml:base=\"")); aBaseURI->GetSpec(spec); // nsEscapeHTML is good enough, because we only need to get // quotes, ampersands, and angle brackets char* escapedSpec = nsEscapeHTML(spec.get()); if (escapedSpec) base += escapedSpec; NS_Free(escapedSpec); base.Append(NS_LITERAL_CSTRING("\"")); tagStack.AppendElement(NS_ConvertUTF8toUTF16(base)); } else { tagStack.AppendElement(NS_LITERAL_STRING(XHTML_DIV_TAG)); } } else { // HTML tagStack.AppendElement(NS_LITERAL_STRING(HTML_BODY_TAG)); if (aBaseURI) { base.Append(NS_LITERAL_CSTRING((HTML_BASE_TAG))); base.Append(NS_LITERAL_CSTRING(" href=\"")); aBaseURI->GetSpec(spec); base = base + spec; base.Append(NS_LITERAL_CSTRING("\"")); tagStack.AppendElement(NS_ConvertUTF8toUTF16(base)); } } if (NS_SUCCEEDED(rv)) { nsCAutoString contentType; nsDTDMode mode; nsCOMPtr<nsIFragmentContentSink> sink; if (aIsXML) { mode = eDTDMode_full_standards; contentType = NS_LITERAL_CSTRING("application/xhtml+xml"); sink = do_CreateInstance(NS_XHTMLPARANOIDFRAGMENTSINK_CONTRACTID); } else { mode = eDTDMode_fragment; contentType = NS_LITERAL_CSTRING("text/html"); sink = do_CreateInstance(NS_HTMLPARANOIDFRAGMENTSINK_CONTRACTID); } if (sink) { sink->SetTargetDocument(document); nsCOMPtr<nsIContentSink> contentsink(do_QueryInterface(sink)); parser->SetContentSink(contentsink); rv = parser->ParseFragment(aFragment, nsnull, tagStack, aIsXML, contentType, mode); if (NS_SUCCEEDED(rv)) rv = sink->GetFragment(PR_TRUE, aReturn); } else { rv = NS_ERROR_FAILURE; } } if (scripts_enabled) loader->SetEnabled(PR_TRUE); return rv; }