root/10kz/shell/ajax-xml-pulldown.html

Revision 43, 11.8 kB (checked in by jm3, 2 years ago)
  • set Id property on all text-based files
  • correctly handling the "no keys found" case with link to GPG help page (just a stub at this point)
  • Property svn:keywords set to Id
Line 
1 <html>
2 <head>
3
4         <style type="text/css">
5                 input, textarea {
6                         color: red;
7                 }
8                 input.debugging, textarea.debugging {
9                         background-color: #eeeeee;
10                         color: #888888;
11                 }
12         </style>
13
14 <script language="javascript">
15
16         // FIXME: needs to change to use GM_xmlhttpRequest because the stock XMLHTTPRequest won't work from gmail / google to localhost:6667
17         function getX() {
18                 var x = false;
19                 if (window.XMLHttpRequest) { // Mozilla/Safari
20                         x = new XMLHttpRequest();
21                         x.overrideMimeType('text/xml');
22                 } else if (window.ActiveXObject) { // IE
23                         x = new ActiveXObject("Microsoft.XMLHTTP");
24                 }
25                 return x;
26         }
27
28         function inject_ciphertext() {
29                 var ct = ""
30                 + "-----BEGIN PGP MESSAGE-----\n"
31                 + "Version: GnuPG v1.2.2 (Darwin)\n"
32                 + "\n"
33                 + "hQQOAyagq+4wmaWEEBAAgvjyvMdVpYzZMPBcxohT3ovppu5QrbNXNyEFfYSlK2SZ\n"
34                 + "Pg8jeqSYrZDy5/AkF2+ZwwerPbhdQ2nD5AbZGJwPUice5+SK63e7CMdi/vuQBDdx\n"
35                 + "zuWexVZ+yhTmB2qv6fV2WYTX9pRKViSiK6VTbC4BtNSOWGP1pJVeZOf93tN+SGyS\n"
36                 + "5Ayv1Mew4pS1QSBJ5DvjKks/Wdp6syyKBp5SAIVVdXCXTtEHDEzXsjte2/FL0Zzm\n"
37                 + "Oj3KhfJM8aWnwe8wL+wQbUrrBAjdmst+aHi/W7P1RmbBZz+T1Q3VMA3yshqQr4Yj\n"
38                 + "2X68lTeBYFh3/IZQJhUPlXOh61eMix+4512AvaLNRvEeZ5gL/PfLAF3pngLvjszI\n"
39                 + "GUg6GTvNcDXzgMvPYvCvIMKcN6t7deHDPdQLg98YuaVt9NXmqPvR8yaNlE3uP/y2\n"
40                 + "QR/9pJYKF8Pn2T1fueqhHKteZfw7oecxxk4csU9PagMyncllTSOFu74es7QT0noa\n"
41                 + "knolISrSP/g7NbK5ZSPAmBVyOuDS+cQ9MIoILzquEZiJBCMamrBFlZ857YnEETTi\n"
42                 + "R0MZWadJxGiFVkPSw8eY+GKHlKjELOulK9fByDwf5jaqT/Ld0bbkqM6rX91PHhkm\n"
43                 + "JP+V788tSAHaQZKUhbP904aROPHCyQn2BNom2D1y8jByq1n2HoktDpWbypj6SyIQ\n"
44                 + "AIUpJUAYICwe1TY8gVq8CDcyZqUx5Sb5Ab0Fc21CsNKcaZwGYN44cf0nhIRQKVSq\n"
45                 + "KN47OSFeC+e7vV414Kg7AV0A7MjFdO4Wf9FnPcu8l6tGLsXLuk+c1CmFEokT06AI\n"
46                 + "avZ6iR0jUO3O3TBRSOebjgPW8ihbzESCeklPfSx0NdPBODRHdlpwSoWUae3ae+42\n"
47                 + "7KFBogPBiuqC1ErUBLTDpnjdrIBa/NMax5huEjIVWtR6x6/tCoYLKJlwzis/ofiK\n"
48                 + "5ZhEwB2LCtWt1ev2HxyVRYDgA2i200lEqhDCky/51Q8hIahWFhkgP6lO3Irl9Et5\n"
49                 + "iiR1hOYqzEDdrFYeFa9ZQvbklgNysx+Wd4eX7m6ai5a0mKrFH/5aZ9rrtqqfsloT\n"
50                 + "W4dnOUS/JCaMAQgt7gp6v9uzcAI9cTLACNC2Kt1H6JGIPfw9EkLXIbZ6i1lh5IU5\n"
51                 + "DeETe3/NIfgkR4aFkUe04cSM32nrHN8HpBz55GCq8Dgdw4nz3p8L+8bCoRQIuxlq\n"
52                 + "X66qBq9hdKYc7GM43iSirT3YpIZAjev7+vK3Yv2MBerDeoQ4EADkUZrT55Xxg4o9\n"
53                 + "nt0Gr/YaUUpvuR/7lGmrwWXsvgYm05Ushs0j0jW1af1U1TlHs6TiNqVMUeybQ0f/\n"
54                 + "cbsuL1Ek+VtnLktC8fIjxKpyMi7GGMX0U5BLx+Wk2qashQEOA6wuJQmnMH+fEAP6\n"
55                 + "AxlHlps9Zi6/1WmE/lrct9KaZkgmnBCXoiecxk3485ESvR/1V+9cEZohYzm76C7h\n"
56                 + "tCHH5vM921KV5UFyXMG2Vm8DTQKCcr0ZePIj4gUdlrNbKsXXrJFyNfgnVTLvY4M5\n"
57                 + "OOZXz+dSaHAjb4RpyuwVXsu10BqHJzyIeKMn+mKNSQMEAIdzGrLH/ObCF7sFkUcc\n"
58                 + "539Mw4XFE7cEdXle+WiyWXOm6QH70++o2d5k3G6WYNgsuXbZAHoRp5AmT2H3WEUE\n"
59                 + "tCAUwBQuRSgDp/A6m9LmrJVuzmcRvaNeX+qz4eSVl4B4sGA4qMjsTZ/G30GDYY4b\n"
60                 + "/UllP63rxPdcnU8ItAAz51v7hIwDxatmRJESvFEBBADJ3tgm2AdE99Wk6dQ/+vrV\n"
61                 + "CVRaPaTrbVNBv1YLjNZ1SfANACKfr/qCVwVQS+vRlUV9FBaLH6/Vv+/Hc+l4P+pt\n"
62                 + "Q8Tt+zbZ3ub1tCtuXqxyM2RZgT4ugDPUrUPBSFzUJw8+OizJC0XE1L2OHcTS5Eso\n"
63                 + "SezfK4RHBUy7tukNmp6n18lAr6vIxAN4JP6YUmYd+VFd0h83rZBpOp/vltgZf0xs\n"
64                 + "UrkCepQb33uwUaUH7YyaWjDuFX32XX+UG3PBJKyOdQAXag==\n"
65                 + "=Xm/3\n"
66                 + "-----END PGP MESSAGE-----\n";
67                 var pt = document.getElementById( "plaintext" );
68                 pt.value = ct;
69         }
70
71         function get_keys(url, strSubmit ) {
72                 var x = getX();
73                 x.open('POST', url, true);
74                 x.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
75                 x.onreadystatechange = function() {
76                         if( x.readyState == 4 && x.responseText != "" ) {
77                                 document.forms[0].result.value = x.responseText;
78                                 pulldown_from_keys( x.responseText );
79                         }
80                 }
81                 x.send(strSubmit);
82         }
83
84         // constant:
85         var BAIL_WITH_ERROR = "bail with error";
86
87         function build_gpg_qs() {
88                 var strSubmit = "";
89                 var k = document.getElementById( "gpg_key_id" );
90                 if( k.childNodes.length == 0 )
91                         strSubmit += ( "key_id=" + escape( k.value ));
92                 else
93                         strSubmit += ( "key_id=" + escape( k[k.selectedIndex].value ));
94                
95                 // FIXME: detect empty message text and bail accordingly
96                 var pt = document.getElementById( "plaintext" ).value;
97                 // HACK: FF javascript not correctly url-encoding pluses in textareas, so we do it ourselves...
98                 pt = pt.replace(/\+/g, "__PLUS__");
99                 strSubmit += ( "&plaintext=" + escape( pt ));
100                
101                 var pp = document.getElementById( "passphrase" );
102                 if( pp ) {
103                         if( pp.value.length != 0 )
104                                 strSubmit += ( "&passphrase=" + escape( pp.value ));
105                         else
106                                 return BAIL_WITH_ERROR;
107                 }
108                
109                 // FIXME: detect empty recipients field and bail appropriately
110                 var r = document.getElementById( "recipients" );
111                 strSubmit += ( "&recipients=" + escape( r.value ));
112
113                 return strSubmit;
114         }
115
116         function encrypt_message() {
117                 var url = "http://localhost:6667/perl.jm3";
118                 var strSubmit = build_gpg_qs();
119                 strSubmit += "&mode=encrypt";
120                 var x = getX();
121
122                 x.open('POST', url, true);
123                 x.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
124                 x.onreadystatechange = function() {
125                         document.forms[0].result.value += "spinning\n"; // FIXME: poor-man's status indicator
126                         if( x.readyState == 4 && x.responseText != "" ) {
127                                 document.getElementById( "plaintext" ).value = x.responseXML.childNodes[0].childNodes[0].nodeValue; // insert only the GPG text
128                         }
129                 }
130                 x.send(strSubmit);
131         }
132
133         function decrypt_message() {
134                 var url = "http://localhost:6667/perl.jm3";
135                 var strSubmit = build_gpg_qs();
136                 strSubmit += "&mode=decrypt";
137                 document.forms[0].result.value = strSubmit + "\n" + document.forms[0].result.value;
138                 var x = getX();
139
140                 x.open('POST', url, true);
141                 x.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
142                 x.onreadystatechange = function() {
143                         document.forms[0].result.value += "spinning\n"; // FIXME: poor-man's status indicator
144                         if( x.readyState == 4 && x.responseText != "" ) {
145                                 document.getElementById( "plaintext" ).value = x.responseXML.childNodes[0].childNodes[0].nodeValue; // insert only the GPG text
146                         }
147                 }
148                 x.send(strSubmit);
149         }
150
151         function sign_message() {
152                 var url = "http://localhost:6667/perl.jm3";
153                 var strSubmit = build_gpg_qs();
154                 if( strSubmit == BAIL_WITH_ERROR ) {
155                         // FIXME: handle this via in-page DOM injection
156                         alert( "enter your passphrase first." );
157                         return;
158                 }
159                 strSubmit += "&mode=sign";
160                 document.forms[0].result.value = strSubmit + "\n" + document.forms[0].result.value;
161                 var x = getX();
162
163                 x.open('POST', url, true);
164                 x.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
165                 x.onreadystatechange = function() {
166                         document.forms[0].result.value += "spinning\n"; // FIXME: poor-man's status indicator
167                         if( x.readyState == 4 && x.responseText != "" ) {
168                                 document.getElementById( "plaintext" ).value = x.responseXML.childNodes[0].childNodes[0].nodeValue; // insert only the GPG text
169                         }
170                 }
171                 x.send(strSubmit);
172         }
173
174         function prompt_for_passphrase( mode ) {
175                
176                 var me = document.getElementById( "sign_button" );
177                 var buttons = me.parentNode; // the button container
178
179                 var d = document.createElement( "div" );
180                 var t = document.createTextNode( "Enter your passphrase: " );
181
182                 var c = document.createElement( "input" );
183                 c.setAttribute( "type", "button" );
184                 c.setAttribute( "value", "Cancel" );
185                 c.setAttribute( "onclick", "this.parentNode.parentNode.removeChild( this.parentNode )" );
186
187                 var s = document.createElement( "input" );
188                 s.setAttribute( "type", "button" );
189                 s.setAttribute( "value", mode ); // FIXME: title-case this
190                 s.setAttribute( "onclick", mode + "_message()" );
191
192                 var p = document.createElement( "input" );
193                 p.setAttribute( "type", "password" );
194                 p.setAttribute( "id", "passphrase" );
195                 p.setAttribute( "size", "50" );
196
197                 d.appendChild( t );
198                 d.appendChild( p );
199                 d.appendChild( s );
200                 d.appendChild( c );
201                 buttons.parentNode.insertBefore( d, buttons );
202
203                 // FIXME: need syntax for div-hiding here
204                 buttons.setAttribute( "display", "none" );
205
206         }
207
208         function pulldown_from_keys( x ) {
209
210         // FIXME: handle no private keys case
211         // FIXME: handle no local server / server error case
212
213                 var f = document.getElementsByTagName("form");
214                 var d = document.createElement("div");
215                 var t = document.createTextNode("Private key: ");
216                 d.appendChild( t );
217
218                 var parser = new DOMParser();
219                 var dom = parser.parseFromString(x, "application/xml");
220                 var options = dom.getElementsByTagName('option');
221
222                 // for users with multiple keys, give them a select menu.
223                 var key_info_ctrl;
224                 if( options.length > 1) {
225                         key_info_ctrl = document.createElement( "select" );
226                         key_info_ctrl.setAttribute( "name", "key_id" );
227                         key_info_ctrl.setAttribute( "id", "gpg_key_id" );
228                         key_info_ctrl.innerHTML = x;
229                 } else {
230                         key_info_ctrl = document.createElement( "input" );
231                         key_info_ctrl.setAttribute( "type", "hidden" );
232                         key_info_ctrl.setAttribute( "name", "key_id" );
233                         key_info_ctrl.setAttribute( "id", "gpg_key_id" );
234                         key_info_ctrl.setAttribute( "value", options[0].attributes[0].value );
235                         var t = document.createTextNode( "Using key: " + options[0].childNodes[0].nodeValue );
236                         d.appendChild( t );
237                 }
238                 d.appendChild( key_info_ctrl );
239
240                 var buttons = document.createElement( "div" );
241                
242                 var encrypt_button = document.createElement( "input" );
243                 var sign_button = document.createElement( "input" );
244                 var sign_and_encrypt_button = document.createElement( "input" );
245                 var decrypt_button = document.createElement( "input" );
246                 encrypt_button.setAttribute( "type", "button" );
247                 encrypt_button.setAttribute( "id", "encrypt_button" );
248                 encrypt_button.setAttribute( "value", "Encrypt" );
249                 sign_button.setAttribute( "type", "button" );
250                 sign_button.setAttribute( "id", "sign_button" );
251                 sign_button.setAttribute( "value", "Sign" );
252                 sign_and_encrypt_button.setAttribute( "type", "button" );
253                 sign_and_encrypt_button.setAttribute( "id", "sign_and_encrypt_button" );
254                 sign_and_encrypt_button.setAttribute( "value", "Sign and Encrypt" );
255                 decrypt_button.setAttribute( "type", "button" );
256                 decrypt_button.setAttribute( "id", "decrypt_button" );
257                 decrypt_button.setAttribute( "value", "Decrypt" );
258
259                 //buttons.appendChild( sign_and_encrypt_button );
260                 buttons.appendChild( decrypt_button );
261                 buttons.appendChild( sign_button );
262                 encrypt_button.setAttribute( "onclick", "encrypt_message()" );
263                 decrypt_button.setAttribute( "onclick", "prompt_for_passphrase( 'decrypt' )" );
264                 sign_button.setAttribute(    "onclick", "prompt_for_passphrase( 'sign' )" );
265                 buttons.appendChild( encrypt_button );
266
267                 d.appendChild( buttons );
268
269                 f[0].appendChild( d );
270         }
271
272         var qs = "key_id=30575CA6"
273                                         + "&recipients=Jason+pratt+%3Cjas%40juniorplenty.com%3E%2C+Nicholas+D%27Angelo+%28nicksfriends%29+%3Cnick%40nicksfriends.com%3E&"
274                                         + "plaintext=" + escape( "foo bar baz" );
275
276 </script>
277
278 <!-- FIXME: replace onload trigger with GM include lines in GM script -->
279 <body onLoad="eval( document.forms[0].onclick_code.value );">
280
281 <h1>AJAX XML-to-HTML-pulldown-menu Creator</h1>
282 <h3>Red text is real UI<br>Light gray text is debugging information which will be hidden in production version </h3>
283
284 <form>
285 <input type="text" id="recipients" name="recipients"
286         value="Jason pratt <jas@juniorplenty.com>, Nicholas D'Angelo (nicksfriends) <nick@nicksfriends.com>" size="100" ><br>
287         <input name="post_to" value="http://localhost:6667/get-secret-keys.jm3" size="50" class="debugging">
288         <input type="button" value="dumb XML" onclick="document.forms[0].post_to.value = 'http://localhost:6667/dumb.jm3' " class="debugging">
289         <input type="button" value="get secret keys" onclick="document.forms[0].post_to.value = 'http://localhost:6667/get-secret-keys.jm3' " class="debugging"><br>
290         <input name="onclick_code" value="get_keys(document.forms[0].post_to.value, qs );" size="50" class="debugging">
291         <input type="button" value="go" onclick="eval( document.forms[0].onclick_code.value );" class="debugging">
292         <input type="button" value="inject ciphertext" onclick="inject_ciphertext()" class="debugging"><br>
293         <textarea id="plaintext" name="plaintext" rows="6" cols="50">This is the message body blah blah... </textarea>
294         <br>
295         <textarea name="result" rows="6" cols="50" class="debugging">Raw results show here:</textarea><br>
296 </form>
297 </body>
298 </html>
Note: See TracBrowser for help on using the browser.