My weekend project this weekend was figuring out how to use the open-source AWStats tool to report against a Domino server. It actually wasn't all that hard, after I worked at it a little bit. For some step-by-step instructions, here's what I came up with:
If nothing else it's pretty easy to set everything up to see what the reports looks like, so you may as well spend a few minutes getting all the pieces together and trying it out on a server. Web server log reports are things that managers and bosses tend to enjoy looking at.
I don't normally post comics on the site, but for some weird reason I keep thinking about that and laughing. Not sure what's so funny about it to me. There's something very Far Side about it...
Here we go again. A similar study was written in 2001, which generated similar reactions. Then there was a second study in late 2002, which met the same type of response (sorry for the archive.org link there... I couldn't get to dreambean.com when I was trying to find that review).
I'm all for watching a J2EE/.NET smackdown, but can we please fight fair? IBM and/or Sun in one corner, Microsoft in the other? I just get tired of these stupid one-sided battles. I mean, you can't really say you've won if the other side wasn't there -- especially if they weren't even invited.
"It has been my observation that most people get ahead during the time that others waste."
- Henry Ford
I love it. That's exactly how I feel about the fact that I write code and read technical information and keep up this silly little blog. Sure, I could be lounging on the sofa eating chips every night, but I do this instead. I'm just trying to get ahead (and besides, I actually enjoy this stuff).
Well, this is because whoever sent you the message has their mail client set up to send messages in Microsoft rich text format, which in turn will bundle the message and all its attachments into a file that's encoded in Transport Neutral Encapsulation Format (TNEF). Unfortunately, while the TNEF format might be "transport neutral", it's far from being "application neutral", and many non-Outlook clients (including Outlook Express) don't really know how to interpret the message. The result is a plain text message that has a .dat file attached to it.
The normal course of action here is to detach the .dat file and find some freeware or shareware utility on the Internet that can do something with it. Being a programmer-type, that didn't sit well with me (all that detaching and extracting and reattaching), so I wanted to automate the process, at least in Notes.
I found help in the Java TNEF library by Amichai Rothman. Somehow, Mr. Rothman discovered the secrets of the TNEF format and wrote an entire Java library to decode those pesky .dat files. Since he made his code/library available as open-source, and since Lotus Notes 6.x has all the required components already built-in, I was able to write an agent that handles all the message extraction for you.
My agent is available for download at: Converting Winmail.dat Files In Your Mail. The agent is meant to be placed in your Notes mail file and set to run against selected documents, so you can just select the messages that you want to convert and run the agent against them. If the conversion was successful, a new copy of the message will be placed in your Inbox folder, with the extracted files attached at the bottom.
I discovered that this is because calling the repeat dates subforms (or, more specifically, using the NotesCSEventOwnerDocument class) worked fine when the calling documents were new, but after they were saved there were three additional things that were required:
PITA. I modified the forms to make sure the EndDate and EndDateTime were properly filled out, and I modified the subforms to temporarily rename the form of the underlying document to "Appointment" while the NotesCSEventOwnerDocument object is being initialized (and then I promptly name it back). Hopefully it's all better now -- please be a dear and download the updated database and test it out for me.
p.s. -- Andrew Barker mentioned that he tried the thing with repeating a reminder every month for 12 months on the 1st starting on January 1, 2004 at midnight, and he didn't get the same missing dates that I did (see the end of yesterday's blog entry to see what I'm talking about). Weird. It's actually happening to me on two different machines.
To see what I'm talking about, just see my latest tip: Setting Up Repeating Dates In Notes. The code and the forms in the database are heavily commented, so I've done everything I can to try to help you out.
the long version of this blog entry
Okay, so someone at work asked me last week if there was a way to add support for repeating calendar entries in the standard Notes TeamRoom template. I had no idea, but I knew that the functionality existed in the standard Notes mail template, so I said I would look to see how difficult it would be to reproduce the mail calendar functionality. I spent about a day on and off trying to understand how the built-in calendar repeating events worked, and finally came back and said that the functionality was probably going to be too complex to add as a "quick fix".
That was pretty much that (because they really didn't want to spend too much time on this), but the problem kept poking at me from the back of my brain. "The functionality is there, I know it is. Why is it so painful to add to my own custom applications?"
Well, since I'm not the kind of person who can just sit back and let that sort of thing go, I spent all weekend hacking away at it. It turns out that there's this magical LotusScript class called NotesCSEventOwnerDocument that creates repeating date lists with a single function call. Unfortunately, trying to figure out how you have to initialize the class in order to successfully make that call is next to impossible, because the class is totally undocumented, and there's not even any good "insider" information on it in the LDD forums.
I say "next to impossible" because I wasn't going to let this thing beat me, and I wasted far more hours than I'll ever admit to in order to figure this thing out. The result is the database you can download at the Setting Up Repeating Dates In Notes tip. The database has an "About This Database" document that's about 2 pages long, with an overview of what the database contains and what you need to know in order to use this repeating date functionality in your own databases. The forms and subforms and agents and script libraries in the database have even more documentation in the inline comments, so be sure to read through that as well.
What a friggin pain in the butt. At least I'll never have to go through all that again, if I ever need the code.
I also found what might be a bug in the native Notes repeat date functionality. Try doing this: open your calendar (the regular one that's hooked in to your mail file), create a reminder for January 1, 2004 at 12:00 AM, and then try to repeat it every month on the 1st for 12 months. Here's the result that I got:
Notice anything strange? I seem to be missing June 1st and November 1st on that list. I'm using Notes 6.51, on Windows XP, in the Eastern Standard Time Zone. I suspect it's a daylight saving time issue, but I really have no idea (since it's impossible to tell what the NotesCSEventOwnerDocument class is doing under the covers).
In the code in my database, I worked around this by setting the time to 12:00 PM, since I didn't really care about the time anyway (just the dates). That seemed to fix the issue, at least in my limited testing.
First, it turns out that Russell Beattie posted exactly this same method for registering jar files almost a year ago. Oh well, I probably should have done a little searching first. If nothing else, just the fact that someone like Russ is also doing and encouraging this sort of thing means that it's probably a good idea.
That is a good point, that you shouldn't go around breaking functionality, so I just wanted to mention that to you so you know what you're getting into. In my case, I will gladly trade the executable functionality for viewing the file contents, because that's exactly what I want to do at least 90% of the time that I'm staring at a jar file. Here are some of the things I have to deal with that make it useful for me to look inside a jar:
This last one happened to me just this past week, and having my jars registered as native zip files helped me immensely. I downloaded and was playing with the IBM WebSphere SDK for Web Services (WSDK), and I successfully built an interface to a web service but I wanted to run it outside of the WebSphere environment. I was having problems because there were a few classes that I needed to reference, but I had no idea which jars to include. Unfortunately, the appserver\lib directory of the wsdk (which is where all the important jars are) has 160 jar files. How the heck am I supposed to know which one to use? Luckily, having my jars registered as zips allowed me to do a simple Windows search within all the jars in that directory and find out where my classes were, in about 20 seconds.
So, just like everything, it depends on how you work. If you never have a reason to look inside a jar file, leave 'em alone. If you're a developer who needs to look at jars on a regular basis, go for it. And even after you've registered a jar like I described, you should still be able to right-click it and choose "Open With > javaw" to run it like you used to (if the need comes about). That functionality is controlled by this registry setting:
which should have been created when you loaded java onto your machine in the first place -- the "jarfile" file type will run "javaw -jar %1", which is what is "supposed" to happen when you double-click a jar.
As a final note, if you ran my registry modification and you decide that you really want the old/default double-click functionality back, just delete or rename your new HKEY_CLASSES_ROOT\.jar registry key, and enter this information instead:
That's what the key should have looked like before you messed with it.
Yeah, I realize that Windows and Sun were having huge battles over Java up until recently, but really a .jar file is just a .zip file with a different extension. You can open zip files natively in Win 2K/XP, why not jars too? Sure, you can rename your .jar files to .zip and then open them that way, but who wants to go around renaming files all day, just to take a peek?
So I did a little poking around, and figured out how to register jars so Windows treats them just like zips. What's really nice about this, besides the fact that you can now double-click a jar and look at it as though it were a folder, is that after the files are registered this way you can search within them as you perform normal file system searches for file names. That becomes unbelievably handy if you've got a directory full of jars and you're trying to figure out which one to include in order to use a particular class file.
Here's the tip: Open JAR Files Natively In Windows.
Oh, and while you're doing that, you might want to tweak the .reg file a little so you can open .ear and .war files the same way. Those are just zip files in disguise too.
(P.S. -- yes, I know that WinZip and other similar tools would have opened my jar files for me as well, but that whole searching-an-archive-file-like-it's-a-folder thing is real nice.)
So we grabbed a loaf of bread and a pack of tortillas out of the fridge and took a look at the packages. Sure enough, each slice of bread had 1 gram of fat, and each tortilla wrap had 5 grams. Huh. Whaddya know?
In a weird sort of way, that actually made the tortilla wrap I ate tonight taste a little better. Mmm, fat grams...
var startDateField = document.getElementsByName("StartDate").item(0);
var dateObj = startDateField.value;
dateObj.setTime(dateObj.getTime() + (21 * 24 * 60 * 60 * 1000));
var endDateField = document.getElementsByName("EndDate").item(0);
endDateField.value = dateObj.getMonth() + "/" + dateObj.getDate() + "/" + dateObj.getFullYear();
I don't have the real code in front of me, but that's the gist. Simple enough, right? Grab the value of the start date, increment it by 21 days (in milliseconds), and set the end date to the incremented value.
But today, it started incrementing the end date by 20 days, not 21 days. Huh? How did that happen? The code didn't change.
Well, October is the magical month where daylight saving time ends around here and we "fall back" an hour on the last Sunday of the month. Which means that if I increment today's date by exactly (21 * 24 * 60 * 60 * 1000) milliseconds, I don't advance the date by 21 days, I advance it by 20 days and 23 hours. So the code above breaks very slightly for most of October.
Stupid daylight saving time...always making me look bad.
It's a good, basic, step-by-step outline of how to install WebSphere Portal on Windows 2000, specifically on a VMWare virtual machine. A couple things I would add, though:
Also, if you want a little more detail about the install process, along with some good instructions about basic Portal-to-Notes connectivity, don't forget to download the install guide on Joel Demay's site.
And I'm not going to talk about who I think is broken in this case, Microsoft or Mozilla...
For example, I went to the grocery store a few minutes ago to pick up some staple items (sandwich meat, half a pound cake, and beer), and one of the things I came back with was a six-pack of Bootie Beer. It's probably going to taste terrible, but I love it for its name, and I love it for quotes like this:
The beer's marketing plan is structured around the slang word, "booty."
"To one person, it means having sex," says Bootie President Tania Torruella. "To another, it means going to the club and getting loose. To a third, it's having a sophisticated dinner with dad."
To me that's just entertaining, and I want to encourage that sort of entertainment, so I will buy that product (probably not more than once, but I'll donate a little to the cause anyway).
Of course, beer is a market where you can take that sort of unconventional approach to your product name. I've heard some pretty amusing stories about names gone bad, especially when they're translated into other languages. For example, the dairy association's "Got Milk" campaign here in the USA had a little setback in Latin countries when the slogan ended up translating into "Are You Lactating". The old Chevy Novas had to be renamed in Mexico because "no va" literally means "won't go".
One example of a questionable name came up today when I saw that Eric Thauvin used a company called GoDaddy to renew his SSL certificate. I wondered why he would have gone out of his way to mention that, and when I went to the site I saw that you can get a medium assurance SSL cert for $30 per year, and a high assurance one for $90 per year. That is so much cheaper than a Verisign or a Thawte certificate, it's not even in the same ballpark.
My first thought was that it must be an "untrusted" certificate, where the user will get prompted to accept or reject it when they hit your secure page, but according to their FAQ, the root certificate is installed by default on IE 5.01 or higher, all versions of Mozilla and Thunderbird, and essentially every other major browser out there. Man, what a bargain.
So then the problem becomes, how do you sell this to your bosses? If you're in a corporate culture, it can actually be a tough sell to convince your management to switch from an "established" and conservative name like Verisign or Thawte to some hairbrained company called GoDaddy. Sure, you save all kinds of money, but there's certainly some psychology going on there.
The good thing is, I think if one of your senior executives happens to access your GoDaddy-secured intranet with IE 3.02 on his Windows 95 machine at home, he'll at least get prompted with a question about trusting a "Valicert" authority, which sounds much better than "Certificate issued by GoDaddy. Hey cool cat, are you sure you want to proceed?"
We're definitely going to try it out on one of our servers and see how it works. I just wish the name was a little more...corporate. Then it would be a slam dunk.
The downside to this (other than the obvious risk of getting a bad cut) is that every once in a while someone at one of these places starts recognizing me from the last time they cut my hair, and then they "claim" me and I always have to wait for them instead of just taking the first empty chair. At this point, I usually start going somewhere else for 6 months or so, which is about the lifespan of hair technicians at a place like that. The upside is that if I can avoid the situation above and get a different person to cut my hair each time, I sometimes get some interesting people to talk to.
The lady who cut my hair today was really nice, and it turns out she has young twins so we talked about kids for a while. After she was done cutting my hair, she asked if I wanted a shampoo and I declined. Then she asked if I wanted her to trim my eyebrows.
I've never got that question before. I'm sure I had quite the strange expression on my face as I started to answer, "No thanks". And she said, "Are you sure? You've got a couple of really long ones there."
Now I'll admit, one very unexpected thing that's happened to me as I've gotten older is that I've managed to grow a couple of "rogue" eyebrow hairs. Normally your eyebrows, eyelashes, arm hairs, etc. grow to a certain pre-determined length and then stop growing. For some reason, a couple of years ago I noticed that one of the hairs on one of my eyebrows decided to ignore nature and just keep on keeping on. By the time I caught wind of this scheme, the hair in question was almost the length of the brow itself, although it was hiding quite cleverly within the other hairs, all tucked away and weaved in there. A few times I tried trimming it, but it would always grow back. Eventually I started plucking it out, at which point another hair temporarily took its place, and then the original hair grew back, and then I had two mutant eyebrow hairs to deal with.
So anyway, I generally try to keep this whole eyebrow situation in check, but this time I got busted by haircut lady. I told her I would take care of it when I got home, but she kept asking. Maybe she just got a new eyebrow trimmer that she wanted to try out, I don't know. She told me it would just take a second, and I really should get my eyebrows trimmed every time I got a haircut.
And that, of course, is part of the problem. There are three scenarios that could happen here:
1. The eyebrow trim looks terrible, and I'm forced to take a few days off work so I don't have to be seen in public.
2. The eyebrow trim looks great, and now I have to ask for one whenever I go to whatever random barber I go to, and that just seems like a weird thing to ask for.
3. The eyebrow trim causes all of my eyebrow hairs to wake from their slumber and start growing out of control, turning me into a shaggy browed freak.
None of these situations seemed very desireable, so I kept declining the offer until I was permitted to leave. Who knows how much of an issue this is going to become as I continue to age in strange and wonderful ways. I guess my ear hair is next.