Added some small boring scripts and programs writen in few last years
[mirrors/Programs.git] / plugins / firefox-extensions / test / skeleton / chrome / content / connection-xpcom.js
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 *
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 *
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
10 *
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
15 *
16 * The Original Code is JSIRC Library.
17 *
18 * The Initial Developer of the Original Code is
19 * New Dimensions Consulting, Inc.
20 * Portions created by the Initial Developer are Copyright (C) 1999
21 * the Initial Developer. All Rights Reserved.
22 *
23 * Contributor(s):
24 * Robert Ginda, rginda@ndcico.com, original author
25 * Peter Van der Beken, peter.vanderbeken@pandora.be, necko-only version
26 *
27 * Alternatively, the contents of this file may be used under the terms of
28 * either the GNU General Public License Version 2 or later (the "GPL"), or
29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
38 *
39 * ***** END LICENSE BLOCK ***** */
40
41 const NS_ERROR_MODULE_NETWORK = 2152398848;
42
43 const NS_ERROR_UNKNOWN_HOST = NS_ERROR_MODULE_NETWORK + 30;
44 const NS_ERROR_CONNECTION_REFUSED = NS_ERROR_MODULE_NETWORK + 13;
45 const NS_ERROR_NET_TIMEOUT = NS_ERROR_MODULE_NETWORK + 14;
46 const NS_ERROR_NET_RESET = NS_ERROR_MODULE_NETWORK + 20;
47 const NS_ERROR_UNKNOWN_PROXY_HOST = NS_ERROR_MODULE_NETWORK + 42;
48 const NS_ERROR_PROXY_CONNECTION_REFUSED = NS_ERROR_MODULE_NETWORK + 72;
49
50 // Offline error constants:
51 const NS_ERROR_BINDING_ABORTED = NS_ERROR_MODULE_NETWORK + 2;
52 const NS_ERROR_ABORT = 0x80004004;
53
54 const NS_NET_STATUS_RESOLVING_HOST = NS_ERROR_MODULE_NETWORK + 3;
55 const NS_NET_STATUS_CONNECTED_TO = NS_ERROR_MODULE_NETWORK + 4;
56 const NS_NET_STATUS_SENDING_TO = NS_ERROR_MODULE_NETWORK + 5;
57 const NS_NET_STATUS_RECEIVING_FROM = NS_ERROR_MODULE_NETWORK + 6;
58 const NS_NET_STATUS_CONNECTING_TO = NS_ERROR_MODULE_NETWORK + 7;
59
60 // Security Constants.
61 const STATE_IS_BROKEN = 1;
62 const STATE_IS_SECURE = 2;
63 const STATE_IS_INSECURE = 3;
64
65 const STATE_SECURE_LOW = 1;
66 const STATE_SECURE_HIGH = 2;
67
68 const nsIScriptableInputStream = Components.interfaces.nsIScriptableInputStream;
69
70 const nsIBinaryInputStream = Components.interfaces.nsIBinaryInputStream;
71 const nsIBinaryOutputStream = Components.interfaces.nsIBinaryOutputStream;
72
73 function toSInputStream(stream, binary)
74 {
75 var sstream;
76
77 if (binary)
78 {
79 sstream = Components.classes["@mozilla.org/binaryinputstream;1"];
80 sstream = sstream.createInstance(nsIBinaryInputStream);
81 sstream.setInputStream(stream);
82 }
83 else
84 {
85 sstream = Components.classes["@mozilla.org/scriptableinputstream;1"];
86 sstream = sstream.createInstance(nsIScriptableInputStream);
87 sstream.init(stream);
88 }
89
90 return sstream;
91 }
92
93 function toSOutputStream(stream, binary)
94 {
95 var sstream;
96
97 if (binary)
98 {
99 sstream = Components.classes["@mozilla.org/binaryoutputstream;1"];
100 sstream = sstream.createInstance(Components.interfaces.nsIBinaryOutputStream);
101 sstream.setOutputStream(stream);
102 }
103 else
104 {
105 sstream = stream;
106 }
107
108 return sstream;
109 }
110
111 function CBSConnection (binary)
112 {
113 /* Since 2003-01-17 18:14, Mozilla has had this contract ID for the STS.
114 * Prior to that it didn't have one, so we also include the CID for the
115 * STS back then - DO NOT UPDATE THE ID if it changes in Mozilla.
116 */
117 const sockClassByName =
118 Components.classes["@mozilla.org/network/socket-transport-service;1"];
119 const sockClassByID =
120 Components.classesByID["{c07e81e0-ef12-11d2-92b6-00105a1b0d64}"];
121
122 var sockServiceClass = (sockClassByName || sockClassByID);
123
124 if (!sockServiceClass)
125 throw ("Couldn't get socket service class.");
126
127 var sockService = sockServiceClass.getService();
128 if (!sockService)
129 throw ("Couldn't get socket service.");
130
131 this._sockService = sockService.QueryInterface
132 (Components.interfaces.nsISocketTransportService);
133
134 /* Note: as part of the mess from bug 315288 and bug 316178, ChatZilla now
135 * uses the *binary* stream interfaces for all network
136 * communications.
137 *
138 * However, these interfaces do not exist prior to 1999-11-05. To
139 * make matters worse, an incompatible change to the "readBytes"
140 * method of this interface was made on 2003-03-13; luckly, this
141 * change also added a "readByteArray" method, which we will check
142 * for below, to determin if we can use the binary streams.
143 */
144
145 // We want to check for working binary streams only the first time.
146 if (CBSConnection.prototype.workingBinaryStreams == -1)
147 {
148 CBSConnection.prototype.workingBinaryStreams = false;
149
150 if (typeof nsIBinaryInputStream != "undefined")
151 {
152 var isCls = Components.classes["@mozilla.org/binaryinputstream;1"];
153 var inputStream = isCls.createInstance(nsIBinaryInputStream);
154 if ("readByteArray" in inputStream)
155 CBSConnection.prototype.workingBinaryStreams = true;
156 }
157 }
158
159 this.wrappedJSObject = this;
160 if (typeof binary != "undefined")
161 this.binaryMode = binary;
162 else
163 this.binaryMode = this.workingBinaryStreams;
164
165 if (!ASSERT(!this.binaryMode || this.workingBinaryStreams,
166 "Unable to use binary streams in this build."))
167 {
168 throw ("Unable to use binary streams in this build.");
169 }
170 }
171
172 CBSConnection.prototype.workingBinaryStreams = -1;
173
174 CBSConnection.prototype.connect =
175 function bc_connect(host, port, config, observer)
176 {
177 this.host = host.toLowerCase();
178 this.port = port;
179
180 if (typeof config != "object")
181 config = {};
182
183 // Lets get a transportInfo for this
184 var pps = getService("@mozilla.org/network/protocol-proxy-service;1",
185 "nsIProtocolProxyService");
186 if (!pps)
187 throw ("Couldn't get protocol proxy service");
188
189 var ios = getService("@mozilla.org/network/io-service;1", "nsIIOService");
190
191 function getProxyFor(uri)
192 {
193 uri = ios.newURI(uri, null, null);
194 // As of 2005-03-25, 'examineForProxy' was replaced by 'resolve'.
195 if ("resolve" in pps)
196 return pps.resolve(uri, 0);
197 if ("examineForProxy" in pps)
198 return pps.examineForProxy(uri);
199 return null;
200 };
201
202 var proxyInfo = null;
203 var usingHTTPCONNECT = false;
204 if ("proxy" in config)
205 {
206 /* Force Necko to supply the HTTP proxy info if desired. For none,
207 * force no proxy. Other values will get default treatment.
208 */
209 if (config.proxy == "http")
210 proxyInfo = getProxyFor("http://" + host + ":" + port);
211 else if (config.proxy != "none")
212 proxyInfo = getProxyFor("irc://" + host + ":" + port);
213
214 /* Since the proxy info is opaque, we need to check that we got
215 * something for our HTTP proxy - we can't just check proxyInfo.type.
216 */
217 usingHTTPCONNECT = ((config.proxy == "http") && proxyInfo);
218 }
219 else
220 {
221 proxyInfo = getProxyFor("irc://" + host + ":" + port);
222 }
223
224 if (jsenv.HAS_STREAM_PROVIDER)
225 {
226 if (("isSecure" in config) && config.isSecure)
227 {
228 this._transport = this._sockService.
229 createTransportOfType("ssl", host, port,
230 proxyInfo, 0, 0);
231 }
232 else
233 {
234 this._transport = this._sockService.
235 createTransport(host, port, proxyInfo, 0, 0);
236 }
237 if (!this._transport)
238 throw ("Error creating transport.");
239
240 if (jsenv.HAS_NSPR_EVENTQ)
241 { /* we've got an event queue, so start up an async write */
242 this._streamProvider = new StreamProvider (observer);
243 this._write_req =
244 this._transport.asyncWrite (this._streamProvider, this,
245 0, -1, 0);
246 }
247 else
248 {
249 /* no nspr event queues in this environment, we can't use async
250 * calls, so set up the streams. */
251 this._outputStream = this._transport.openOutputStream(0, -1, 0);
252 if (!this._outputStream)
253 throw "Error getting output stream.";
254 this._sOutputStream = toSOutputStream(this._outputStream,
255 this.binaryMode);
256
257 this._inputStream = this._transport.openInputStream(0, -1, 0);
258 if (!this._inputStream)
259 throw "Error getting input stream.";
260 this._sInputStream = toSInputStream(this._inputStream,
261 this.binaryMode);
262 }
263 }
264 else
265 {
266 /* use new necko interfaces */
267 if (("isSecure" in config) && config.isSecure)
268 {
269 this._transport = this._sockService.
270 createTransport(["ssl"], 1, host, port,
271 proxyInfo);
272 }
273 else
274 {
275 this._transport = this._sockService.
276 createTransport(null, 0, host, port, proxyInfo);
277 }
278 if (!this._transport)
279 throw ("Error creating transport.");
280
281 /* if we don't have an event queue, then all i/o must be blocking */
282 var openFlags;
283 if (jsenv.HAS_NSPR_EVENTQ)
284 openFlags = 0;
285 else
286 openFlags = Components.interfaces.nsITransport.OPEN_BLOCKING;
287
288 /* no limit on the output stream buffer */
289 this._outputStream =
290 this._transport.openOutputStream(openFlags, 4096, -1);
291 if (!this._outputStream)
292 throw "Error getting output stream.";
293 this._sOutputStream = toSOutputStream(this._outputStream,
294 this.binaryMode);
295
296 this._inputStream = this._transport.openInputStream(openFlags, 0, 0);
297 if (!this._inputStream)
298 throw "Error getting input stream.";
299 this._sInputStream = toSInputStream(this._inputStream,
300 this.binaryMode);
301 }
302
303 this.connectDate = new Date();
304 this.isConnected = true;
305
306 // Bootstrap the connection if we're proxying via an HTTP proxy.
307 if (usingHTTPCONNECT)
308 {
309 this.sendData("CONNECT " + host + ":" + port + " HTTP/1.1\r\n\r\n");
310 }
311
312 return this.isConnected;
313
314 }
315
316 CBSConnection.prototype.listen =
317 function bc_listen(port, observer)
318 {
319 var serverSockClass =
320 Components.classes["@mozilla.org/network/server-socket;1"];
321
322 if (!serverSockClass)
323 throw ("Couldn't get server socket class.");
324
325 var serverSock = serverSockClass.createInstance();
326 if (!serverSock)
327 throw ("Couldn't get server socket.");
328
329 this._serverSock = serverSock.QueryInterface
330 (Components.interfaces.nsIServerSocket);
331
332 this._serverSock.init(port, false, -1);
333
334 this._serverSockListener = new SocketListener(this, observer);
335
336 this._serverSock.asyncListen(this._serverSockListener);
337
338 this.port = this._serverSock.port;
339
340 return true;
341 }
342
343 CBSConnection.prototype.accept =
344 function bc_accept(transport, observer)
345 {
346 this._transport = transport;
347 this.host = this._transport.host.toLowerCase();
348 this.port = this._transport.port;
349
350 if (jsenv.HAS_STREAM_PROVIDER)
351 {
352 if (jsenv.HAS_NSPR_EVENTQ)
353 { /* we've got an event queue, so start up an async write */
354 this._streamProvider = new StreamProvider (observer);
355 this._write_req =
356 this._transport.asyncWrite (this._streamProvider, this,
357 0, -1, 0);
358 }
359 else
360 {
361 /* no nspr event queues in this environment, we can't use async
362 * calls, so set up the streams. */
363 this._outputStream = this._transport.openOutputStream(0, -1, 0);
364 if (!this._outputStream)
365 throw "Error getting output stream.";
366 this._sOutputStream = toSOutputStream(this._outputStream,
367 this.binaryMode);
368
369 //this._scriptableInputStream =
370 this._inputStream = this._transport.openInputStream(0, -1, 0);
371 if (!this._inputStream)
372 throw "Error getting input stream.";
373 this._sInputStream = toSInputStream(this._inputStream,
374 this.binaryMode);
375 }
376 }
377 else
378 {
379 /* if we don't have an event queue, then all i/o must be blocking */
380 var openFlags;
381 if (jsenv.HAS_NSPR_EVENTQ)
382 openFlags = 0;
383 else
384 openFlags = Components.interfaces.nsITransport.OPEN_BLOCKING;
385
386 /* no limit on the output stream buffer */
387 this._outputStream =
388 this._transport.openOutputStream(openFlags, 4096, -1);
389 if (!this._outputStream)
390 throw "Error getting output stream.";
391 this._sOutputStream = toSOutputStream(this._outputStream,
392 this.binaryMode);
393
394 this._inputStream = this._transport.openInputStream(openFlags, 0, 0);
395 if (!this._inputStream)
396 throw "Error getting input stream.";
397 this._sInputStream = toSInputStream(this._inputStream,
398 this.binaryMode);
399 }
400
401 this.connectDate = new Date();
402 this.isConnected = true;
403
404 // Clean up listening socket.
405 this.close();
406
407 return this.isConnected;
408 }
409
410 CBSConnection.prototype.close =
411 function bc_close()
412 {
413 if ("_serverSock" in this && this._serverSock)
414 this._serverSock.close();
415 }
416
417 CBSConnection.prototype.disconnect =
418 function bc_disconnect()
419 {
420 if ("_inputStream" in this && this._inputStream)
421 this._inputStream.close();
422 if ("_outputStream" in this && this._outputStream)
423 this._outputStream.close();
424 this.isConnected = false;
425 /*
426 this._streamProvider.close();
427 if (this._streamProvider.isBlocked)
428 this._write_req.resume();
429 */
430 }
431
432 CBSConnection.prototype.sendData =
433 function bc_senddata(str)
434 {
435 if (!this.isConnected)
436 throw "Not Connected.";
437
438 if (jsenv.HAS_NSPR_EVENTQ && jsenv.HAS_STREAM_PROVIDER)
439 this.asyncWrite (str);
440 else
441 this.sendDataNow (str);
442 }
443
444 CBSConnection.prototype.readData =
445 function bc_readdata(timeout, count)
446 {
447 if (!this.isConnected)
448 throw "Not Connected.";
449
450 var rv;
451
452 if (!("_sInputStream" in this)) {
453 this._sInputStream = toSInputStream(this._inputStream);
454 dump("OMG, setting up _sInputStream!\n");
455 }
456
457 try
458 {
459 // XPCshell h4x
460 if (typeof count == "undefined")
461 count = this._sInputStream.available();
462 if (this.binaryMode)
463 rv = this._sInputStream.readBytes(count);
464 else
465 rv = this._sInputStream.read(count);
466 }
467 catch (ex)
468 {
469 dd ("*** Caught " + ex + " while reading.");
470 this.disconnect();
471 throw (ex);
472 }
473
474 return rv;
475 }
476
477 CBSConnection.prototype.startAsyncRead =
478 function bc_saread (observer)
479 {
480 if (jsenv.HAS_STREAM_PROVIDER)
481 {
482 this._transport.asyncRead (new StreamListener (observer),
483 this, 0, -1, 0);
484 }
485 else
486 {
487 var cls = Components.classes["@mozilla.org/network/input-stream-pump;1"];
488 var pump = cls.createInstance(Components.interfaces.nsIInputStreamPump);
489 pump.init(this._inputStream, -1, -1, 0, 0, false);
490 pump.asyncRead(new StreamListener(observer), this);
491 }
492 }
493
494 CBSConnection.prototype.asyncWrite =
495 function bc_awrite (str)
496 {
497 this._streamProvider.pendingData += str;
498 if (this._streamProvider.isBlocked)
499 {
500 this._write_req.resume();
501 this._streamProvider.isBlocked = false;
502 }
503 }
504
505 CBSConnection.prototype.hasPendingWrite =
506 function bc_haspwrite ()
507 {
508 if (jsenv.HAS_STREAM_PROVIDER)
509 return (this._streamProvider.pendingData != "");
510 else
511 return false; /* data already pushed to necko */
512 }
513
514 CBSConnection.prototype.sendDataNow =
515 function bc_senddatanow(str)
516 {
517 var rv = false;
518
519 try
520 {
521 if (this.binaryMode)
522 this._sOutputStream.writeBytes(str, str.length);
523 else
524 this._sOutputStream.write(str, str.length);
525 rv = true;
526 }
527 catch (ex)
528 {
529 dd ("*** Caught " + ex + " while sending.");
530 this.disconnect();
531 throw (ex);
532 }
533
534 return rv;
535 }
536
537 /* getSecurityState returns an array containing information about the security
538 * of the connection. The array always has at least one item, which contains a
539 * value from the STATE_IS_* enumeration at the top of this file. Iff this is
540 * STATE_IS_SECURE, the array has a second item indicating the level of
541 * security - a value from the STATE_SECURE_* enumeration.
542 *
543 * STATE_IS_BROKEN is returned if any errors occur, and STATE_IS_INSECURE is
544 * returned for disconnected sockets.
545 */
546 CBSConnection.prototype.getSecurityState =
547 function bc_getsecuritystate()
548 {
549 if (!this.isConnected || !this._transport.securityInfo)
550 return [STATE_IS_INSECURE];
551
552 try
553 {
554 var sslSp = Components.interfaces.nsISSLStatusProvider;
555 var sslStatus = Components.interfaces.nsISSLStatus;
556
557 // Get the actual SSL Status
558 sslSp = this._transport.securityInfo.QueryInterface(sslSp);
559 sslStatus = sslSp.SSLStatus.QueryInterface(sslStatus);
560 // Store appropriate status
561 if (!("keyLength" in sslStatus) || !sslStatus.keyLength)
562 return [STATE_IS_BROKEN];
563 else if (sslStatus.keyLength >= 90)
564 return [STATE_IS_SECURE, STATE_SECURE_HIGH];
565 else
566 return [STATE_IS_SECURE, STATE_SECURE_LOW];
567 }
568 catch (ex)
569 {
570 // Something goes wrong -> broken security icon
571 dd("Exception getting certificate for connection: " + ex.message);
572 return [STATE_IS_BROKEN];
573 }
574 }
575
576 CBSConnection.prototype.getCertificate =
577 function bc_getcertificate()
578 {
579 if (!this.isConnected || !this._transport.securityInfo)
580 return null;
581
582 var sslSp = Components.interfaces.nsISSLStatusProvider;
583 var sslStatus = Components.interfaces.nsISSLStatus;
584
585 // Get the actual SSL Status
586 sslSp = this._transport.securityInfo.QueryInterface(sslSp);
587 sslStatus = sslSp.SSLStatus.QueryInterface(sslStatus);
588
589 // return the certificate
590 return sslStatus.serverCert;
591 }
592
593 function _notimpl ()
594 {
595 throw "Not Implemented.";
596 }
597
598 if (!jsenv.HAS_NSPR_EVENTQ)
599 {
600 CBSConnection.prototype.startAsyncRead = _notimpl;
601 CBSConnection.prototype.asyncWrite = _notimpl;
602 }
603 else if (jsenv.HAS_STREAM_PROVIDER)
604 {
605 CBSConnection.prototype.sendDataNow = _notimpl;
606 }
607 else
608 {
609 CBSConnection.prototype.asyncWrite = _notimpl;
610 }
611
612 delete _notimpl;
613
614 function StreamProvider(observer)
615 {
616 this._observer = observer;
617 }
618
619 StreamProvider.prototype.pendingData = "";
620 StreamProvider.prototype.isBlocked = true;
621
622 StreamProvider.prototype.close =
623 function sp_close ()
624 {
625 this.isClosed = true;
626 }
627
628 StreamProvider.prototype.onDataWritable =
629 function sp_datawrite (request, ctxt, ostream, offset, count)
630 {
631 //dd ("StreamProvider.prototype.onDataWritable");
632
633 if ("isClosed" in this && this.isClosed)
634 throw Components.results.NS_BASE_STREAM_CLOSED;
635
636 if (!this.pendingData)
637 {
638 this.isBlocked = true;
639
640 /* this is here to support pre-XPCDOM builds (0.9.0 era), which
641 * don't have this result code mapped. */
642 if (!Components.results.NS_BASE_STREAM_WOULD_BLOCK)
643 throw 2152136711;
644
645 throw Components.results.NS_BASE_STREAM_WOULD_BLOCK;
646 }
647
648 var len = ostream.write (this.pendingData, this.pendingData.length);
649 this.pendingData = this.pendingData.substr (len);
650 }
651
652 StreamProvider.prototype.onStartRequest =
653 function sp_startreq (request, ctxt)
654 {
655 //dd ("StreamProvider::onStartRequest: " + request + ", " + ctxt);
656 }
657
658
659 StreamProvider.prototype.onStopRequest =
660 function sp_stopreq (request, ctxt, status)
661 {
662 //dd ("StreamProvider::onStopRequest: " + request + ", " + ctxt + ", " +
663 // status);
664 if (this._observer)
665 this._observer.onStreamClose(status);
666 }
667
668 function StreamListener(observer)
669 {
670 this._observer = observer;
671 }
672
673 StreamListener.prototype.onStartRequest =
674 function sl_startreq (request, ctxt)
675 {
676 //dd ("StreamListener::onStartRequest: " + request + ", " + ctxt);
677 }
678
679 StreamListener.prototype.onStopRequest =
680 function sl_stopreq (request, ctxt, status)
681 {
682 //dd ("StreamListener::onStopRequest: " + request + ", " + ctxt + ", " +
683 //status);
684 if (this._observer)
685 this._observer.onStreamClose(status);
686 }
687
688 StreamListener.prototype.onDataAvailable =
689 function sl_dataavail (request, ctxt, inStr, sourceOffset, count)
690 {
691 ctxt = ctxt.wrappedJSObject;
692 if (!ctxt)
693 {
694 dd ("*** Can't get wrappedJSObject from ctxt in " +
695 "StreamListener.onDataAvailable ***");
696 return;
697 }
698
699 if (!("_sInputStream" in ctxt))
700 ctxt._sInputStream = toSInputStream(inStr, false);
701
702 if (this._observer)
703 this._observer.onStreamDataAvailable(request, inStr, sourceOffset,
704 count);
705 }
706
707 function SocketListener(connection, observer)
708 {
709 this._connection = connection;
710 this._observer = observer;
711 }
712
713 SocketListener.prototype.onSocketAccepted =
714 function sl_onSocketAccepted(socket, transport)
715 {
716 this._observer.onSocketAccepted(socket, transport);
717 }
718 SocketListener.prototype.onStopListening =
719 function sl_onStopListening(socket, status)
720 {
721 delete this._connection._serverSockListener;
722 delete this._connection._serverSock;
723 }
This page took 0.715333 seconds and 4 git commands to generate.