Skip to content
Snippets Groups Projects
Commit ef5aa646 authored by deuce's avatar deuce
Browse files

Initial checking of ZuulTerm (working title).

Currently suports RLogin to my BBS as me only.
parent 1c0511a3
No related branches found
No related tags found
No related merge requests found
ZuulTerm Protocol v0.1
The ZuulTerm protocol runs on top of an 8-bit clean connection.
The Zuul protocol is a client/server protocol for session control data.
The idea is that a control connection exists where session data is transferred
and one or more auxiliary connections for stateless data.
The session is in UTF-8 mode at all times, and the string control characters are
used as defined in http://www.ecma-inte rnational.org/publications/files/ECMA-ST/Ecma-048.pdf
No other control characters are supported however.
U+0090
Device Control String
The contained string contains one of the folowing commands (case sensitive):
GET <URL>
Where URL is replaced with a valid URL. The current page is replaced with the contents of the specified
URL.
8.3.27 DCS - DEVICE CONTROL STRING
Notation: (C1)
Representation: 09/00 or ESC 05/00
DCS is used as the opening delimiter of a control string for device control use. The command string
following may consist of bit combinations in the range 00/08 to 00/13 and 02/00 to 07/14. The control
string is closed by the terminating delimiter STRING TERMINATOR (ST).
The command string represents either one or more commands for the receiving device, or one or more
status reports from the sending device. The purpose and the format of the command string are specified
by the most recent occurrence of IDENTIFY DEVICE CONTROL STRING (IDCS), if any, or depend on
the sending and/or the receiving device.
U+009D
Operating System Command
Used to interact with the OS. This is *not* a command line to run,
but an abstract description of one.
8.3.89 OSC - OPERATING SYSTEM COMMAND
Notation: (C1)
Representation: 09/13 or ESC 05/13
OSC is used as the opening delimiter of a control string for operating system use. The command string
following may consist of a sequence of bit combinations in the range 00/08 to 00/13 and 02/00 to 07/14.
The control string is closed by the terminating delimiter STRING TERMINATOR (ST). The
interpretation of the command string depends on the relevant operating system.
U+009F
Application Program Command
The contained string is JavaScript to be executed in the context of the window current window. Note the
character set restriction however, the JS must be written in a subset of ASCII.
8.3.2 APC - APPLICATION PROGRAM COMMAND
Notation: (C1)
Representation: 09/15 or ESC 05/15
APC is used as the opening delimiter of a control string for application program use. The command
string following may consist of bit combinations in the range 00/08 to 00/13 and 02/00 to 07/14. The
control string is closed by the terminating delimiter STRING TERMINATOR (ST). The interpretation of
the command string depends on the relevant application program.
U+009C
String Terminator
Marks the end of a string.
8.3.143 ST - STRING TERMINATOR
Notation: (C1)
Representation: 09/12 or ESC 05/12
ST is used as the closing delimiter of a control string opened by APPLICATION PROGRAM
COMMAND (APC), DEVICE CONTROL STRING (DCS), OPERATING SYSTEM COMMAND
(OSC), PRIVACY MESSAGE (PM), or START OF STRING (SOS).
U+009E
Privacy Message
Unused, must be ignored
8.3.94 PM - PRIVACY MESSAGE
Notation: (C1)
Representation: 09/14 or ESC 05/14
PM is used as the opening delimiter of a control string for privacy message use. The command string
following may consist of a sequence of bit combinations in the range 00/08 to 00/13 and 02/00 to 07/14.
The control string is closed by the terminating delimiter STRING TERMINATOR (ST). The
interpretation of the command string depends on the relevant privacy discipline.
U+0098
Start of String
Unused, must be ignored
8.3.128 SOS - START OF STRING
Notation: (C1)
Representation: 09/08 or ESC 05/08
SOS is used as the opening delimiter of a control string. The character string following may consist of
any bit combination, except those representing SOS or STRING TERMINATOR (ST). The control string
is closed by the terminating delimiter STRING TERMINATOR (ST). The interpretation of the character
string depends on the application.
[App]
Name=ZuulTerm
Version=0.1
BuildID=0
ID=zuulterm@bbsdev.net
Vendor=Synchronet
[Gecko]
MinVersion=1.5
content ZuulTerm file:content/
function RLoginConnection(address, port, recvfunc)
{
this.recvfunc=recvfunc;
this.onStartRequest=function(request, context) {};
this.onStopRequest=function(request, context, status) {
alert("Disconnected!");
endTerm();
};
this.onDataAvailable=function(request, context, inputStream, offset, count) {
this.recvfunc(this.sock.read(count, count, 0));
};
this.write=function(data)
{
this.sock.write(data);
}
this.close=function()
{
this.sock.close();
}
this.connected=function()
{
return(this.sock.transport.isAlive());
}
this.sock=new Socket();
this.sock.connect(address,port);
this.write("\x00admin\x00deuce\x00ZuulTerm/115200\x00");
if(this.sock.read(1,1,10000)!='\x00')
alert("No RLogin ack!");
this.sock.asyncRead(this);
}
function Socket()
{
const sockServiceClass =
Components.classes["@mozilla.org/network/socket-transport-service;1"];
this.sockService = sockServiceClass.getService().QueryInterface(Components.interfaces.nsISocketTransportService);
}
Socket.prototype.connect=function(addr,port,handler)
{
this.addr = addr.toLowerCase();
this.port = port;
var usingHTTPCONNECT = false;
this.transport = this.sockService.createTransport(null, 0, addr, port, null);
if(!this.transport)
throw("Could not create transport!");
this.outputStream = this.transport.openOutputStream(Components.interfaces.nsITransport.OPEN_BLOCKING, 0, 0);
if(!this.outputStream)
throw("Could not create output stream!");
this.sOutputStream = Components.classes["@mozilla.org/binaryoutputstream;1"].createInstance(Components.interfaces.nsIBinaryOutputStream);
if(!this.sOutputStream)
throw("Could not create sOutput stream!");
this.sOutputStream.setOutputStream(this.outputStream);
this.inputStream = this.transport.openInputStream(0/*Components.interfaces.nsITransport.OPEN_BLOCKING*/, 0, 0);
if(!this.inputStream)
throw("Could not create input stream!");
this.sInputStream = Components.classes["@mozilla.org/binaryinputstream;1"].createInstance(Components.interfaces.nsIBinaryInputStream);
if(!this.sInputStream)
throw("Could not create Sinput stream!");
this.sInputStream.setInputStream(this.inputStream);
return true;
}
Socket.prototype.write=function(data)
{
this.sOutputStream.writeBytes(data, data.length);
}
Socket.prototype.read=function(minbytes, maxbytes, timeout /* milliseconds */)
{
var buf='';
var total_delay=0;
var recv=0;
if(typeof(maxbytes) != 'number')
maxbytes=1024*1024*1; // One megabyte
if(typeof(minbytes) != 'number')
minbytes=1;
while(buf.length < minbytes && (typeof(timeout != 'number') || total_delay < timeout)) {
if(total_delay) {
nsWaitForDelay(100);
total_delay += 100;
}
try {
recv=this.sInputStream.available();
if(recv > maxbytes)
recv=maxbytes;
if(recv < minbytes)
recv = minbytes;
buf += this.sInputStream.readBytes(recv);
}
catch(e) {
// Is this "Would Block"?
}
}
return buf;
}
Socket.prototype.asyncRead=function(handlers)
{
var pump = Components.classes["@mozilla.org/network/input-stream-pump;1"].createInstance(Components.interfaces.nsIInputStreamPump);
pump.init(this.inputStream, -1, -1, 1, 1024*1024, false);
this.handlers=handlers;
pump.asyncRead(handlers, this);
}
Socket.prototype.close=function()
{
this.inputStream.close();
this.outputStream.close();
}
var connection=null;
function UpdateTerm(data)
{
var term=document.getElementById("frame").contentDocument.getElementById("terminal");
var win=document.getElementById("frame").contentWindow;
term.innerHTML += data;
win.scroll(0, term.clientHeight);
}
function doTerm(host, port)
{
var ConnOpt=document.getElementById("MainConnectionMenu-connect").disabled=true;
var DisconnOpt=document.getElementById("MainConnectionMenu-disconnect").disabled=false;
connection=new RLoginConnection(host,port,UpdateTerm);
}
function endTerm()
{
if(connection != null)
connection.close();
connection=null;
var ConnOpt=document.getElementById("MainConnectionMenu-connect").disabled=false;
var DisconnOpt=document.getElementById("MainConnectionMenu-disconnect").disabled=true;
}
function dumpObj(obj,name)
{
var i;
for(i in obj) {
// if(typeof(obj[i]=='object')) {
// dumpObj(obj[i],name+"["+i+"]");
// }
// else {
alert(name+"["+i+"]="+obj[i]);
// }
}
}
function translateKey(key)
{
var str;
if(key.charCode==0) {
if(key.keyCode < 32)
return String.fromCharCode(key.keyCode);
alert("Unhandled key code "+key.keyCode);
return('');
}
return String.fromCharCode(key.charCode);
}
function sendKey(key)
{
if(connection != null) {
connection.write(translateKey(key));
}
}
// From http://sejq.blogspot.com/2008/12/two-javascript-synchronous-sleep.html
/**
* Netscape compatible WaitForDelay function.
* You can use it as an alternative to Thread.Sleep() in any major programming language
* that support it while JavaScript it self doesn't have any built-in function to do such a thing.
* parameters:
* (Number) delay in millisecond
*/
function nsWaitForDelay(delay) {
/**
* Just uncomment this code if you're building an extention for Firefox.
* Since FF3, we'll have to ask for user permission to execute XPCOM objects.
*/
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
// Get the current thread.
var thread = Components.classes["@mozilla.org/thread-manager;1"].getService(Components.interfaces.nsIThreadManager).currentThread;
// Create an inner property to be used later as a notifier.
this.delayed = true;
/* Call JavaScript setTimeout function
* to execute this.delayed = false
* after it finish.
*/
setTimeout("this.delayed = false;", delay);
/**
* Keep looping until this.delayed = false
*/
while (this.delayed) {
/**
* This code will not freeze your browser as it's documented in here:
* https://developer.mozilla.org/en/Code_snippets/Threads#Waiting_for_a_background_task_to_complete
*/
thread.processNextEvent(true);
}
}
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window id="MainWindow" title="ZuulTerm" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" persist="width height">
<script src="chrome://ZuulTerm/content/Util.js" />
<script src="chrome://ZuulTerm/content/Socket.js" />
<script src="chrome://ZuulTerm/content/RLogin.js" />
<script src="chrome://ZuulTerm/content/Term.js" />
<menubar id="MainMenubar">
<menu id="MainFileMenu" label="File" accesskey="F">
<menupopup id="MainFileMenu-popup">
<menuitem label="Exit" accesskey="x" oncommand="window.close();"/>
</menupopup>
</menu>
<menu id="MainViewMenu" label="View" accesskey="V">
<menupopup id="MainViewMenu-popup">
<menuitem label="Directory" accesskey="D"/>
<menuitem label="Scrollback" accesskey="S"/>
</menupopup>
</menu>
<menu id="MainConnectionMenu" label="Connection" accesskey="C">
<menupopup id="MainConnectionMenu-popup">
<menuitem label="Connect" accesskey="C" disabled="false" oncommand="doTerm('nix.synchro.net', 513);" id="MainConnectionMenu-connect"/>
<menuitem label="Disconnect" accesskey="D" disabled="true" oncommand="endTerm();" id="MainConnectionMenu-disconnect"/>
</menupopup>
</menu>
</menubar>
<iframe id="frame" src="chrome://ZuulTerm/content/default.html" showcaret="true" onkeypress="sendKey(event)" type="content-primary" flex="1"/>
</window>
<html>
<body><pre id="terminal"></pre></body>
</html>
pref("toolkit.defaultChromeURI", "chrome://ZuulTerm/content/ZuulTerm.xul");
pref("javascript.options.showInConsole",true);
#!/bin/sh
xulrunner application.ini
"C:\Program Files\Mozilla Firefox\Firefox.exe" -app application.ini
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment