I’ve got Buckets!

Jan 8, 2008

I have finished the “Hello World!” of connecting to Amazon S3 with LotusScript. I have basically completed a “ListAllMyBuckets” call.

I wish I could post all of my code but I’m still waiting to hear back from Julian Robichaux. I can always try and find him at Lotusphere.

The ListMyBuckets Agent:

Function FormatDateToISO8601(aDate As NotesDateTime) As String
	' Thanks to Joel Litton http://www.joelitton.net/A559B2/home.nsf/d6plinks/JLIN-5UU4B2
	Dim dtLocal As NotesDateTime
	Dim dtGMT As NotesDateTime
	Set dtGMT = New NotesDateTime( Left$(aDate.GMTTime, 22) )
	FormatDateToISO8601= Format$(dtGMT.LSLocalTime, "yyyy-mm-ddThh:nn:ss.000Z")
End Function

Sub Initialize

	Const mysecretkey = PUT YOUR SECRET KEY HERE
	Const myAccessKey = PUT YOUR ACCESS KEY HERE
	Dim myS3 As New AmazonS3_n3()
	Dim mydate As New XSD_DATETIME
	Dim mykey As New XSD_STRING
	Dim mysig As New XSD_STRING

	Dim dateTime As New NotesDateTime( "" )
	Dim hmacbuilder As String
	Dim formattedDate As String
	Call dateTime.SetNow

	Dim mybuckets As ListAllMyBucketsResult_n3
	formattedDate = FormatDateToISO8601(dateTime)
	Call mydate.setValueFromString(formattedDate)
	Call mykey.setValueFromString(myaccesskey)
	HMACBuilder = "AmazonS3ListAllMyBuckets" + formattedDate
	Call mysig.setValueFromString(HMAC_SHA1_B64(mysecretkey,HMACBuilder))
	Set mybuckets =  myS3.ListAllMyBuckets(mykey,mydate,mysig)

End Sub

You basically send Amazon three things in the web service. Your Access Key, the date, and then a signature which is a HMAC_SHA1 encoded concatenation of “AmazonS3″ + the function you’re running + the date.
I had to tweak Joel Litton’s ISO8601 date a bit to add extra zeros for precision.

The hardest code part was the HMAC_SHA1 encoding. I found HMAC code and I found SHA1 but combining the two seemed to be harder than I thought. Paul Johnston’s Javascript code made the most sense to me so I ported a lot of his code to LotusScript. I used a fair chunk of Julian Robichaux’s SHA1 script also (hence the need to get Julian’s permission to post). I spent a lot of time shifting bits and worrying about signed and unsigned operations.

In the end… Amazon likes my scripts because it actually returns something. I am slightly worried about these Web Services in Domino 8. When my scripts were wrong and a fault was returned. I expected the fault codes to populate correctly in the object and they were not. I’m not sure who’s fault that is. We’ll keep experimenting.

What’s next? I want to use Amazon to store files straight from Domino and I would love to load files (images?) from S3 on the fly.

by tom | Categories: lotus, programming, web design | No Comments

Creating ICS (iCalendar) files can be handy especially in environments where Lotus Notes is not the main email/scheduling system. There are many ways to create the ICS file but it has to maintain this format. Ellie Harmon wrote a sample and description of the format here.


BEGIN:VCALENDAR
PRODID:-//Microsoft Corporation//Outlook 11.0 MIMEDIR//EN
VERSION:2.0
METHOD:REQUEST
BEGIN:VEVENT
ORGANIZER:MAILTO:
DTSTART:
DTEND:
LOCATION:
TRANSP:OPAQUE
SEQUENCE:0
UID:
DTSTAMP:
DESCRIPTION:
SUMMARY:
PRIORITY:5
X-MICROSOFT-CDO-IMPORTANCE:1
CLASS:PUBLIC
BEGIN:VALARM
TRIGGER:-PT15M
ACTION:DISPLAY
DESCRIPTION:Reminder
END:VALARM
END:VEVENT
END:VCALENDAR 

The one trick with Lotus Notes is the date formats. Use this script to format your dates:


Call parentDoc.AppendItemValue( "icsStartDate", Format(item.DateTimeValue.LSGMTTime, "yyyymmdd\Thhmmss\Z")) 

If you don’t need a time, replace “hhmmss” with “000000.”"

In once scenario… I allowed users to download an ICS based on a document they were viewing on the web. If you want to try that… print this code as the first line of your agent:


Print |Content-Type:text/calendar| &Chr(13) & Chr(10)| 
by tom | Categories: lotus, programming, web design | 1 Comment

Christmas came early this year. I just finished a HMAC-SHA1 function for LotusScript. I used a lot of Paul Johnston’s code (translated from Javascript) so I am waiting for his permission to post it.

UPDATE: I finally finished the script library. Here’s a link to the post.

by tom | Categories: lotus, programming, web design | No Comments

Mental Note: YUI

Dec 5, 2007

Mental Note #300053241: Play with the YUI Library.

For those of you that don’t know what YUI is:

The Yahoo User Interface (YUI) Library is a coherent collection of JavaScript and CSS resources that make it easier to build richly interactive applications in web browsers. Some pieces of YUI, like the Event Utility, operate under the hood and are simply there to make in-browser programming easier. Others, like the Calendar Control, comprise visual widgets that can be placed on your page with a default look-and-feel.

by tom | Categories: programming, web design | 1 Comment

Jaime (who blogs at Another Copy Of) posted his atFunctions.js that he uses in his web applications. I’m sure every Notes developer has rewritten this version of @DBLookup in JavaScript but this is the version I use:

BTW, I rely on Jaime’s fullTrim() function but you can substitute any “trim” of your own.

function dbLookupTextList(server, path, view, key, column, category) {
	// server & path optional
	xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
	xmlDoc.async = false;
	if (server != "") {
		server = "http://" + server;
	}
	if (path != "") {
		path = "/" + path + "/";
	} else {
		path = getDBPath() + "/";
	}
	if (category != "") {
		category = "&RestrictToCategory=" + ReplaceSubstring(category, " ", "%20");
	}
	vurl = fullTrim(server) + fullTrim(path) + view + "?readviewentries&count=10000" + fullTrim(category);
	xmlDoc.load(vurl);
	nodes = xmlDoc.documentElement.childNodes;
	var tempArray = new Array;
	for (var i = 0; i < nodes.length; i++) {
		var textListNodes = nodes.item(i).childNodes.item(column).childNodes.item(0).childNodes;
		if (key != "") {
			if(nodes.item(i).childNodes.item(0).text == key) {
				for (var r = 0; r < textListNodes.length ; r++) {
					tempArray.push(textListNodes.item(r).text)
					}
			}
		} else {
			for (var r = 0; r < textListNodes.length ; r++) {
				tempArray.push(textListNodes.item(r).text)
			}
		}
	}
	return(tempArray);
}
by tom | Categories: lotus, programming, web design | No Comments

In order to develop applications that are “Better, Faster, and Cheaper” I am constantly re-organizing my toolbox. Key pieces of code (i.e. email generation, sla calculation, report generation, etc… ) are great for backend processing but sometimes you need quick tools for the UI.

I’m going to talk about one of my most common HTML tables I use in forms. I use this table for almost all of my web forms and people seem to like them. They look good and print really well. For me, creating a new table on the form is as fast as copying and pasting pass-thru HTML and changing a few attributes.

Click on the thumbnail to see the sample table:
Sample Table

The table uses pass-thru HTML instead of the standard Notes table. I mostly use two column tables but it can be customized for whatever purpose.
Click on the thumbnail to see what the table looks like in the form (or subform):

Backend Table

That green box talks about the “magic” that makes the header. Here’s the code in that Computed Value:

class := “inputTable1a”;
id := “tblCustomerInformation”;
HeaderText := “Customer Information”;
defaultExpanded := @True;
view := “$$Keywords”;
returnCol := 3;

key := “Help Text - ” + HeaderText;

helpText := @DbLookup(”" : “”; “”; view; key; returnCol;[FAILSILENT]);

“<table class=\”" + class + “\” id=\”" + id + “\” >” +

“<tr><th>” + headerText + “</th><th style=\”text-align:right\”><img id=\”img_” + id +
“\” class =\”noPrint\” onclick=\”toggleTableVisability(’”+id+”‘,this)\” src=\”" + @If(expanded;dspcollapseIMG_URL;dspexpandIMG_URL) +
“\”/></th></tr>” + @If(helpText !=”";”<tr class=\”trHelpRow\” style=\”\”>
<td colspan=\”2\”>” + helptext +”</td></tr>”;”")

This code sets up the <TABLE>, <TR>, <TH> (header) tags. It also adds an extra row below the table for a “Help Text” line (#2 in the first graphic).

continue reading »

by tom | Categories: lotus, programming, web design | No Comments