This post is inspired by the Put a Flex UI On Your Application article by Bruce Eckel.
The example
The example that will be presented is a simple form showing sudo attempts recorded in the
/var/log/auth.log
log in a Linux box. A simple program written in Snobol4 using CSnobol4 is used to extract the entries from
auth.log
. A AIR/Flex program is used to display the data. Both programs are communicated using HTTP.Although there are several ways to communicate a AIR application with a server side element, HTTP was chosen because of its simplicity to implement in Snobol.
Simple HTTP in Snobol
A way to answer simple HTTP GET method requests from Snobol was required. This requires the creation of a server socket to answer requests. Luckly CSnobol4 includes a nice example for creating a server socket (
snolib/serv.sno
) using the SERV_LISTEN
function. Having this element it was very simple to implement the GET method support.
serverPort = 8080
...
SLOOP FD = SERV_LISTEN("inet", "stream", serverPort) :F(LERR)
INPUT(.NET, 9, "UWT", "/dev/fd/" FD) :F(IERR)
OUTPUT(.NET, 9)
OUTPUT = "Accepting request "
LINE = NET
LINE "GET " GetStringPat $ getString " HTTP/" NUMBER "." NUMBER :F(LERR)
getString ARB "username=" ARB $ requestedUserName ("&" | RPOS(0))
OUTPUT = "Requesting SUDOS for user: " requestedUserName
INPUT(.LOGFILE,10,,"/var/log/auth.log")
NET = "HTTP/1.1 200 OK" CRLF
NET = "Server: SNOBOL4/1.1 (Linux)" CRLF
NET = "Content-Type: text/xml" CRLF
NET = CRLF
Extracting the data
The data extraction process is presented in the following code.
LetterU = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
LetterL = "abcdefghijklmnopqrstuvwxyz"
Digit = "0123456789"
DirectorySeparator = "/"
GetQuerySeparator = "?"
EscapeChar = "%.&="
GetStringChar = LetterU LetterL Digit DirectorySeparator EscapeChar GetQuerySeparator
GetStringPat = SPAN(GetStringChar)
...
NET = "<sudosdata>"
&ANCHOR = 1
LETTER = LetterU LetterL
USERNAMECHAR = Digit LetterU LetterL
USERNAMEPAT = SPAN(USERNAMECHAR)
READLINE LINE = LOGFILE :F(DONE)
LINE SPAN(LETTER) $ month SPAN(" ") SPAN(Digit) $ day ARB " sudo: " USERNAMEPAT . USER :F(READLINE)
LINE ARB "COMMAND=" ARB . COMMAND RPOS(0)
USER requestedUserName :F(READLINE)
NET = "<sudo><date>" month " " day "</date><user>" USER "</user><command>" COMMAND "</command></sudo>" :(READLINE)
DONE
NET = "</sudosdata>" :S(END)
The answer is formated as XML.
The Interface Code
The interface is a very simple program containing a text input to filter the query for a specify user. The useful HTTPService component is used to get the data from the Snobol program.
The Flex part of the program is the following:
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
title="Sudos Test">
<mx:Script>
<![CDATA[
import flash.utils.Dictionary;
private function callQuery():void {
request.send();
}
]]>
</mx:Script>
<mx:HBox>
<mx:Label text="Sudos" />
<mx:TextInput id="userName" />
</mx:HBox>
<mx:Button label="Query!" click="callQuery()"/>
<mx:DataGrid id="data" dataProvider="{request.lastResult.sudosdata.sudo}">
<mx:columns>
<mx:DataGridColumn headerText="date" dataField="date"/>
<mx:DataGridColumn headerText="user" dataField="user"/>
<mx:DataGridColumn headerText="command" dataField="command"/>
</mx:columns>
</mx:DataGrid>
<mx:HTTPService id="request" url="http://localhost:8080"
useProxy="false"
method="GET">
<mx:request xmlns="">
<username>{userName.text}</username>
</mx:request>
</mx:HTTPService>
</mx:WindowedApplication>
How it looks
An example of running these programs is the following:
Code for this post can be found here.