Fri, 16 Jan 2015 04:50:19 +0100
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">¬Cached.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">¬Cached.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>