This section publishes IT related articles, guides, papers and software I have written
Various IT related articles
There are basically 3 types of multipart messages:
For the benefit of ayone who may be interested in sending an HTML e-mail that references an swf (Flash) movie (or anything else for that matter) embedded within the same e-mail message, here is a complete description of how to go about it.
The process is totally manual since e-mail clients (yes, Outlook included) do not support such operations. Also note that such e-mails only work on e-mail clients that do support HTML viewing (like Outlook and Netscape Messenger).
First you have to manually compose the source code for your mail message. This code includes multiple message parts. One part is the HTML message that will be viewed by the mail recipient and another part is the movie attachment that we will reference with the CID link within the HTML code. The message is of the type multipart/related and should be so in order to ensure that the the CID links work.
Here is a sample that I have recently used to convey my XMas wishes to my friends (it worked for all microsoft, eudora and netscape mail clients):
From: Fotios
To: Everyone@I_Like
Reply-To: fotios@altavista.net
Subject: xmas wishes
Mime-Version: 1.0
X-Mailer: MyFingersAreSore 0.1
Content-Type: multipart/related; boundary="wootsoo-wootsoo-eh"; type=Text/HTML
--wootsoo-wootsoo-eh
Content-Type: Text/HTML; charset=US-ASCII
<HTML>
<HEAD>
<TITLE>Merry Christmas & A Happy 2001...(You need the Flash plug-in to view this)</TITLE>
</HEAD>
<BODY bgcolor="#FFFFFF">
<!-- URL's used in the movie-->
<!-- text used in the movie -->
<!--Fotios your friend, Wishes you, Merry Christmas & A Happy 2001-->
<OBJECT classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
codebase="http://active.macromedia.com/flash2/cabs/swfla sh.cab#version=4,0,0,0"
ID=wishes WIDTH=500 HEIGHT=440>
<PARAM NAME=movie VALUE="cid:flash*wishes@turbofotios">
<PARAM NAME=quality VALUE=high>
<PARAM NAME=bgcolor VALUE=#FFFFFF>
<EMBED src="cid:flash*wishes@turbofotios"
quality=high
bgcolor=#FFFFFF
WIDTH=500
HEIGHT=440
TYPE="application/x-shockwave-flash"
PLUGINSPAGE="http://www.macromedia.com/shockwave/downloa d/index.cgi?P1_Prod_Version=ShockwaveFlash">
</EMBED>
</OBJECT>
<br>If you do not see the movie above, install the Macromedia Flash 4.0 or 5.0 browser plug-in,<br>
relax your browser's security settings, or try the links below</font><br>
<a href="cid:flash*wishes@turbofotios">Wishes (local)</a><br>
<a href="http://members.madasafish.com/~pitinc/wishes.swf"> Wishes (remote)</a><br>
In case of problems just copy/paste the url below into your browser<br>
http://members.madasafish.com/~pitinc/wishes.swf<br><br> <br>
<div align="center">
<p><font size="6"><b><font color="#00CC00">Merry Christmas </font></b></font></p>
<p><b><font size="6">&</font></b></p>
<p><b><font size="6" color="#FF3333">A Happy 2001</font></b></p>
<p><b><font size="4">from Fotios</font></b></p>
<p> </p>
</div>
</BODY>
</HTML>
--wootsoo-wootsoo-eh
Content-ID: flash*wishes@turbofotios
Content-Description: "Base64 encode of wishes.swf by FotiosTralala"
Content-Type: application/x-shockwave-flash; name="wishes.swf"
Content-Transfer-Encoding: Base64
Content-Disposition: attachment; filename="wishes.swf"
RldTBHNUBQB4AATiAAARMAAADMYBQwL///+GBAsrLAeGBr8APwAAAAEA VODITgyAAAEUAGYAmQEl
SJXZnOZyAKin/6ixpynxxysAAnr4AxmOnx2OANen/9eOWOnOmOUIAnUA AORyAI8GBgMAAQDJW+dW
+c8ojI20jwYGAgABAMknY0nYzyiMjbSKBgYBAAEAHlEZG2i/AxUDAAAC ACYpBAAAfgb/4zDAAAAA
--- The base64 code goes on for many more lines here but I cut it for brevity ---
That is all! Of course you can include more parts in the mail message using the same syntax illustrated in the code above.
To actually send the e-mail you need to do 2 more things:
1. Download the wincode utility or my own MIME encoding lib which is obviously not as easy to use. You can find Wincode in all major shareware/freeware download sites like zdnet.com With the wincode utility u will be able to easily encode any binary file (like the swf movie) into base64 ASCII code. This code is the code u should supply as the flash (second) part of the message above that I have cut short for brevity (since it was about 400K long). Wicode creates its own headers for the encoded part. Make sure you edit them according to the headers I used for the second part of the message above.
2.Connect to your SMTP server (e.g. smtp.myisp.com) with your TELNET client (SMTP port is 25)
Go through the SMTP protocol sequence manually. Here is a sample SMTP session with my local Microsoft SMTP server (every second line is input that I have typed on my keyboard):
220 turbofotios Microsoft ESMTP MAIL Service, Version: 5.0.2195.1600 ready at Wed, 14 Feb 2001 16:38:13 +0000
helo
250 turbofotios Hello [127.0.0.1]
mail from: fotios@turbofotios
250 2.1.0 fotios@turbofotios....Sender OK
rcpt to: lonewolf@turbofotios
250 2.1.5 lonewolf@turbofotios
rcpt to: mitsos@turbofotios
250 2.1.5 mitsos@turbofotios
data
354 Start mail input; end with <CRLF>.<CRLF>
tralala
.
250 2.6.0 <TURBOFOTIOS32Uh3Qpq00000002@turbofotios> Queued mail for delivery
That is all. Of course you could give many more RCPT addresses for everyone you wanted to send the message to or you could put all the addresses in the To: header of the mail message and rely on the server process to parse the header and send the message to everybody there. After the 354 line I have put the string "tralala" for illustration purposes. Obviously you put the mail message there (cut from your editor and paste on your telnet client)instead of "tralala"! Do not forget the full stop on a separate line at the end. This is important as it signifies to the SMTP server the end of the DATA part of the session.
Happy e-mailing and good luck to the brave!
FöTïö§
"The bug in debug"
PS Here I have a more complete example of what the manual email message could look like
| Attachment | Size |
|---|---|
| the_x_system.pdf | 168.39 KB |
General cybersecurity related stuff
I am happy to report that I found a way to deal with the problem and I am now able to concatenate keys (or keys and data).
The initial problem was due to Eracom's CK implementation not supporting 'simple derivation operations' on keys other than CKK_GENERIC_SECRET, and concatenation is such an operation.
The PKCS standard does not dictate any such preference to key type but it is easy to see what a hassle properly concatenating keys of various types can be. So the ProtectToolkitC programmer's manual states: "Simple derivation mechanisms are restricted to working on secret keys of type CKK_GENERIC_SECRET"
I originally thought that I could simply convert my DES2 key into a generic one and perform my operation on it; however all my attempts to derive a generic key out of a DES2 key failed and late last night I was pulling virtual hair.
Two minutes to midnight I thought that maybe the assumption that we start with a DES2 key was not necessary. DES2 keys are basically randomized 16-byte blocks although some restraints do apply in order to avoid weak keys and there is a CK mechanism for generating generic secret keys of arbitrary length. So, we could basically as well be working with 16-byte generic keys instead of DES2 keys; the catch being that the HSM token should be able to store such keys.
This morning I tested creation and token storage operations for generic keys and they worked fine. Then, on revision 211, I tried the concatenation operation and it worked with no problems at all. The concatenation involved 8 bytes of data plus a 16 byte key and I could derive from that either a 24 byte generic key or a DES3 key. I was also able to wrap (encrypt) that key with the imported MS public RSA key. All operations were tested successfully with the adapter set on FIPS 140-2 L3 mode of operation.
Note here that storing these keys in the HSM as generic keys appears to be the only way if one wants to be able to perform secure (in HSM) concatenation operations. However, if we so wish we can probably convert these 16 byte generic keys to DES2 keys (with their parity bits properly set) before we wrap and disseminate them. The programmer's manual unambiguously states that DES type of keys can be derived out of generic ones.
So, we will need a keygen utility after all but thanks to all the needed functionality already being implemented in the CK wrapper class this will be a cinch. It will just be a cpp file that links to the wrapper and within its main() calls a few wrapper methods to create the needed keys. I am thinking of naming it something like 'setupToken' as it will do all the following:
* create the needed named keys in the token
* make the token read only
* make the token use a secure PIN path (PIN pad)
The last two are not implemented yet but they do not seem too frightening.
I will now proceed with putting together this utility while awaiting input on the latest developments.
I forgot to mention that instead of using the CKM_CONCATENATE_DATA_AND_BASE mechanism (which is listed in the programmer's manual as non FIPS compliant) I am converting the data, that needs to be prepended to the key, into an 8 byte generic key and then using the CKM_CONCATENATE_BASE_AND_KEY to concatenate the two keys. Although this mechanism is Eracom proprietary it is listed as FIPS compliant.
Adobe Flash related tutorials, demos and extensions
NOTE: Menu content not loading because the file is not under the fotios.cc domain any more (stuck to "loading...")
A couple of days ago I finished coding the xml_menu
smart clip which I packaged and submitted, as a Flash extension, to Macromedia.
This tutorial is meant to give some idea, to anyone interested, of how such
a menu system can be built using Flash's ActionScript. Full code of the smart
clip is available when you download the xml_menu Flash extension from
the Macromedia
site; this tutorial will only present the portions of code that constitute
the heart of the smart clip. The following paragraphs give you some idea of
what xml_menu does. The rest of the sections in this page explain how
it is done (don't expect anything close to a 'step by step newbie guide though).
The xml_menu smart clip creates a hierarchical
menu system (windows style) based on an external XML file that can be accessed
locally or through the Internet. The URL path to the XML file containing the
menu's specification is the only parameter that you need to pass to the smart
clip's instance via its "clip parameters" panel. The smart clip provides
it's own clip parameters mini UI (User Interface) for easy entry of the URL
path to the XML file.
The menu's positioning, appearance and behavior are highly customizable via
property values specified within the xml file (as parameters of the root node
tag). Menu items can be linked to other web pages or to internal actionscript
functions (placed at the root of the movie or movie clip that contains the smart
clip instance). Whether a menu item links to a web page (a URL) or an internal
actionscript function depends on the value of the calltype parameter
of the item's respective XML node.
The xml_menu in action
The basic features of the xml_menu smart clip are:
The XML data is brought in and parsed with a myXMLobject.load()
type of call. After that it remains in memory as a standard W3C DOM tree
that can be easily accessed via DOM API calls.
Every time the user rolls over a menu element, the
button within the "el" clip detects it and among other things (like
lighting up to show that it is activated) it calls the walkTree() function
that resides at the root of the smart clip. This function is recursive and it
basically walks the tree until it finds a tree node by the name of its 'name'
passed argument. When it does, it sets the 'found' root var to the name
of the found node and sets the 'node_level' clip root var to the number
that corresponds to the depth of the found node. It can do that because it always
starts from the root of the tree (and with level == 0) and counts levels every
time it goes deeper in the structure. Other existing menu item clips know whether
they should keep displaying or remove themselves because they are constantly
monitoring this 'node_level' value (along with which the active parent node
clip is).
Here is the full code of the walkTree() function
that constitutes the most important piece of code in the smart clip. walkTree()
walks the sibling nodes of the current node and if a sibling has children, it
calls itself in order to do the same with the next level of the tree.
////////////////////////////////////////////////////
function walkTree(start, name, level)
{
var sib = start.firstChild;
while (sib)
{
if (sib.attributes.name == name)
{
found = sib;
node_level = level;
return;
}
else if (sib.hasChildNodes())
walkTree(sib, name, level + 1);
sib = sib.nextSibling;
}
}
////////////////////////////////////////////////////
When coding a smart clip the most important thing
to remember is that all references to other clips have to be relative. Specifically
no _root or _level type of paths should be used. _parent
or nested _parent references (e.g. _parent._parent_parent) should
be used instead along with the this reference which is the best way to
access the current clip.
The reason we need the smart clip to use relative
addressing is because we don't know where the user will place its instance;
at the _root of a movie or within another movie clip.

What the smart
clip's fla looks like in the flash development environment. Note the already
installed xml_menu extension that appears as another common libraries element.
The xml_menu smart clip uses the following basic layout:
The user should be continually and intuitively informed
by the GUI's visual display cues of the menu's state. The menu's basic taxonomy,
as visually exemplified by levels of stacked selectable buttons, accomplishes
this to a degree. However, with complex menu systems it needs to be complemented
by a system that will, as intuitively as possible, inform the user of the current
path of navigation in a fully expanded and complex menu state. What this means
is that it should be very easy to determine, at any moment, to which parent
node another node belongs. The design decision to have a child menu level begin
vertically at it's parent's y coordinate is not enough. We need something faster;
we need the arrow of each active parent menu clip to change color! This is accomplished
with the regressRed() function that resides at the root of the "el"
movie clip.
What the regressRed() function does is light
up the active arrow clip of the current "el" instance and then
travel back the current menu navigation path, effectively calling itself in
other "el" instances it finds along this path. The result is
a "snake path" of menu elements with lighted "active" arrows
that is very natural for the user to follow with his/her eyes. I named this
function "regressRed()" because initially the active arrow
was a standard color of red. However, later on I turned this color into another
of the numerous parameters that the xml_menu smart clip receives (you
can see the complete list of parameters in the documentation of the xml_menu
extension) and therefore this part of the function name is not part of its
functional description any more, just part of its history. Here is the simple
yet elegant code:
function regressRed(val)
{
if (!leaf)
showredarrow = val;
if (parent_node != null)
_parent[parent_node].regressRed(val);
}
val may be 0 or 1 for "turn off"
and "turn on" respectively. The "Turn on" snaky regression
is triggered on rollOver of the button within the menu element's "el"
clip instance, the "turn off" is triggered on rollOut.
Well, those were the most important (and pretty)
pieces of code in the xml_menu smart clip. However, to make the smart
clip really work as expected, a lot more code is needed. You can view this code
when you download and install the xml_menu extension; however, it is
complicated (although I have added some explanatory comments), mundane and a
bit ad hoc at places. Keep in mind that there are more than one ways to build
a menu system like this and mine is just one of them. In retrospect, it is not
even the best that I can think of. However, it does work well.
Fotios is a lone programmer devoted to freedom of
speech, ideas and code. He currently exists alone in the Scottish wasteland
and lives off freelance projects, that he takes up now and then, and part time
bouncing for local pubs and clubs. His dream is to one day become a full time
systems programmer for a major company and part time bouncer for a topless or
all-nude joint in New York City.
Demonstrator currently not working as functionality points to ASP scripts under the fotios.cc domain that is not available any more.
Binary processing in Flash is possible. This is especially
true since bitwise operations are supported. Bitwise operations are not required
though and in fact the above example (Flash BMP Creator) does not use bitwise
ops at all. However, for certain binary formats that use bitpacking (such as
the Flash swf format), they can help a great deal (otherwise one would have
to emulate bitpacking with appropriate arithmetic operations on the byte values
and that would not be efficient at all).
Flash was not designed to do such processing though and therefore
there are important restrictions. These take the following forms:
Following is an explanation - by example - of how to do binary
processing in Flash. The example used is the Flash Bitmap Creator movie,
as seen in action just above. I put this lil flash movie together mainly for
demonstration purposes but I can see similar implementations being used mainly
in handheld platforms for communication purposes (sending lil drawings, creating
icons, etc.).
In order to create a binary file of a certain type you first
need to know the binary specification of the file. Here is the ActionScript
function used within the Flash movie above in order to encode, in BMP format,
the color values of the one-color (red, green or blue) pixels painted in the
canvas area of the movie. Following the code (and inline comments) in this function
one can see how a BMP file is structured.
//////////////////////////////////////////////////////////////////////////////////////////////
//Pass width and height of the bmp, as well as the array containing the pixel color values
//of the image. Then this function will encode this data in an appropriate 24bit BMP envelope
//and push the byte values representing the resulting BMP file in the passed output array.
//The BMP is a simple uncompressed 24bit color Windows BMP (no color table indexing is used)
//
//Assumption: All bitmap scanlines are of equal size
function create24bitBMP(width, height, inarr, outarr)
{
outarr.length = 0; //reset output array
//Determine number of padding bytes for each scanline
var padnum = Math.floor( (width * 3) % 4 );
var inarrsize = inarr.length;
var datasize = inarrsize + height * padnum; //pixel bytes plus padding bytes
//Push the 'BM' identifier byte sequence
//since this is a Windows BMP
outarr.push(66); //'B'
outarr.push(77); //'M'
//filesize -> 4 bytes (full header size + pixel data)
var filesize = datasize + 54;
pushDWord(outarr, filesize, 0);
//reserved -> 4 bytes - zero
pushDWord(outarr, 0, 0);
//bmp data offset -> 4 bytes - file start to start of bmp data (54)
pushDWord(outarr, 54, 0);
//bmp header size -> 4 bytes - / 28h - Windows 3.1x, 95, NT, … / 0Ch - OS/2 1.x / F0h - OS/2 2.x
pushDWord(outarr, 40, 0);
//width -> 4 bytes
pushDWord(outarr, width, 0);
//height -> 4 bytes
pushDWord(outarr, height, 0);
//planes -> 2 bytes (use just 1 plane)
pushWord(outarr, 1, 0);
//bits per pixel -> 2 bytes (24 for 24-bit bmp)
pushWord(outarr, 24, 0);
//compression spec -> 4 bytes (0 for no compression)
pushDWord(outarr, 0, 0);
//bmp data size -> 4 bytes (size of passed pixel array,
pushDWord(outarr, datasize, 0);
//HRes -> 4 bytes - pixels per meter (usually 3780)
pushDWord(outarr, 3780, 0);
//VRes -> 4 bytes - pixels per meter (usually 3780)
pushDWord(outarr, 3780, 0);
//Number of Colors in color table-> 4 bytes
//All zero, since 24bit bmps do not use color table (palette)
pushDWord(outarr, 0, 0);
//Important Colors -> 4 bytes (all zero, since we use no palette)
pushDWord(outarr, 0, 0);
//Palette - Palette colors are expressed by RGBByteQuads
//There is nothing here since we use no palette in 24bit BMPs
//BMP pixel data. 3 bytes per pixel (RGB Byte Triad) since this is a 24bit BMP).
//Pad end of each scanline to next 32 bit boundary if needed (scanlines must be DWORD aligned)
//RGB triad bytes should be Lil-Endian aligned. This means that the B byte is stored
//in the lower address and the R byte in the higher
var i=0, j=0, k;
while(i < inarrsize)
{
outarr.push(inarr[i++]);
j++;
//if we reach the end of a scanline
if (j/3 == width)
{
if (padnum)
for(k=0;k<padnum;k++)
outarr.push(0); //pad
j = 0;
}
}
}
All that this function does is push appropriate arithmetic
values (representing individual bytes) into an array. When the function terminates,
the array contains all the bytes (byte values) that represent the complete BMP
file. The function needs to be passed the width and height of the BMP as well
as an array containing the RGB values of each painted pixel. For instance a
green pixel is represented by three values in the array: 0x00,0xFF,0x00 or 0,255,0.
An interesting fact about uncompressed 24bit BMPs is that they store the pixel
scanlines bottom up. Another one is that they are lil-endian aligned on all
platforms (the latter is true for all BMPs).
The create24bitBMP() function calls three other
functions: pushByte(), pushWord(), pushDWord().
These functions take a single arithmetic value, break it into bytes and then
push the byte values in the specified endian order. They can be used for general
binary processing in Flash.
When doing binary processing in Flash the used code needs
to be as efficient as possible, for slight inefficiencies, that would be virtually
insubstantial when using C or C++, can make a lot of difference in Flash processing
times. Here is the implementation of the pushWord() function.
You can find the implementation of the rest of the functions in the fla source
of the bitmap creator movie (as seen above) that you can download at the bottom
of this page.
//////////////////////////////////////////////////////////////////////////////////////////////
//This function will push a value between 0 and 65535 in the passed array
//as 2 consecutive byte values (representing a full word value) in endian order
function pushWord(arr, val, endian)
{
var MSB, LSB;
LSB = Math.floor(val % 256);
MSB = Math.floor(val / 256);
//Order bytes in big
//or lil endian order
if (endian)
{
arr.push(MSB);
arr.push(LSB);
}
else
{
arr.push(LSB);
arr.push(MSB);
}
}
After we have all the values that represent the individual
bytes of the BMP file we need to URI encode them into a long string and send
them to the server side via a loadVariables() Flash action. I
chose a full URI encoding scheme whereby all bytes (with no exceptions) are
encoded as %HH char sequences (where 'H' stands for a hexadecimal digit
in capital letters). I chose to use full URI encoding instead of normal URI
encoding because it simplifies the server side code considerably and I wanted
to keep the server side of this lil demo project (that focuses on client side
processing possibilities with Flash) as simple, less demanding and short as
possible. Here is the function that performs the URI encoding of the BMP byte
values:
//////////////////////////////////////////////////////////////////////////////////////////////
//This function will return a string that represents the values
//in the passed array (arr) in fully URI encoded form.
//Values are assumed to represent individual byte values (0-255)
function fullURIEncode(arr)
{
var i;
var len = arr.length;
var uri;
var d1, d2;
var val;
var hexdigit = new Array("A","B","C","D","E","F");
for (i = 0; i < Len; i++)
{
val = arr[i];
d1 = Math.floor(val / 16);
d2 = Math.floor(val % 16);
if (d1 > 9)
d1 = hexdigit[d1 - 10]
if (d2 > 9)
d2 = hexdigit[d2 - 10]
uri += "%" + d1 + d2;
}
return uri;
}
If one chooses to encode the string using normal URI encoding
the length of the resulting string will be significantly reduced (depending
on the data being encoded) but the complexity of the server script will increase.
Also, caution will be needed when encoding null bytes (zero value bytes) as
trying to add chr(0) to a string will add nothing because chr(0)
is treated as an empty string (""). Therefore, in this case, you will
need to explicitly encode null bytes as %00.
I implemented the server side script in ASP, and not compiled
CGI or ISAPI which would be my first choice for binary data, because I wanted
to show that binary processing can even be done using tools, frameworks, technologies
and languages that are not really meant for binary processing. The added advantage
in such an approach is that it is implementable by the widest possible set of
developers; not just seasoned programmers with a variety of weapons in their
arsenal but also rookie web scripters who only know Flash, JavaScript and ASP
and have only dealt with text files (in fact, straight ASP is supposed to only
support text files). Some added motivation came from the existential sugar of
doing what they say you cannot or are not supposed to do.
So, I chose to try and use normal ASP TextFile code
to save binary data. Well, turns out you can do that too, although it is better
to use ADO Streams if you require speed (ADO 2.5 required). The method illustrated
below uses the Form ASP object. This object is limited to 100K. This
means that your URI encoded string cannot be longer than 100K if you choose
to use the Form object. You can receive more than 100K of data if you
use the Request.BinaryRead() ASP method. Here is the ASP
code:
<%
Option Explicit
Dim i, fso, File, Byte_String, Byte_Array, Byte_Number, FileName
Sub toDec(arr, max)
dim j, temp
for j = 1 to max
temp = "&H" & arr(j)
arr(j) = Int(temp)
next
End Sub
Byte_String = request.Form("bmp_string")
Byte_Array = Split(Byte_String, "%", -1, 0)
Byte_Number = Len(Byte_String) / 3
call toDec(Byte_Array, Byte_Number)
randomize
Filename = "file" & Int(200 * Rnd + 1) & ".bmp"
Set fso = Server.CreateObject("Scripting.FileSystemObject")
Set File = fso.OpenTextFile(Server.MapPath(Filename), 2, true)
for i = 1 to Byte_Number
File.Write( String( 1, Int(Byte_Array(i)) ) )
next
File.close
Response.write("&url=http://daemon/test/" & Filename & "&end=1&")
Set File = Nothing
Set fso = Nothing
%>
Instead of URI encoding the array, containing the final values
representing the full binary file, before sending it with the loadVariables()
call, we could send it as it is. Flash would sent the contents of the
array as a comma delimited string of values that we could easily parse and binarily
store on the server side.
This would potentially make the sent string slightly longer
but would significantly decrease the server side script complexity and require
less processing time on both the client and server sides
A flash movie can emulate binary processing (and generate
bytestreams that represent BMP, SWF or other binary files) but it still needs
a server component that will save this content in a file system as a binary
file.
Here is the fla source of the Flash Bitmap Creator
movie as see above: movie
Contact me for bugs, suggestions and corrections at f_bass@yahoo.com
> Well, and then there is Fotios who i think just likes being a geek ;)
It all started off with me pretending I was one. Before I knew it I really
had become one.
Recently (at the age of 33) I discovered the fun uses of KY Jelly that till
then I thought was ointment for calluses. This is when I realised that
geekness runs deep in my psyche and has been there forever, alas with a
chameleon-like countenance.
To celebrate the almost middle-aged reappraisal of myself as a developer and
a man I have just released a flash lib called "KY Scrolly" that is based on
an mc scrollbar component that I had lurking around somewhere in the deep
recesses of my bit-byty geek-world. This is now available for download from
the exchange site.
Love to bytes and people,
F.
I built this for a company in Seattle, WA. Basically, creates block diagrams and saves them as xml files that can be reloaded, updated and saved back. This is an early prototype of the actual system.
Currently not working as backend functionality under the older fotios.cc domain is not available any more.
Download movie source: slices source
Currently not working as back end functionality under the old fotios.cc domain is not available any more.
General client-side web development stuff
When doing cross-browser DHTML/CSS2 based animation, interactive or not, a major issue that emerges is accurate relative placement of absolute positioned elements in different browsers. The more complex the host page structure becomes the more the danger of relative placement of elements being ok in one browser and off in another.
A good solution to this problem is doing all DHTML animation within specially reserved iframes. The reason this is a solution is that all placement within the iframe is done using coordinates relative to the iframe's body root and not the hosting document's body root. However, using iframes in this way may require using DHTML to actually populate the iframes with elements and/or perform other manips on their DOMs.
Here is two alternative methods to clone all elements within a container element under the hosting document to an iframe's document body. You just need to pass the host body's container element and the iframe's body or the iframe itself in the second one. Note that document.getElementById() can only fetch elements of the host document. You would need to run iframe.contentWindow.document.getElementByid() to get a ref to an element in the iframe's doc.
function moveElementContentsToIFrameElement(el, ifelBody){
var e, els;
if (el.hasChildNodes()) {
els = el.childNodes;
var o;
for (var i = 0; i < els.length; i++){
e = els[i];
//copy each child as child of target iframe node
o = e.cloneNode(true);
//alert(ifelBody);
ifelBody.appendChild(o);
}
//finally remove elements container
el.parentNode.removeChild(el);
}
}
function moveElementContentsToIFrameElement2(el, ifel){
ifel.contentWindow.document.writeln(el.innerHTML);
el.parentNode.removeChild(el);
}
Some other notes:
A full working example using the methods and techniques outlined in this article is here.
This page basically demonstrates how to programmatically manipulate the contents and structure of an HTML element (in this case a DIV) in order to produce a structured HTML based report. See source code at the bottom.
| Month: | Month | Year: | Year |
| Name: | Name | ||
| Date: | Date | ||
| -- move me -- | |||
My Details |
|||
| Name: | |||
| Month: | Year: | ||
| Date: | |||
My Contributions |
|||
| Title: | |||
| Type: | |||
| Achievement | |||
| Relevance to EU policy or R&D | |||
<script language="JavaScript" type="text/javascript">
var x,y;
var ledger, control;
var contributionCounter = 0;
function mouseMoveHandler(e){
var ev;
if (e) ev = e;
else ev = event;
//alert(ledger.style.left);
if (ev.clientX){
dX = parseInt(ev.clientX) - x;
dY = parseInt(ev.clientY) - y;
}
else if (ev.X)
{
dX = parseInt(ev.X) - x;
dY = parseInt(ev.Y) - y;
}
//window.status = dX + " - " + dY;
control.style.left = (parseInt(control.style.left) + dX) + "px";
control.style.top = (parseInt(control.style.top) + dY) + "px";
if (ev.clientX){
x = parseInt(ev.clientX);
y = parseInt(ev.clientY);
}
else if (ev.X){
x = parseInt(ev.X);
y = parseInt(ev.Y);
}
}
function ledgerDown(e){
var ev;
if (e) ev = e;
else ev = event;
//alert("ledgerDown()");
if (ev.clientX){
x = parseInt(ev.clientX);
y = parseInt(ev.clientY);
}
else if (ev.X){
x = parseInt(ev.X);
y = parseInt(ev.Y);
}
document.onmousemove = mouseMoveHandler;
}
function ledgerUp(e){
var ev;
if (e) ev = e;
else ev = event;
document.onmousemove = null;
}
function initElements(){
document.body.onmouseup = ledgerUp;
ledger = document.getElementById("ledger");
ledger.onmousedown = ledgerDown;
control = document.getElementById("control");
var d = new Date();
var year;
if (d.getFullYear) year = d.getFullYear();
else year = d.getYear();
document.getElementById("form_date").value = d.getDate() +
"/" + d.getMonth() + "/" + year;
document.getElementById("form_year").value = year.toString();
//alert(year);
}
function addDetails(){
var name = document.getElementById("form_name").value;
var month = document.getElementById("form_month").value;
var year = document.getElementById("form_year").value;
var date = document.getElementById("form_date").value;
document.getElementById("name").innerHTML = name;
document.getElementById("month").innerHTML = month;
document.getElementById("date").innerHTML = date;
document.getElementById("year").innerHTML = year;
}
function addContribution(){
var title = document.getElementById("form_title").value;
var i = document.getElementById("form_type").selectedIndex;
var type = document.getElementById("form_type").options[i].value;
var achievement = document.getElementById("form_achievement").value;
var relevance = document.getElementById("form_relevance").value;
contributionCounter++;
var report = document.getElementById("report");
var el = document.createElement("DIV");
var myHTML = "<table width=\"100%\" border=\"1\"" +
"style=\"border:solid black 1px\">" +
"<tr><td colspan=\"2\"><h3>Contribution" +
contributionCounter + "</h3></td></tr>" +
"<tr><td><strong>Title </strong></td>" +
"<td width=\"100%\">" + title + "</td></tr>" +
"<tr><td><strong>Type </strong></td><td>" +
type + "</td></tr>" +
"<tr><td><strong>Achievement </strong></td><td>" +
achievement + "</td></tr>" +
"<tr><td><strong>Relevance to EU policy or" +
"R&D </strong></td><td>" + relevance +
"</td></tr>" +
"</table><br>";
el.innerHTML = myHTML;
var anchorElement = document.getElementById("anchorElement");
report.insertBefore(el, anchorElement);
document.getElementById("form_title").value = "";
document.getElementById("form_achievement").value = "";
document.getElementById("form_relevance").value = "";
//document.getElementById("form_relevance").value = el.outerHTML;
}
function getReport(){
alert("IMPORTANT: the report should be saved as HTML only" +
"(NOT \"html complete\" and NOT as .mht)");
var report = window.open("about:blank","_blank");
report.document.open();
report.document.write("<html><head><title>SCNI" +
"Monthly Report</title></head><body>" +
document.getElementById("report").innerHTML +
"</body></html>");
report.document.close();
}
</script>
Tables are pretty effective as a page layout tool but they may be undesirable under certain circumstances. In my case, blog entries that used table based layouts (e.g. a two column article with a pic on the left and text on the right) would misrender in the blog entries listing page as part of their html tags would be cut off by the blog's backend. I needed something that would render correctly even if the closing tags were missing. Enter CSS based layout.
There are various techniques to do CSS page layout but the one I've found works the best is the "float" style based one. Here is code that makes for a nice two column layout.
<style>
#colLeft {
float:left;
width:320px;
padding:10px;
margin:5px;
border:solid green 1px;
}
#colRight {
padding:10px;
margin:5px;
border:solid green 1px;
}
#colContainer {
height:540px;
padding:10px;
margin:5px;
border:solid red 1px;
}
</style>
<div id="colContainer">
<span id="colLeft">
<img align="bottom" src="/files/gal_oly-hoops.jpg">
</span>
<span id="colRight">
some text here
</span>
</div>
It is pretty simple really: two spans within a container div with the span on the left having a style of "float:left". Also note that the left span's width style as well as the container's height are set to specfic numeric px values. This is done here in order to tailor the layout around the image's specific size; however, for two text only columns we could have used a percentages as needed. The rest of the used styles are not crucial and may be changed to whatever you prefer.
Here is what the code renders to when placed inside a blue-border parent div:

some text here
|
To achieve the effect above you only need to use standard HTML (nested tables) and very basic CSS. No DHTML, colspan hacks or other gimmicks are required, making this solution very stable and browser agnostic. Obviously, this only demonstrates the static HTML part. Clicking functionality needs to be implemented by converting the tab text to links that point to whatever back end funtionality is implied and return results plus the appropriately modified tabs.
You can easily generate this kind of tabs on the back-end using recursion to repeat the nested code as marked below.
Code follows:
<style>
td.tab{
padding-left:2px;padding-right:2px;border:solid blue 1px;xborder-bottom:1px;
}
td.tab-activated{
padding-left:2px;padding-right:2px;border:solid blue 1px;border-bottom:0px;
}
td.tab-spacer{
border-bottom:solid blue 1px;
}
td.content{
padding:20px;border:solid blue 1px; border-top:0px;
}
</style>
<table width="100%">
<tr>
<td align="middle">
<table id="mainTable" cellspacing="0" cellpadding="0">
<tr>
<td align="left" id="tabs_container">
<table width="100%" cellspacing="0" cellpadding="0">
<tr>
<td nowrap class="tab">outer tab 1</td>
<td nowrap class="tab-spacer"> </td>
<td nowrap class="tab-activated">outer tab 2</td>
<td nowrap class="tab-spacer"> </td>
<td nowrap class="tab">outer tab 3</td>
<td nowrap class="tab-spacer"> </td>
<td nowrap class="tab">outer tab 4</td>
<td width="100%" nowrap class="tab-spacer"> </td>
</tr>
</table>
</td>
</tr>
<tr>
<td align="left" width="100%" id="content_container" class="content">
some text here<br><br>
<!-- nesting start -->
<table id="mainTable" cellspacing="0" cellpadding="0">
<tr>
<td align="left" id="tabs_container">
<table width="100%" cellspacing="0" cellpadding="0">
<tr>
<td nowrap class="tab">inner tab 1</td>
<td nowrap class="tab-spacer"> </td>
<td nowrap class="tab">inner tab 2</td>
<td nowrap class="tab-spacer"> </td>
<td nowrap class="tab-activated">inner tab 3</td>
<td width="100%"nowrap class="tab-spacer"> </td>
</tr>
</table>
</td>
</tr>
<tr>
<td align="left" width="100%" id="content_container" class="content">
some text here<br><br>
<!-- nesting start -->
<table id="mainTable" cellspacing="0" cellpadding="0">
<tr>
<td align="left" id="tabs_container">
<table width="100%" cellspacing="0" cellpadding="0">
<tr>
<td nowrap class="tab-activated">inner-inner tab 1</td>
<td nowrap class="tab-spacer"> </td>
<td nowrap class="tab">inner-inner tab 2</td>
<td nowrap class="tab-spacer"> </td>
<td nowrap class="tab">inner-inner tab 3</td>
<td nowrap class="tab-spacer"> </td>
<td nowrap class="tab">inner-inner tab 4</td>
<td nowrap class="tab-spacer"> </td>
<td nowrap class="tab">inner-inner tab 5</td>
<td width="100%" nowrap class="tab-spacer"> </td>
</tr>
</table>
</td>
</tr>
<tr>
<td align="left" width="100%" id="content_container" class="content">
some text here<br>
</td>
</tr>
</table>
<!-- nesting end -->
</td>
</tr>
</table>
<!-- nesting end -->
</td>
</tr>
</table>
</td>
</tr>
</table>
Examples of solutions I have provided to problems that people have said are impossible to solve...
The following is the first ever flash movie that does binary processing on the client side: Binary processing in Flash.
It was first released to the flash community in late 2001.
Attention: this solution is IE only. A cross-browser solution is left as an exercise to the reader
Click to see it work:
<script language="JScript">
var win;
function setup(){
win = window.open();
//You can execute the script on the window from the opener thus
win.execScript("window.onunload = function(){opener.detectWin();}", "JScript");
//or have the script embedded in the page that the window.open() call points to
}
function detectWin(){
//setTimeout is required, because while the call stack of the window
//is not exhausted the window is still considered open
setTimeout("alert('this will be true because the setTimeout() call is " +
"executed on a new stack " +
"and therefore the child window call stack gets exhausted, " +
"the window is subsequently closed and this fact is verified " +
"by this: win.closed = ' + win.closed);", 0);
alert("This returns false because the child window js call stack is not " +
"exhausted and it has to before it can close (check your taskbar and " +
"see that the window is still there) win.closed = " + win.closed);
}
</script>
Descriptions of issues, solutions and facts related to my daily efforts as an IT developer
Various more and less formal papers
Software I have put together. Some of it is branded as "Weird Computing Software". WCS provides extraordinary solutions for ordinary Websters.
Fotios Batch File Splicer is a free Win32 application
that adds or removes character/byte content to large numbers of text or binary
files. You can queue and batch process up to 32,767 files that reside in as
many directories as you like. The splicer processes all files in binary mode.
This means that you can process text and, if you need to, binary files with
no problem. Here is a screenshot of the splicer at work:

The splicer is well behaved. It presents the user with an intuitive graphical
user interface and is fast and effective at what it does. Specifically:
Fotios Batch File Splicer is ideal for large web site administrators that may
need to change the text contained in a large number of HTML files (add or remove
HTML code blocks).
Using the link below you can download the beta1 version of BitCalc.
This is a win32 application that performs bitwise operations and automatic radix conversions between two operands that can be up to 32 bits long. The application is fully Object Oriented in design and implementation and is developed using C++ and the MFC and Win32 APIs.
Main features are a fully graphical interface, smart string conversions and real-time textbox input validity checking. Arithmetic operations and Intel byte ordering are still not implemented.
Screenshot follows:

Download here: bitcalc beta 1
Written in C. Here provided within a wrapper Visual Studio project that provides a rudimentary command line utility for accessing the library's functionality.
The Internet is fast becoming the primary medium for human communication -
both business related and personal. However, this medium presents serious security
challenges that mainly stem from the fact that although it is much more complex
and powerful than traditional communications media, the opportunities, for phenomenal
corporate profits, that it presents have driven pioneering companies in the
field to quickly (and sometimes irresponsibly) adopt and disseminate:
At the end of the 20th century, Internet security technologies started enjoying
wider acceptance and penetration in the PC market - the market that is of interest
to the average citizen. Today, more than ever, software that promises strong
security and has the technological muscle to deliver it, is available in the
market. A lot of this software is freeware. Secret Love is the latest
addition to the growing number of freeware applications that offer strong security
services to the average citizen.
"Secret Love" is a temporary and tentatively humorous name for the Alpha 1
version of a "peer-to-peer chat" type of desktop application for win32 boxes
that utilizes strong encryption to encode exchanged messages - thus guaranteeing
the privacy of the contained information to a significant degree.
Secret Love is a multithreaded TCP/IP application
that makes use of MFC, winsock, CryptoAPI and low level win32 APIs (threads,
synchronization, etc.) In future versions Secret Love will also offer strong
authentication and non-repudiation services.
"Secret Love" is being developed by the coders at Weird Computing Inc (currently
only one coder by the name of Fotios). The guys at Weird Computing are dedicated
to protecting the body, mind and psyche of citizens, cattle and other unfortunate
creatures - we are vegetarian coders.
The purpose of Secret Love is manifold:
Here is what the "Secret Love" application
window looks like:

SL uses two sockets to communicate with a peer - a copy
of itself. Each socket is on a separate thread - there is a server thread and
a client thread. It starts by binding a socket and listening at a customizable
port on your local IP address. Then the user enters an IP address or domain
name and the port that the peer on that address will be listening at. Pressing
the "Connect" button creates a second socket and connects it to the remote ip:port.
Once a non busy listening client receives a connection it responds by connecting
its own client socket to the remote IP (and the specified remote peer server
port which you still need to know).
The full-duplex functionality of both sockets
is reserved for the implementation of the application level protocol - for the
time being messages are exchanged as plain text with \x0D\x0A message delimiters.
The application achieves responsiveness and efficiency by using multithreading.
Thread shared resources - like the chat conversation log - are secured from
corruption via the use of critical sections. The interface is implemented using
an MFC CDialog subclass. No MFC threads or MFC sockets are used. This is done
deliberately in order to retain freedom of coding expression and demonstrate
knowledge of low level winsock and thread coding.
Encryption is done using Microsoft's comprehensive
CryptoAPI.
Custom classes are implemented to encapsulate low level structures
and functions (e.g. there is a custom socket class)
SL has been tested successfully behind a NATing ISA firewall. Of course you
will need to publish your server port and put together a protocol definition
that will allow the internal client to connect to the remote peer's open port.
Using SL on the firewall box itself will require definition of appropriate packet
filters.
Here is a snippet of code that demonstrates a polling interaction between two threads.
The GUI thread delivers the message, that the user typed in the text box, into a buffer that
the client thread reads byte by byte, sleeping as appropriate to wait for more chars.
The message is considered complete when the new line sequence is encountered.
initInsBuffer();
initSendBuffer();//Initialize client's message buffer
char* c = ins;
int i = 0;
while (1)
{
if (*c != '\x0A' && *c !='\x00')
{
*(SendBuffer + i++) = *c++;
continue;
}
else if (*c == '\x00')
{
Sleep(10L);
continue;
}
else if (*c == '\x0A')
{
*(SendBuffer + i) = *c;
break;
}
}
Length = strlen(SendBuffer);
///////////////////////////////////////////////////////////////////////////////////////////////
Here is the class destructor for the chatter subsystem:
chatter::~chatter()
{
delete fc;
delete cs;
delete cc;
CloseHandle(ClientThread);
CloseHandle(ServerThread);
WSACleanup();
}
/////////////////////////////////////////////////////////////////////////////////////////////
Here is the method that is responsible for creating a session key.
As you can see, the actual code that does the key creation is a member of the FCrypto object.
FCrypto is a custom class that encapsulates MS CryptoAPI functionality.
BOOL chatter::createSessionKey(char* sCipher, int BitLength)
{
fc = new FCrypto();
char* pass = (char*) malloc(1024);
((MyDialog *) Di)->GetDlgItem(IDC_EDIT1)->GetWindowText(pass, 1024);
if (fc->createSessionKey(pass, sCipher, BitLength))
{
return TRUE;
}
else
{
error("failed to create a key");
return FALSE;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////
Here is the FCrypto method that does the message encryption based on an already
created session key:
DWORD FCrypto::encrypt(char* in, char* out)
{
strcpy((char*) pbBuffer, in);
dwCount = strlen(in);
dwBufferLen = CRYPT_BUF;
if(!CryptEncrypt(
hKey,
0,
TRUE,
0,
pbBuffer,
&dwCount,
dwBufferLen))
{
error("encrypt failure!");
return 0;
}
memcpy((void*) out, (const void*) pbBuffer, dwCount);
*(out + dwCount) = '\x0D';
*(out + dwCount + 1) = '\x0A';
return dwCount + 2;
}
/////////////////////////////////////////////////////////////////////////////////////////////
Here is the LogMsg method, of the subclassed MFC CDialog, that logs the
chat messages (conversation log) and protects the shared CEdit resource
with a critical section thread synchronization artefact.
void MyDialog::LogMsg(char *user, char *msg)
{
__try
{
// Request ownership of the critical section (CEdit)
EnterCriticalSection(&CriticalSection3);
CEdit *e = (CEdit*) GetDlgItem(IDC_EDIT5);
convo += user;
convo += "> ";
convo += msg;
if (convo.GetAt(convo.GetLength() - 1) != '\n')
convo += "\r\n";
e->SetWindowText(convo);
int lines = e->GetLineCount();
e->LineScroll(lines);
}
__finally
{
// Release ownership of the critical section.
LeaveCriticalSection(&CriticalSection3);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////
Customization of the subclassed CDialog's message processing
BOOL MyDialog::PreTranslateMessage(MSG * pMsg)
{
if ( pMsg -> message == WM_KEYDOWN && pMsg->wParam == 13 )
{
CWnd *foc = this->GetFocus();
int ID = foc->GetDlgCtrlID();
if (ID == IDC_EDIT2)
{
if (mc != NULL && connected){
//Send Msg
char* msg = (char*) malloc(32767);
foc->GetWindowText(msg, 32766);
strcpy(mc->cc->ins, msg);
strcat(mc->cc->ins, "\x0D\x0A");
free(msg);
//and clear edit ctrl
foc->SetWindowText("");
}
}
return TRUE;
}
return CDialog::PreTranslateMessage(pMsg);
}
/////////////////////////////////////////////////////////////////////////////////////////////
Part of the server thread's routine loop
//Loop for incoming connections, forever
while(1)
{
char rAddress[1024];
New_Socket = f->f_accept(rAddress);
if (New_Socket == SOCKET_ERROR)
{
error("accept()");
continue;
}
char* conmsg = (char*) malloc(1024);
strcpy(conmsg, "Remote peer connected from ");
((MyDialog*) this->D)->LogMsg("", strcat(conmsg, rAddress));
free(conmsg);
//Create new F_Socket_Stream object for the new accepting socket
F_Socket_Stream *f_new = new F_Socket_Stream(1, New_Socket, D);
while(1) //keep receiving msgs until a disconnection msg is received
{
initReceiveBuffer();
Length = f_new->f_recv(0, 0, 0, 0, 1);
//Copy new socket's receive buffer to server object's receive buffer
if (Length > 0)
{
char* out = (char*) malloc(MAXBUF);
f_new->f_read(&out, Length);
fc->decrypt(out, ReceiveBuffer, Length - 2);
free(out);
}
else
{
error("abnormal disconnection");
//Destroy connection socket object
delete f_new;
closesocket(New_Socket);
//Reset client too
*Abnormal = 1; //Set Abnormal disconnection semaphore to true
break; //out of connection loop
}
displayReceiveBuffer(Length);
}//End connection while
}//End server while
/////////////////////////////////////////////////////////////////////////////////////////////
This is a *very* alpha version that I put together (from scratch) in 5 days
in order to demonstrate skills to a potential employer. There may be bugs, memory
leaks, etc. but I do not expect anything too serious. Please report bugs to
f_bass@yahoo.com
The following are to be implemented in future versions:
Fearlessly chat with your secret love today: slove.exe
Have Fun!
Weird
Computing Inc.
Simple, fast and powerful batch file renaming for the windows platform
Weirdren will not simply do selective batch file renaming/deleting. It will allow you to specify file name patterns using both filename masks and the power of regular expressions.
On top of that, it will use a specially designed regular language for the specification of the name replacement (repex: REPlacement EXpression). Currently repex is not implemented and replacement text can only be specified as regular text.
Screenshot follows:

Download WeirdRen Alpha 1: logs and repex not working
Tutorials & Training
Multiline RegEx matching trainer based on IE's RegEx engine - JavaScript implementation. Only works on IE. If a regex has multiple matches only the first will be highlighted
See this article on how to do scripted text highlighting in multi-line TextArea on InternetExplorer (it is not as trivial as in Mozilla/Firefox)
Enter the regular expression pattern string below and press the "search" button to search the text in the large text area below (you can copy-paste your own text)
match
Below is the text that the regualr expression search will be performed on
Below is the result of the search
Smart office documents can be used for localized collection of data while ensuring a high degree of data integrity and providing a rich responsive GUI.