JSR-170

I hadn’t heard about JSR-170 before so I did a search on Google and found a presentation on JSR-170 from JavaPolis 2004. The presentation gives an overview of the specification and what it is for.

Looking at the concept of a content repository that JSR-170 introduces, the Domino/DB2 integration again makes a lot of sense. Could this be the promise of one single, all-knowing, all-encompasing content storage facility?

Given that the specification might have changed since you should search for updated information if you need exact information about the specification.

Helping out a fellow blogger getting the actual bytes of an image resource – a lesson in the intricacies of DXL representation

This is a rather lengthy Friday post for those of you who have tried being haunted by a programming problem you simply couldn’t let go. I guess those of you into Java and Notes development will probably appreciate it as well… 🙂

It all started Thursday night when I read a post called I need some help, PLEASE over at Jamie Prices blog. Jamie needed some help to extract the bytes from an image resource in a Notes database using Java. Being the nice guy I am, the fact that it sounded pretty nerdy (direct hit again) and because I didn’t think it would be that difficult I started messing around with it.

Easy? Well no, but I cracked it!

Thursday

I immediately thought “DXL” and started up Eclipse. I guessed that the image resource would probably be base64 encoded and thought it a small matter to solve Jamies problem. I imagined 3 easy steps:

  • Get the DXL for the image resource,
  • Extract the base64 encoded image resource,
  • Decode the base64 string to a byte array

and I would be laughing… Well not so easy.

I pretty quickly got at the base64 encoded image resource but whatever I did I couldn’t get the image properly converted. I thought this was simply my tired fingers so I posted my idea and some code in a comment on Jamies blog and went to bed.

As I read your post you need some way to get a byte array of an image resource in the current database - right? You could use DXL to get at the base64 encoded image and then decode it into a byte array (here I find an image resource called "location.gif"):

Database db = ac.getCurrentDatabase();
NoteCollection nc = db.createNoteCollection(false);
nc.setSelectImageResources(true);
nc.buildCollection();
String noteid = nc.getFirstNoteID();
String noteid2 = null;
while (noteid.length() > 0) {
  noteid2 = nc.getNextNoteID(noteid);
  Document doc = db.getDocumentByID(noteid);
  if (!doc.getItemValue("$TITLE").elementAt(0).equals("location.gif")) {
    nc.remove(doc);
  }
  noteid = noteid2;
}

DxlExporter exporter = session.createDxlExporter();
exporter.setForceNoteFormat(true);
String dxl = exporter.exportDxl(nc);

If you look at the generated DXL a base64 encoded image will appear there. I didn't go further since I wanted to make sure that this is actually what you want to achieve.

<snip total_wrong="true">
I did however find out that I was unable to export design elements to DXL using Java from a local database under Notes 7.0.1 - I had to do it on a server...
</snip>

/lekkim

Friday

Today, Friday, I received an e-mail from Jamie thanking me for looking into the issue. In hindsight I know he just smelled the blood… At that point however the e-mail just reminded me that I hadn’t solved the problem which really bothered me. I did some research and found some evidence that something might be up with the base64 encoded image resource. A post I found on LDD pointed towards the fact that the base64 might contain some header and/or control information as well. Venturing further down this avenue and by comparing the bytes of a decoded image resource with the bytes of the same image not as an image resource revealed the secret.

The structure of an image resource

It turns out that an image resource has 66 bytes of header information followed by 10240 bytes of image data, 10 bytes of “control information”, 10240 bytes of image data, 10 bytes of “control information” and so on… I felt I was on to something.

I extracted the base64 encoded image resource from the DXL using cut-and-paste and wrote some code to process the image resource bytes as per the above pattern an voilá! One perfect, viewable, valid image on my harddrive.


public byte[] getImageBytes() throws NotesException {
   // get base64 encoded image
   String base64 = this.getBase64();

   // convert the base64 to byte array
   // using the Base64 encoder/decorder by
   // Robert Harder from http://iharder.net/base64
   byte[] b_source = Base64.decode(base64);

   // remove header and control information
   ArrayList list = new ArrayList();
   int j=0;
   int k=0;
   int i=0;
   for (i=0; i<b_source.length; i++) {
      if (i<66) {
         // ignore (some kind of header)
      } else if (j < 10240) {
         list.add(new Byte(b_source[i]));
         j++;
      } else if (k<9){
         k++;
      } else {
         j=0;
         k=0;
      }
   }

   byte[] result = new byte[list.size()];
   i=0;
   for (Iterator ite=list.iterator(); ite.hasNext(); i++) {
      result[i] = ((Byte)ite.next()).byteValue();
   }

   // return result
   return result;
}

This was all well and good. The extracted bytes was easily written to disk using a java.io.FileOutputStream:

// write to a file on the file system
FileOutputStream out = new FileOutputStream("c:\image_resource.gif");
out.write(my_acquired_image_bytes);

out.flush();
out.close();

Get at the base64 data from Java

Now came the time to get at the base64 data of any image resource. I chose to use a regular expression for the job.

A thing to bear in mind is that the base64 data of an image resource in DXL is sometimes split over two “rawdataitems”. This seems to be filesize related since an image resource of 17 kb is in one item and one of 35 kb is in two items (probably our dear 32kb limit)

public String getBase64() throws NotesException {
   // build a note collection of image resources
   NoteCollection nc = this.pDb.createNoteCollection(false);
   nc.setSelectImageResources(true);
   nc.buildCollection();
   String noteid = nc.getFirstNoteID();
   String noteid2 = null;
   while (noteid.length() > 0) {
      noteid2 = nc.getNextNoteID(noteid);
      Document doc = this.pDb.getDocumentByID(noteid);
      if (!doc.getItemValue("$TITLE").elementAt(0).equals(this.pName)) {
         // not the one we are looking for
         nc.remove(doc);
      }

      noteid = noteid2;
   }

   // make sure we have at least one image resource
   if (nc.getCount() != 1) {
      throw new RuntimeException("Unable to find the requested image resource");
   }

   // export our collection if the found image resource as DXL
   DxlExporter exporter = this.pSession.createDxlExporter();
   exporter.setForceNoteFormat(true);
   String dxl = exporter.exportDxl(nc);

   // use regexp to get the base64 encoded image resource
   Pattern p = Pattern.compile("<rawitemdata type='1'>([a-zA-Z0-9/=+\s]*)</rawitemdata>");
   Matcher m = p.matcher(dxl);
   StringBuffer buf = new StringBuffer();
   while (m.find()) {
      buf.append(m.group(1));
   }

   // return
   return buf.toString();
}

Please note: Since I used the java.util.regex package it means that the code requires Notes 7.x to run since the package was added in Java 1.4.x. It should however be fairly easy to get the base64 using string operations as well if you’re pre-Notes 7.

Conclusion

Well it turned out not to be as easy as first expected but at least I have peace of mind now that I cracked it. I sent the code to Jamie and he’s trying it out as well so we’ll see how it goes. For those who are interested to see the complete code I have put together an example database available for download.

I hope Jamie can use the code. Happy Friday!

Jack Dausman: The move to the Eclipse platform a bad thing for the Notes client?

Well this is refreshing – Jack Dausman posts about the possible downside to the change of the Notes UI from the home grown UI framework to the Eclipse platform. While he’s worried about the developers and administrators his post got me thinking and I do not think the shift to going to be such a big deal for them. In my view the main impact is going to be on the end-users since they’re the ones actually seeing the new client. The Domino Designer and Domino Administrator is not going to change in the same timeframe – at least that’s what I gather from Ed Brill in the recent Taking Notes podcast.

My view is that the impact on developers and administrators by the move to the Eclipse platform with the Hannover client is going to come from having to develop and manage these new composite, cross-cutting, applications possible with the Hannover client. This is going to make Single-Sign-On and common and managable backends increasingly important. Off cause new development tools and strategies are going to emerge but my guess is that the majority of Notes developers and administrators wont see the big difference for quite a long time.

Compacting from the Notes client

Honestly – who knew that the compact you do via the “Database preference” dialog from the Notes client doesn’t change or upgrade the ODS (On Disk Structure)? (e.g. from ODS41 to ODS43)

Not a big thing – I just never thought about it.

Show ‘n Tell Thursday: Loving DNS blacklists (16 Mar 2006)

Before I continue however, let me tell you that the real definitive voice on SPAM prevention in Domino is really Chris Linfoot whose site contains a wealth of information on how to prevent SPAM in Domino. Julian and Bruce did two “Taking Notes” podcasts with Chris on SPAM that you might want to check out as well.

Anyways – for most companies SPAM is a really big issue and something that turn the hair of the IT department gray. I have heard estimates to the fact that 66-75% of the e-mail traffic on the web is generated by spammers. Something to be quite concerned about.

As an enterprise there are a couple of measures you can take to protect yourself from receiving massive amounts of SPAM:

  • Route your e-mail through a third-party that handles the SPAM control for you.
  • Purchase a hardware device such as a Baracuda.
  • Run an internal SPAM prevention server such as TrendMicro or another SMTP host with some kind of baysian filtering.
  • Use DNS blacklists.

In addition to the above a new approach called “graylisting” is starting to gain acceptance. In my mind graylisting sounds very promising for the time being but isn’t yet supported by Domino though.

Common for all the above solutions are that they are either quite expensive or time consuming to setup and configure. While all of the above solutions work you can get a lot of bang for your buck using a free approach called DNS blacklisting. While the concept of blacklisting is probably well known to most, the concept of DSN blacklisting may not be. Using DNS blacklist(s) the Domino server will query the blacklist(s) for the IP address of the sending SMTP server on each transaction. If the IP address of the sending server is found in a configured blacklist the server can log the occurance or simply refuse to accept the e-mail.

Configuring DNS blacklists in Domino is easy. Simply edit the configuration document for your incoming SMTP server and go to the “Router/SMTP” –> “Restrictions and Controls…” –> “SMTP Inbound Controls” tab. Toggle the “DNS Blacklist filters” to enabled and add a couple of blacklist servers and select the appropriate action to perform when a sending server is found in the blacklist. Please not that all servers are queried – not just until a match is found so you really shouldn’t just add all the DNS blacklists in the World…

There are numerous lists of there on the web with varying quality and different levels of strictness. We normally use the below list for customer installations without any issues (again Chris Linfoot has more on the different lists):

Apart from the above lists you might want to utilize some lists that deny e-mail from know spammer nations if you do not normally receive e-mails from those countries. At the office we deny e-mails from Taiwan, China and Russia:

  • ch.countries.nerd.dk
  • ru.countries.nerd.dk
  • tw.countries.nerd.dk

A complete list of country lists and information on how to use these lists are available at countries.nerd.dk.

If you are running Domino 7 you also really should instruct the Domino server to only accept e-mails to the recipients that exists in the Domino Directory. This is done on the same tab as above in the “Inbound Intended Recipients Controls” section:

To see how many connections are rejected using the blacklists you can use a Domino server command at the console:

sh stat smtp

This will produce output like the below:

  SMTP.Command.DATA = 1357
  SMTP.Command.EHLO = 33
  SMTP.Command.HELO = 5548
  SMTP.Command.Invalid = 3955
  SMTP.Command.MAIL = 5693
  SMTP.Command.NOOP = 3
  SMTP.Command.QUIT = 1603
  SMTP.Command.RCPT = 2065
  SMTP.Command.RSET = 155
  SMTP.DNSBL.bl.spamcop.net.Hits = 1115
  SMTP.DNSBL.ch.countries.nerd.dk.Hits = 1
  SMTP.DNSBL.dnsbl.sorbs.net.Hits = 2532
  SMTP.DNSBL.list.dsbl.org.Hits = 163
  SMTP.DNSBL.ru.countries.nerd.dk.Hits = 5
  SMTP.DNSBL.TotalHits = 3867
  SMTP.DNSBL.tw.countries.nerd.dk.Hits = 51
  ...
  ...

Above you can see some SMTP statistics from a server at my office. You can see a line each of the blacklists we employ starting with “SMTP.DNSBL” telling you how many hits each list have had. Please note that the statistic for a blacklist is not visible until the blacklist have had at least one hit. As you can see we deny quite a lot of SPAM just using this simple approach.

Happy blacklisting…

Domino 7 too complex for IBM to support on Linux?

While perusing the supported Linux distributions for Domino 7.0.1 I found the number to be in stark contrast to the number of distributions supported for DB2 UDB. According to the technote Domino 7.0.1 is only supported on 3 distributions while DB2 UDB is supported on 15 distributions! (To be fair DB2 UDB is only “recommended and validated” on 5 of the 15 distributions but still…)

Why the difference?

From the perspective of smaller installations the support of DB2 UDB on Ubuntu 5.04 is very nice since it together with DB2 UDB Express provides a almost no-cost entry into the world of DB2.

Domino 7 Redpapers available

2 new Domino 7 Redpapers that might be of interest to those not yet having made the move is now available from the IBM Redbooks website:

The first one is showing concrete examples of how the ITSO application was enhanced using the Domino/DB2 integration and webservices. The latter has a section for those still on Domino 5 who are looking into going directly to Domino 7.

Re: CD to MIME Conversion Error: “CVS: Failure”

Problem solved – sort of… Downgrading the server from Domino 7.0.1 to Domino 7.0 has solved the issue we were having with CD to MIME conversion.

Now I have to decide whether to report this to Lotus Support. The problem is that the server is a production server and the customer can’t really afford us playing around with the server.

CD to MIME Conversion Error: “CVS: Failure”

After upgrading a customer server from 6.5.4 to 7.0.1 I am having major issues with CD to MIME conversion in e-mails sent via LotusScript (normal e-mail sending is OK):

14-03-2006 13:44:55   Begin CD to MIME Conversion(Process: Router (000008CC:0000000D), Database: E:DominoDatamail.box, Note: 00305AEE)
14-03-2006 13:44:55   CD to MIME error (Process: Router (000008CC:0000000D), Database: E:DominoDatamail.box, Note: 00305AEE): CVS: Failure
14-03-2006 13:44:55   End CD to MIME Conversion(Process: Router (000008CC:0000000D), Database: E:DominoDatamail.box, Note: 00305AEE)
14-03-2006 13:44:55   Router: No messages transferred to 192.2.4.9 (host 192.2.4.9) via SMTP

I tried enabling debugging for the conversion process using some notes.ini settings (CONVERTER_LOG_LEVEL=40, DebugMIMEConversion=1) but they doesn’t provide anything useful.

Anyone with ideas? I’m currently downloading Domino 7.0 to see if downgrading will help.