annotate LICENSE-MERGELY.html @ 6532:33b71a130b16

templates: properly escape inline JavaScript values TLDR: Kallithea has issues with escaping values for use in inline JS. Despite judicious poking of the code, no actual security vulnerabilities have been found, just lots of corner-case bugs. This patch fixes those, and hardens the code against actual security issues. The long version: To embed a Python value (typically a 'unicode' plain-text value) in a larger file, it must be escaped in a context specific manner. Example: >>> s = u'<script>alert("It\'s a trap!");</script>' 1) Escaped for insertion into HTML element context >>> print cgi.escape(s) &lt;script&gt;alert("It's a trap!");&lt;/script&gt; 2) Escaped for insertion into HTML element or attribute context >>> print h.escape(s) &lt;script&gt;alert(&#34;It&#39;s a trap!&#34;);&lt;/script&gt; This is the default Mako escaping, as usually used by Kallithea. 3) Encoded as JSON >>> print json.dumps(s) "<script>alert(\"It's a trap!\");</script>" 4) Escaped for insertion into a JavaScript file >>> print '(' + json.dumps(s) + ')' ("<script>alert(\"It's a trap!\");</script>") The parentheses are not actually required for strings, but may be needed to avoid syntax errors if the value is a number or dict (object). 5) Escaped for insertion into a HTML inline <script> element >>> print h.js(s) ("\x3cscript\x3ealert(\"It's a trap!\");\x3c/script\x3e") Here, we need to combine JS and HTML escaping, further complicated by the fact that "<script>" tag contents can either be parsed in XHTML mode (in which case '<', '>' and '&' must additionally be XML escaped) or HTML mode (in which case '</script>' must be escaped, but not using HTML escaping, which is not available in HTML "<script>" tags). Therefore, the XML special characters (which can only occur in string literals) are escaped using JavaScript string literal escape sequences. (This, incidentally, is why modern web security best practices ban all use of inline JavaScript...) Unsurprisingly, Kallithea does not do (5) correctly. In most cases, Kallithea might slap a pair of single quotes around the HTML escaped Python value. A typical benign example: $('#child_link').html('${_('No revisions')}'); This works in English, but if a localized version of the string contains an apostrophe, the result will be broken JavaScript. In the more severe cases, where the text is user controllable, it leaves the door open to injections. In this example, the script inserts the string as HTML, so Mako's implicit HTML escaping makes sense; but in many other cases, HTML escaping is actually an error, because the value is not used by the script in an HTML context. The good news is that the HTML escaping thwarts attempts at XSS, since it's impossible to inject syntactically valid JavaScript of any useful complexity. It does allow JavaScript errors and gibberish to appear on the page, though. In these cases, the escaping has been fixed to use either the new 'h.js' helper, which does JavaScript escaping (but not HTML escaping), OR the new 'h.jshtml' helper (which does both), in those cases where it was unclear if the value might be used (by the script) in an HTML context. Some of these can probably be "relaxed" from h.jshtml to h.js later, but for now, using h.jshtml fixes escaping and doesn't introduce new errors. In a few places, Kallithea JSON encodes values in the controller, then inserts the JSON (without any further escaping) into <script> tags. This is also wrong, and carries actual risk of XSS vulnerabilities. However, in all cases, security vulnerabilities were narrowly avoided due to other filtering in Kallithea. (E.g. many special characters are banned from appearing in usernames.) In these cases, the escaping has been fixed and moved to the template, making it immediately visible that proper escaping has been performed. Mini-FAQ (frequently anticipated questions): Q: Why do everything in one big, hard to review patch? Q: Why add escaping in specific case FOO, it doesn't seem needed? Because the goal here is to have "escape everywhere" as the default policy, rather than identifying individual bugs and fixing them one by one by adding escaping where needed. As such, this patch surely introduces a lot of needless escaping. This is no different from how Mako/Pylons HTML escape everything by default, even when not needed: it's errs on the side of needless work, to prevent erring on the side of skipping required (and security critical) work. As for reviewability, the most important thing to notice is not where escaping has been introduced, but any places where it might have been missed (or where h.jshtml is needed, but h.js is used). Q: The added escaping is kinda verbose/ugly. That is not a question, but yes, I agree. Hopefully it'll encourage us to move away from inline JavaScript altogether. That's a significantly larger job, though; with luck this patch will keep us safe and secure until such a time as we can implement the real fix. Q: Why not use Mako filter syntax ("${val|h.js}")? Because of long-standing Mako bug #140, preventing use of 'h' in filters. Q: Why not work around bug #140, or even use straight "${val|js}"? Because Mako still applies the default h.escape filter before the explicitly specified filters. Q: Where do we go from here? Longer term, we should stop doing variable expansions in script blocks, and instead pass data to JS via e.g. data attributes, or asynchronously using AJAX calls. Once we've done that, we can remove inline JavaScript altogether in favor of separate script files, and set a strict Content Security Policy explicitly blocking inline scripting, and thus also the most common kind of cross-site scripting attack.
author Søren Løvborg <sorenl@unity3d.com>
date Tue, 28 Feb 2017 17:19:00 +0100
parents aa3b55946089
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4125
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
1 <!DOCTYPE html>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
2 <html lang="en">
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
3 <!--[if IE]>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
4 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
5 <![endif]-->
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
6 <head>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
7 <meta charset="utf-8" /><title>Mergely License</title>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
9 <meta name="description" content="Mergely license requirements for open source software and commercial software" />
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
10 <meta name="keywords" content="diff,merge,compare,compare documents,js diff,javascript diff,comparison,online diff,difference,file,text,unix,patch,algorithm,saas,longest common subsequence,diff online" />
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
11 <meta name="author" content="Jamie Peabody" />
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
12 <meta name="author" content="Jamie Peabody" />
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
13 <link rel="shortcut icon" href="http://www.mergely.com/favicon.ico" />
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
14 <link href='http://fonts.googleapis.com/css?family=Noto+Sans:400,700' rel='stylesheet' type='text/css' />
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
15 <link href='fonts/berlin-sans-fb-demi.css' rel='stylesheet' type='text/css' />
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
16 <link href='style/mergely.css' rel='stylesheet' type='text/css' />
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
17 <link href='/Mergely/lib/mergely.css' rel='stylesheet' type='text/css' />
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
18 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
19 <script type="text/javascript">
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
20 var _gaq = _gaq || [];
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
21 _gaq.push(['_setAccount', 'UA-85576-5']);
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
22 _gaq.push(['_trackPageview']);
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
23 (function() {
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
24 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
25 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
26 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
27 })();
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
28 </script>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
29 </head>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
30 <body>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
31 <div id="page">
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
32 <div id="content">
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
33 <div id="header">
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
34 <h1><span>Mergely License - Closed Distribution License</span></h1>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
35 <div id="options">
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
36 <a href="/editor" class="button">Online Diff</a>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
37 <a href="/download" class="button">Download</a>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
38 </div>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
39 <nav>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
40 <ul>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
41 <li><a href="/">Home</a></li> <li><a href="/doc">Documentation</a></li> <li><a href="/about">About Mergely</a></li> <li><a href="/license">License</a></li> <li><a href="#footer">Contact</a></li> </ul>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
42 </nav>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
43 </div>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
44
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
45 <div id="main">
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
46 <h1>Mergely License</h1>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
47 <p>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
48 All Mergely code is Copyright 2014 by Jamie Peabody.
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
49 Mergely is distributed under the
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
50 <a href="http://www.gnu.org/licenses/gpl.html">GPL</a>,
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
51 <a href="http://www.gnu.org/licenses/lgpl.html">LGPL</a>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
52 and
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
53 <a href="http://www.mozilla.org/MPL/MPL-1.1.html">MPL</a> open source licenses.
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
54 This triple <b>copyleft</b> licensing model avoids incompatibility with other open
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
55 source licenses. These open source licenses are specially indicated for:
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
56 <ul>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
57 <li>Integrating Mergely into Open Source software;</li>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
58 <li>Personal and educational use of Mergely;</li>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
59 <li>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
60 Integrating Mergely in commercial software, taking care of satisfying
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
61 the Open Source licenses terms, while not able or interested on supporting
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
62 Mergely and its development.
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
63 </li>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
64 </ul>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
65 </p>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
66 <h2>Mergely Commercial License - Closed Distribution License - CDL</h2>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
67 <p>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
68 You may contact <a href="mailto:jamie.peabody@gmail.com">Jamie Peabody</a> to enquire about
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
69 obtaining a CDL license.
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
70 </p>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
71 <p>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
72 This license offers a very flexible way to integrate Mergely in your commercial
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
73 application. These are the main advantages it offers over an Open Source license:
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
74 </p>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
75 <p>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
76 Modifications and enhancements do not need to be released under an Open
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
77 Source license; There is no need to distribute any Open Source license terms
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
78 along with your product and no reference to it have to be done; You do not have
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
79 to mention any reference to Mergely in your product; Mergely source code does not
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
80 have to be distributed with your product; You can remove any file from Mergely
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
81 when integrating it with your product.
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
82 </p>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
83 <p>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
84 The CDL is a lifetime license valid for all previous releases of Mergely published
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
85 prior to the year of purchase, and any releases in the following year. Please select
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
86 the license option that best fit your needs above. It includes 1 year of
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
87 <b>personal e-mail support</b>.
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
88 </p>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
89 <h2>Third party codes</h2>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
90 <p>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
91 Mergely utilizes <b>CodeMirror</b>, a third-party library released under an
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
92 <a href="http://en.wikipedia.org/wiki/MIT_License">MIT</a>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
93 license. Also used is <b>jQuery</b> and is released under the
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
94 <a href="http://en.wikipedia.org/wiki/MIT_License">MIT</a> or
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
95 <a href="http://www.gnu.org/licenses/gpl.html">GPL</a> Version 2 license.
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
96 </p>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
97 </div>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
98
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
99 <div id="footer">
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
100 <a href="/download" class="download">Download</a>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
101 <ul>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
102 <li id="google-plus"><a target="_blank" href="http://groups.google.com/group/mergely">http://groups.google.com/group/mergely</a></li>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
103 <li id="github"><a target="_blank" href="https://github.com/wickedest/Mergely">https://github.com/wickedest/Mergely</a></li>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
104 <li id="email"><a target="_blank" href="mailto:jamie.peabody@gmail.com">jamie.peabody@gmail.com</a></li>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
105 </ul>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
106 </div>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
107 </div>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
108 <div id="copyright">By <b>Jamie Peabody</b></div>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
109 </div>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
110 </body>
aa3b55946089 Migrate to Mergely 3.3.4.
"Bradley M. Kuhn" <bkuhn@ebb.org>
parents:
diff changeset
111 </html>