Business blogging – an interview with Scott Anderson of HP

At the Blogging BOF at Lotusphere 2005 there was some discussion of blogging as a tool in business. Below is a link to an interview with Scott Anderson, Hewlett Packard’s Director of Enterprise Brand Communication, about blogging at HP:

“The blogosphere is changing how customers gather and consume information about the marketplace. Scott Anderson, Hewlett Packard’s Director of Enterprise Brand Communications took a huge step in bringing his company in line with the principles of open dialogue with its customers through the blogosphere. In this program, Scott describes the experience and the challenges of evolving corporate communication beyond the static web and into the live web.”

Business Blogging, Doing it Right

Show ‘n Tell Thursday: Validating XML when parsing with NotesSAXParser (23 Mar 2006)

When using and parsing XML for any purpose other than purely educational you really want to be using a DTD (Document Type Definition) to make sure the document is “valid” in the eyes of the application. This is possible both when using the DOM and the SAX parser, though there are differences as to when you might discover a violation of the DTD.

Using DOM a violation will be discovered before you actually start walking the DOM tree since the entire document is parsed and validated before control is given back to you as the programmer. Using SAX a violation is not reported until encountered which means that you might have parsed and processed most of the XML document so beware… When using SAX with a DTD you really shouldn’t consider any data from the XML as being valid until the SAX_EndDocument event has been raised (in the case of LotusScript).

To use a DTD with the SAX parser you really only need to be aware of the fact that the path to the DTD should be specified using the file:// protocol as shown in the example XML document below (notice the DTD import in bold):

<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE names SYSTEM "file:///c:/names.dtd">
<names>
  <name>
    <first>Mikkel</first>
    <last>Heisterberg</last>
  </name>
</names>

In this simple example the DTD is very simple and simply states that:

  • there is an element called “names”
  • the “names”-element can have 0 to many children elements called “name”
  • the “name”-element must have two children called “first” and “last” in that order
  • the contents of the “first”-element is parsable character data (#PCDATA)
  • the contents of the “last”-element is parsable character data (#PCDATA)

A caveat that most forget to mention is that the name of the top-level element should be named in the DTD import (<!DOCTYPE names SYSTEM…).

<!ELEMENT names (name*)>
<!ELEMENT name (first,last)>
<!ELEMENT first (#PCDATA)>
<!ELEMENT last (#PCDATA)>

Left is only to tell the NotesSAXParser to validate the parsed XML document against the specified DTD using the InputValidationOption-property (see code in bold).

Sub Initialize
  Dim session As New NotesSession
  Dim stream_xml As NotesStream
  Dim parser As NotesSAXParser

  Set stream_xml = session.CreateStream()
  Call stream_xml.Open("c:names.xml")

  'create validating parser
  Set parser = session.CreateSAXParser(stream_xml)
  parser.InputValidationOption = VALIDATE_ALWAYS

  'declare events
  On Event SAX_StartElement From parser Call SAXStartElement

  'start parsing
  On Error Goto catch
  Call parser.Parse()
  Exit Sub
catch:
  Msgbox parser.Log
  Resume finally
finally:

End Sub

Public Sub SAXStartElement(Source As NotesSAXParser, Byval ElementName As String, Attributes As NotesSAXAttributeList)
   Print "Encountered start of element: " + ElementName
End Sub

The above code can be copied into an agent in Domino Designer if you want to play around with it. To play around with it change the XML (e.g. by adding multiple “name”-elements and having the last one be invalid) to see how the violation isn’t reported until encoutered. Both the XML and the DTD goes in the root of the C-drive as the code is written.

Happy parsing…

Is the lack of Java skills in the Notes/Domino developer community the Achilles’ heel of IBM?

For years IBM has been preaching Java as the next language for development across the IBM suite of products. Still even with the immense focus very few Notes/Domino developers has seemed to lash on to the language. With the introduction of the Hannover client built on top of the Eclipse based Workplace client this will become a real issue in my eyes.

I think that the fenced-in comforts of the Notes/Domino platform have become a sedative for the Notes /Domino developer at large. Too long has the developer community been allowed to seek inwards and focus solely on the proprietary world of LotusScript, @Formula and simple actions to solve the issues at hand. I acknowledge that the @Formula language and simple actions definitely has their place in the Notes product and that these languages really shouldn’t be part of this discussion. My grievances are with the lack of new language adoption and if you live in the IBM World this new language is Java.

(As an aside it now appears JavaScript should also be considered an IBM World language with its introduction as a core language in the Workplace suite of products.)

I guess very few Notes/Domino developers who doesn’t program in Java (regularly or at all) wake up in the mornings and think they are missing out on something and that the consequences of missing out are going to be that big. I’m afraid they really are missing out and that it is going to be a big thing. The problem is however, from the standpoint of IBM, that the developers are not the only ones who are really going to suffer from this lack of Java adoption. IBM is going to suffer as well.

Instead of having a Notes/Domino developer community with a basic understanding of the Java language IBM is left with a community where probably as large portion cannot even write a simple “Hello World” application without the help of a book. In my eyes this is going to be significant since the move to the Hannover client framework will be real big thing for these people due to lack of Java knowledge.

I find this very sad since IBM had the possibility to prevent this from happening. No one could predict the future back in 1999/2000 and knew the direction that the Notes product was taking beyond the 5.x release which was a big thing. No one could predict that IBM would create the Eclipse framework and that most IBM client products would be based upon it.

But here we are, it’s now 2006 and I guess IBM has known for a few years that the Notes client would be built on top of Eclipse at some point in time. I therefore find it sad that IBM hasn’t been more active in driving the adoption of the Java language among Notes/Domino developers during the 6.x releases.

Because IBM is committed to the Notes/Domino product and due to the large population of custom applications out there LotusScript will probably be supported from now to the demise of the platform. Though supported it will be very difficult, if not impossible, to build the kinds of composite, networked applications that will be possible with Hannover using LotusScript. You’ll need Java for these kinds of applications. This brings us back to IBM since this fact will be a real Achilles’ heel when it comes to the adoption and getting the real benefit from the new Hannover client. The success of the Hannover client and the applications possible will rest on getting the customers to use and new features and begin to develop composite applications.

From my point of view I think there are a number of reasons for the lack of adoption. Probably the biggest culprit of the discussion is the perceived simple nature of LotusScript. Leaving Java on version 1.1.8 in the Notes/Domino products throughout the entire Notes 5.x codestream, the lack of proper UI support for Java and the complex and oftentimes impossible to comprehend and poorly documented security managers installed by the Notes/Domino JVM certainly didn’t help matters.

I make a point of saying the perceived simplicity of LotusScript since it isn’t in my mind an easier language to learn. I would even say that due to the lack of documentation and quality education material available for LotusScript, Java would probably be easier to learn than LotusScript for a new Notes/Developer starting of.

I am of the understanding that the difference between Java and LotusScript is just a matter of syntax. Nothing else. There is no need to completely understand the finer points of object oriented design to be proficient in Java. You can write as much procedural code in Java as you can in LotusScript. Of cause you can do considerably more stuff with LotusScript than Java in Notes/Domino but it need not be LotusScript or Java which is often the case in my experience. It has however become the reality that new developers learn LotusScript and not Java.

There is no need to begin to point fingers but I think it is sad that the state of Java development within the Notes/Domino developer community is what it is. The community at large needs to skill-up and get to grips with Java. Now is a good a time as any to get started – rather sooner than later. The reward will be apparent once Hannover is released.

Request for comments

For those of you who get this far – thank you for reading… 🙂 I would really appreciate your view on this. I’ll be happy to hear that I’m wrong but I am afraid that I am not.

How are roaming id-files encrypted?

The customer would like to move the user id-files into the personal name and address book to automatically have the id-files roam with the users. Technote 1102575 (“What information replicates to the roamed Notes Client from the roaming server?”) states the following:

1. User ID
- The user ID is stored (as a file attachment) in the Roaming User's Personal Address Book if the user's organization allows its replication, and if the Domino Administrator selected the option for replicating it. The user ID is doubly encrypted for added security before being attached.

- Because the user ID replicates, the roaming user will no longer need to copy it to different computers when modifying it (for example, by changing the password). However, until replication occurs, a change such as a new password may not take effect immediately. If this happens, try typing the previous user password.

I paid special notice to the sentence:

The user ID is doubly encrypted for added security before being attached.

This sentence raises the question of which keys are used for this encryption? It cannot be the id-file itself since it would render the id-file undecryptable. If cannot be the server id-file since it would make the id-file undecryptable if the user roams to another server. If it is some adhoc keys how does the user know how to decrypt the id-file at the next logon?

Does anyone know?

Looking at the names.nsf using NotesPeak reveals a profile document called “roaminguserid” with a file attachment ($FILE item). The item looks signed but there is distinguishable clear text.

It statement in the technote could of cause be erroneous (it wouldn’t be the first time)… Sounds like IBM Support is about to get a call.

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…