by Doug Schwartz
May 18, 2007
Introduction
In part 1 of this series I explained how to create an AIM Lite plugin that received a text file as part of an IM. In this article I show how to create the sending plugin. If you have not read part 1, this article will not make much sense. Since you are still with me, I am going to jump right into creating the sending plugin.
The sending plugin lets the user select a text file and sends that text file to their current buddy.
We are going to create the plugin in the following order:
- Create the plugin.xml file.
- Create the main.box file.
- Create the main.js file.
Creating the plugin.xml File
The plugin.xml file contains a single widget element.
This element can contain a number of sub-elements, but the only required sub-element is the uuid, which is a developer or deployment key. The only differences between this plugin.xml file and the one for the receiving plugin are the uuid, name, and description. Don't forget to replace YOUR_DEVELOPER_KEY with your developer key in the following code.
<?xml version="1.0" encoding="utf-8" ?>
<widget
uuid = "{YOUR_DEVELOPER_KEY}"
version = "1.0"
name = "SendTextFile"
description = "This plugin sends a text file"
vendor = "Me, Myself, and I Inc."
/>
Creating the main.box File
This file is exactly the same as the main.box for the receiving plugin. The main.box file contains a single window element.
This element defines the user interface (UI) for the plugin. A plugin can be visible, invisible (no UI), or visible only in response to an event. This plugin is invisible, and main.box contains the following text:
<?xml version="1.0" encoding="utf-8" ?>
<window
xmlns="http://www.aol.com/boxely/box.xsd"
xmlns:s="http://www.aol.com/boxely/style.xsd"
xmlns:on="http://www.aol.com/boxely/reaction.xsd"
on:constructed="onConstructed();"
on:destroyed="onDestroyed();"
s:height="0"
s:width="0"
hidden="true"
collapsed="true"
floating="true"
>
<code id="main" language="jscript" src="main.js"/>
</window>
You can easily tell the plugin is invisible by the hidden="true" element.
Creating the main.js File
The main difference in this plugin versus the receiving plugin is that
in this plugin the IM is not intercepted, but created in a new function, sendTextFile, which is invoked from the exec function when the plugin is selected.
The first four lines of main.js contain four global variables.
var kCommandId = 0; var gSession; var sendTo; var maxChars = 64;
Where:
kCommandId- Defines the integer value of the plugin command.
gSession- Caches the session object.
sendTo- Contains the name of the current buddy.
maxChars- Limits the number of characters we send in the IM.
Other than the cmd.text assignment, the
onConstructed function is the same in the sending plugin as the receiving.
function onConstructed() {
var dict = scene.paramsDictionary;
gSession = dict.valueForKey("session");
var pInfo = dict.valueForKey("pluginInfo");
var cmd = pInfo.addCommand(kCommandId);
cmd.text = "Send text file to current buddy";
scene.connectObject(gSession, "session_");
dict.setValueForKey(new commandListener(), "commandTarget");
}
The sending plugin does trap the IM to get the name of the current buddy. It could do this in a number of places, but I chose to intercept the IM in BeforeImSend. It saves the name of the current buddy in the sendTo variable. We will use this later to create the IM we send.
function session_BeforeImSend(session, imSession, recipient, im) {
sendTo = recipient.Name;
}
The Exec function only checks whether the incoming id is that of our command, kCommandId. If it is, Exec calls the sendTextFile function. Here is the Exec function.
commandListener.prototype.Exec=function(id, users) {
if (id == kCommandId) {
sendTextFile();
}
}
The sendTextFile function is where the action is.
It performs the following.
- Creates the Open File dialog box so the text file can be selected.
- Splits the filename from the path.
- Reads the file into a variable.
- Truncates the text if it is too long.
- Encodes the text.
- Creates a new IM.
- Gets the session with the current buddy.
- Sends the IM.
Here is the code of the sendTextFile function.
function sendTextFile() {
var filter = "Text Files (*.txt)|*.txt||";
var fileList = appUtils.openFileDialog(this.scene,
"Open File",
null,
null,
filter,
false);
if (fileList) {
// Split off path from filename
var pathFile = fileList.getValue(0);
var last = pathFile.lastIndexOf("\\") + 1;
var path = pathFile.substring(0, last);
var fName = pathFile.substring(last);
// Open file and read the whole thing in
var basics = shell.serviceManager.basics;
var fs = basics.fileStream;
var sr = basics.rawStreamReader;
fs.openForRead(pathFile);
sr.stream = fs;
var myFile = sr.readStringTillEndOfStream("");
fs.close();
// Get the # of chars in the file
var numChars = myFile.length;
if (numChars > maxChars) {
numChars = maxChars;
myFile = myFile.substr(0, maxChars);
}
// Just in case file has some chars that
// AIM Lite cannot digest directly
myFile = encodeURIComponent(myFile);
// Send filename, # of chars, then file
var prefix = fName +
":" +
numChars +
":" +
myFile;
// Create IM
var im = gSession.createIM(prefix);
// Get session with current buddy
// sendTo is
var imSess = gSession.CreateImSession(sendTo);
// Send the IM containing the file
imSess.SendIm(im);
}
}
Figure 1 shows an example of the Open File dialog box.

Figure 1. The Open File dialog box
As with the receiving plugin, the sending plugin also needs to create the
QueryStatus function. Here is the code for this function
and the commandListener object.
function commandListener() {}
commandListener.prototype.QueryStatus=function(id,
users) {
return (id == kCommandId) ? true : false;
}
Testing the Plugin
There is no easy way to test this plugin besides deploying it. So zip up plugin.xml, content/main.box, and content/main.js,
change the extension of the ZIP file to ".awi", double-click the AWI file, open two AIM Lite clients, create an IM session between the two, select the ReceiveTextFile plugin in one, select the SendTextFile plugin in the other, and finally, send the text file.
Conclusion
Now you understand how to create an IM and use it to send a short text file. The next step would be to remove the constraints of 64 characters and text only. I envision some sort of handshake protocol between the sending plugin and the receiving plugin. That way the sending plugin would be assured that the buddy on the other end has installed the receiving plugin. I also imagine buffering larger files as IMs, with the receiving plugin storing the intermediate chunks and concatenating them when the final piece arrives. Also, by encoding the original file and decoding it on the receiving end, there is no reason that non-text files could not be sent.
Resources
SendTextFileCode.zip contains the complete source code for this article. If you want to see this plugin at work:
- Install AIM Lite.
- Unzip SendTextFileCode.zip to get the source files.
- Open the plugin.xml file.
- Change
YOUR_DEVELOPER_KEYto your developer key. - Zip the files back up.
- Change the file extension to ".awi".
- Double-click the AWI file to install the plugin.
References
Here are a number of web pages where you can get further information about AIM Lite, plugins, and the source code for this article.
- AIM Lite Plugin contains some basic information on plugins and a number of sample plugins.
- The AIM Developer FAQ contains additional information about Open AIM and AIM plugins.
- AOL Developer Resources contains a wide variety of developer resources.
- aimInfo is a blog written by one of the AOL developers who wrote many of the AIM plugins.
- AIM Developer Key Management is where you go to get keys for your plugin.

call me right now please!!!
call me right now please!!!
good explication
Thanks you.
Bst Rgds,
Michael B.