docshell/resources/content/netError.xhtml

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

     1 <?xml version="1.0" encoding="UTF-8"?>
     3 <!DOCTYPE html [
     4   <!ENTITY % htmlDTD
     5     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
     6     "DTD/xhtml1-strict.dtd">
     7   %htmlDTD;
     8   <!ENTITY % netErrorDTD
     9     SYSTEM "chrome://global/locale/netError.dtd">
    10   %netErrorDTD;
    11   <!ENTITY % globalDTD
    12     SYSTEM "chrome://global/locale/global.dtd">
    13   %globalDTD;
    14 ]>
    16 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    17    - License, v. 2.0. If a copy of the MPL was not distributed with this
    18    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
    20 <html xmlns="http://www.w3.org/1999/xhtml">
    21   <head>
    22     <title>&loadError.label;</title>
    23     <link rel="stylesheet" href="chrome://global/skin/netError.css" type="text/css" media="all" />
    24     <!-- If the location of the favicon is changed here, the FAVICON_ERRORPAGE_URL symbol in
    25          toolkit/components/places/src/nsFaviconService.h should be updated. -->
    26     <link rel="icon" type="image/png" id="favicon" href="chrome://global/skin/icons/warning-16.png"/>
    28     <script type="application/javascript"><![CDATA[
    29       // Error url MUST be formatted like this:
    30       //   moz-neterror:page?e=error&u=url&d=desc
    31       //
    32       // or optionally, to specify an alternate CSS class to allow for
    33       // custom styling and favicon:
    34       //
    35       //   moz-neterror:page?e=error&u=url&s=classname&d=desc
    37       // Note that this file uses document.documentURI to get
    38       // the URL (with the format from above). This is because
    39       // document.location.href gets the current URI off the docshell,
    40       // which is the URL displayed in the location bar, i.e.
    41       // the URI that the user attempted to load.
    43       function getErrorCode()
    44       {
    45         var url = document.documentURI;
    46         var error = url.search(/e\=/);
    47         var duffUrl = url.search(/\&u\=/);
    48         return decodeURIComponent(url.slice(error + 2, duffUrl));
    49       }
    51       function getCSSClass()
    52       {
    53         var url = document.documentURI;
    54         var matches = url.match(/s\=([^&]+)\&/);
    55         // s is optional, if no match just return nothing
    56         if (!matches || matches.length < 2)
    57           return "";
    59         // parenthetical match is the second entry
    60         return decodeURIComponent(matches[1]);
    61       }
    63       function getDescription()
    64       {
    65         var url = document.documentURI;
    66         var desc = url.search(/d\=/);
    68         // desc == -1 if not found; if so, return an empty string
    69         // instead of what would turn out to be portions of the URI
    70         if (desc == -1)
    71           return "";
    73         return decodeURIComponent(url.slice(desc + 2));
    74       }
    76       function retryThis(buttonEl)
    77       {
    78         // Note: The application may wish to handle switching off "offline mode"
    79         // before this event handler runs, but using a capturing event handler.
    81         // Session history has the URL of the page that failed
    82         // to load, not the one of the error page. So, just call
    83         // reload(), which will also repost POST data correctly.
    84         try {
    85           location.reload();
    86         } catch (e) {
    87           // We probably tried to reload a URI that caused an exception to
    88           // occur;  e.g. a nonexistent file.
    89         }
    91         buttonEl.disabled = true;
    92       }
    94       function initPage()
    95       {
    96         var err = getErrorCode();
    98         // if it's an unknown error or there's no title or description
    99         // defined, get the generic message
   100         var errTitle = document.getElementById("et_" + err);
   101         var errDesc  = document.getElementById("ed_" + err);
   102         if (!errTitle || !errDesc)
   103         {
   104           errTitle = document.getElementById("et_generic");
   105           errDesc  = document.getElementById("ed_generic");
   106         }
   108         var title = document.getElementById("errorTitleText");
   109         if (title)
   110         {
   111           title.parentNode.replaceChild(errTitle, title);
   112           // change id to the replaced child's id so styling works
   113           errTitle.id = "errorTitleText";
   114         }
   116         var sd = document.getElementById("errorShortDescText");
   117         if (sd)
   118           sd.textContent = getDescription();
   120         var ld = document.getElementById("errorLongDesc");
   121         if (ld)
   122         {
   123           ld.parentNode.replaceChild(errDesc, ld);
   124           // change id to the replaced child's id so styling works
   125           errDesc.id = "errorLongDesc";
   126         }
   128         // remove undisplayed errors to avoid bug 39098
   129         var errContainer = document.getElementById("errorContainer");
   130         errContainer.parentNode.removeChild(errContainer);
   132         var className = getCSSClass();
   133         if (className && className != "expertBadCert") {
   134           // Associate a CSS class with the root of the page, if one was passed in,
   135           // to allow custom styling.
   136           // Not "expertBadCert" though, don't want to deal with the favicon
   137           document.documentElement.className = className;
   139           // Also, if they specified a CSS class, they must supply their own
   140           // favicon.  In order to trigger the browser to repaint though, we
   141           // need to remove/add the link element. 
   142           var favicon = document.getElementById("favicon");
   143           var faviconParent = favicon.parentNode;
   144           faviconParent.removeChild(favicon);
   145           favicon.setAttribute("href", "chrome://global/skin/icons/" + className + "_favicon.png");
   146           faviconParent.appendChild(favicon);
   147         }
   148         if (className == "expertBadCert") {
   149           showSecuritySection();
   150         }
   152         if (err == "remoteXUL") {
   153           // Remove the "Try again" button for remote XUL errors given that
   154           // it is useless.
   155           document.getElementById("errorTryAgain").style.display = "none";
   156         }
   158         if (err == "cspFrameAncestorBlocked") {
   159           // Remove the "Try again" button for CSP frame ancestors violation, since it's
   160           // almost certainly useless. (Bug 553180)
   161           document.getElementById("errorTryAgain").style.display = "none";
   162         }
   164         if (err == "nssBadCert") {
   165           // Remove the "Try again" button for security exceptions, since it's
   166           // almost certainly useless.
   167           document.getElementById("errorTryAgain").style.display = "none";
   168           document.getElementById("errorPageContainer").setAttribute("class", "certerror");
   169           addDomainErrorLink();
   170         }
   171         else {
   172           // Remove the override block for non-certificate errors.  CSS-hiding
   173           // isn't good enough here, because of bug 39098
   174           var secOverride = document.getElementById("securityOverrideDiv");
   175           secOverride.parentNode.removeChild(secOverride);
   176         }
   177       }
   179       function showSecuritySection() {
   180         // Swap link out, content in
   181         document.getElementById('securityOverrideContent').style.display = '';
   182         document.getElementById('securityOverrideLink').style.display = 'none';
   183       }
   185       /* In the case of SSL error pages about domain mismatch, see if
   186          we can hyperlink the user to the correct site.  We don't want
   187          to do this generically since it allows MitM attacks to redirect
   188          users to a site under attacker control, but in certain cases
   189          it is safe (and helpful!) to do so.  Bug 402210
   190       */
   191       function addDomainErrorLink() {
   192         // Rather than textContent, we need to treat description as HTML
   193         var sd = document.getElementById("errorShortDescText");
   194         if (sd) {
   195           var desc = getDescription();
   197           // sanitize description text - see bug 441169
   199           // First, find the index of the <a> tag we care about, being careful not to
   200           // use an over-greedy regex
   201           var re = /<a id="cert_domain_link" title="([^"]+)">/;
   202           var result = re.exec(desc);
   203           if(!result)
   204             return;
   206           // Remove sd's existing children
   207           sd.textContent = "";
   209           // Everything up to the link should be text content
   210           sd.appendChild(document.createTextNode(desc.slice(0, result.index)));
   212           // Now create the link itself
   213           var anchorEl = document.createElement("a");
   214           anchorEl.setAttribute("id", "cert_domain_link");
   215           anchorEl.setAttribute("title", result[1]);
   216           anchorEl.appendChild(document.createTextNode(result[1]));
   217           sd.appendChild(anchorEl);
   219           // Finally, append text for anything after the closing </a>
   220           sd.appendChild(document.createTextNode(desc.slice(desc.indexOf("</a>") + "</a>".length)));
   221         }
   223         var link = document.getElementById('cert_domain_link');
   224         if (!link)
   225           return;
   227         var okHost = link.getAttribute("title");
   228         var thisHost = document.location.hostname;
   229         var proto = document.location.protocol;
   231         // If okHost is a wildcard domain ("*.example.com") let's
   232         // use "www" instead.  "*.example.com" isn't going to
   233         // get anyone anywhere useful. bug 432491
   234         okHost = okHost.replace(/^\*\./, "www.");
   236         /* case #1: 
   237          * example.com uses an invalid security certificate.
   238          *
   239          * The certificate is only valid for www.example.com
   240          *
   241          * Make sure to include the "." ahead of thisHost so that
   242          * a MitM attack on paypal.com doesn't hyperlink to "notpaypal.com"
   243          *
   244          * We'd normally just use a RegExp here except that we lack a
   245          * library function to escape them properly (bug 248062), and
   246          * domain names are famous for having '.' characters in them,
   247          * which would allow spurious and possibly hostile matches.
   248          */
   249         if (endsWith(okHost, "." + thisHost))
   250           link.href = proto + okHost;
   252         /* case #2:
   253          * browser.garage.maemo.org uses an invalid security certificate.
   254          *
   255          * The certificate is only valid for garage.maemo.org
   256          */
   257         if (endsWith(thisHost, "." + okHost))
   258           link.href = proto + okHost;
   259       }
   261       function endsWith(haystack, needle) {
   262         return haystack.slice(-needle.length) == needle;
   263       }
   265     ]]></script>
   266   </head>
   268   <body dir="&locale.dir;">
   270     <!-- ERROR ITEM CONTAINER (removed during loading to avoid bug 39098) -->
   271     <div id="errorContainer">
   272       <div id="errorTitlesContainer">
   273         <h1 id="et_generic">&generic.title;</h1>
   274         <h1 id="et_dnsNotFound">&dnsNotFound.title;</h1>
   275         <h1 id="et_fileNotFound">&fileNotFound.title;</h1>
   276         <h1 id="et_malformedURI">&malformedURI.title;</h1>
   277         <h1 id="et_unknownProtocolFound">&unknownProtocolFound.title;</h1>
   278         <h1 id="et_connectionFailure">&connectionFailure.title;</h1>
   279         <h1 id="et_netTimeout">&netTimeout.title;</h1>
   280         <h1 id="et_redirectLoop">&redirectLoop.title;</h1>
   281         <h1 id="et_unknownSocketType">&unknownSocketType.title;</h1>
   282         <h1 id="et_netReset">&netReset.title;</h1>
   283         <h1 id="et_notCached">&notCached.title;</h1>
   284         <h1 id="et_netOffline">&netOffline.title;</h1>
   285         <h1 id="et_netInterrupt">&netInterrupt.title;</h1>
   286         <h1 id="et_deniedPortAccess">&deniedPortAccess.title;</h1>
   287         <h1 id="et_proxyResolveFailure">&proxyResolveFailure.title;</h1>
   288         <h1 id="et_proxyConnectFailure">&proxyConnectFailure.title;</h1>
   289         <h1 id="et_contentEncodingError">&contentEncodingError.title;</h1>
   290         <h1 id="et_unsafeContentType">&unsafeContentType.title;</h1>
   291         <h1 id="et_nssFailure2">&nssFailure2.title;</h1>
   292         <h1 id="et_nssBadCert">&nssBadCert.title;</h1>
   293         <h1 id="et_malwareBlocked">&malwareBlocked.title;</h1>
   294         <h1 id="et_cspFrameAncestorBlocked">&cspFrameAncestorBlocked.title;</h1>
   295         <h1 id="et_remoteXUL">&remoteXUL.title;</h1>
   296         <h1 id="et_corruptedContentError">&corruptedContentError.title;</h1>
   297       </div>
   298       <div id="errorDescriptionsContainer">
   299         <div id="ed_generic">&generic.longDesc;</div>
   300         <div id="ed_dnsNotFound">&dnsNotFound.longDesc;</div>
   301         <div id="ed_fileNotFound">&fileNotFound.longDesc;</div>
   302         <div id="ed_malformedURI">&malformedURI.longDesc;</div>
   303         <div id="ed_unknownProtocolFound">&unknownProtocolFound.longDesc;</div>
   304         <div id="ed_connectionFailure">&connectionFailure.longDesc;</div>
   305         <div id="ed_netTimeout">&netTimeout.longDesc;</div>
   306         <div id="ed_redirectLoop">&redirectLoop.longDesc;</div>
   307         <div id="ed_unknownSocketType">&unknownSocketType.longDesc;</div>
   308         <div id="ed_netReset">&netReset.longDesc;</div>
   309         <div id="ed_notCached">&notCached.longDesc;</div>
   310         <div id="ed_netOffline">&netOffline.longDesc2;</div>
   311         <div id="ed_netInterrupt">&netInterrupt.longDesc;</div>
   312         <div id="ed_deniedPortAccess">&deniedPortAccess.longDesc;</div>
   313         <div id="ed_proxyResolveFailure">&proxyResolveFailure.longDesc;</div>
   314         <div id="ed_proxyConnectFailure">&proxyConnectFailure.longDesc;</div>
   315         <div id="ed_contentEncodingError">&contentEncodingError.longDesc;</div>
   316         <div id="ed_unsafeContentType">&unsafeContentType.longDesc;</div>
   317         <div id="ed_nssFailure2">&nssFailure2.longDesc;</div>
   318         <div id="ed_nssBadCert">&nssBadCert.longDesc2;</div>
   319         <div id="ed_malwareBlocked">&malwareBlocked.longDesc;</div>
   320         <div id="ed_cspFrameAncestorBlocked">&cspFrameAncestorBlocked.longDesc;</div>
   321         <div id="ed_remoteXUL">&remoteXUL.longDesc;</div>
   322         <div id="ed_corruptedContentError">&corruptedContentError.longDesc;</div>
   323       </div>
   324     </div>
   326     <!-- PAGE CONTAINER (for styling purposes only) -->
   327     <div id="errorPageContainer">
   329       <!-- Error Title -->
   330       <div id="errorTitle">
   331         <h1 id="errorTitleText" />
   332       </div>
   334       <!-- LONG CONTENT (the section most likely to require scrolling) -->
   335       <div id="errorLongContent">
   337         <!-- Short Description -->
   338         <div id="errorShortDesc">
   339           <p id="errorShortDescText" />
   340         </div>
   342         <!-- Long Description (Note: See netError.dtd for used XHTML tags) -->
   343         <div id="errorLongDesc" />
   345         <!-- Override section - For ssl errors only.  Removed on init for other
   346              error types.  -->
   347         <div id="securityOverrideDiv">
   348           <a id="securityOverrideLink" href="javascript:showSecuritySection();" >&securityOverride.linkText;</a>
   349           <div id="securityOverrideContent" style="display: none;">&securityOverride.warningContent;</div>
   350         </div>
   351       </div>
   353       <!-- Retry Button -->
   354       <button id="errorTryAgain" autocomplete="off" onclick="retryThis(this);">&retry.label;</button>
   355       <script>
   356         // Only do autofocus if we're the toplevel frame; otherwise we
   357         // don't want to call attention to ourselves!  The key part is
   358         // that autofocus happens on insertion into the tree, so we
   359         // can remove the button, add @autofocus, and reinsert the
   360         // button.
   361         if (window.top == window) {
   362             var button = document.getElementById("errorTryAgain");
   363             var nextSibling = button.nextSibling;
   364             var parent = button.parentNode;
   365             parent.removeChild(button);
   366             button.setAttribute("autofocus", "true");
   367             parent.insertBefore(button, nextSibling);
   368         }
   369       </script>
   371     </div>
   373     <!--
   374     - Note: It is important to run the script this way, instead of using
   375     - an onload handler. This is because error pages are loaded as
   376     - LOAD_BACKGROUND, which means that onload handlers will not be executed.
   377     -->
   378     <script type="application/javascript">initPage();</script>
   380   </body>
   381 </html>

mercurial