Woohoo! My first Nigerian scam!

I started Web programming seven years ago. I’ve posted my e-mail address on Web pages. I’ve posted on the newsgroups. I’ve given my e-mail address to sites that don’t really need my e-mail address, and that turn around and sell it. The throwaway e-mail address I reserved for such sites has gradually become an e-mail address that I use regularly for sites I trust, too, so I can’t just ignore it.

So, of course, I get spam. I get spam about breast implants and discount Viagra (the spammers are apparently very confused as to my gender). Heck, I used to get loads of spam about septic tank repair. (This was all the more amusing because I was living in an apartment at the time.) I still get spam about real estate in Marion, Iowa, where I haven’t lived for three years.

Can you believe that today was the first time I got a Nigerian scam e-mail?

Reprinted below for your amusement. (I did fix the line breaks so it was more-or-less readable.)

Mrs. Julia Moyo
34 Gallo Court, 3 Avenue, Florida 1710
Johannesburg South Africa
E-mail: moyojulia@tiscali.co.uk


Dear Sir,

I am Mrs. Julia Moyo a Zimbabwean and the wife of Mr. Edward Moyo a renowned Farmer in Bulawayo Town in The Peoples Republic of Zimbabwe (Southern Africa).

I write to you on behalf of the Moyo`s family, to request if you are available and have the facility to assist my family undertake some capital investment in your country. It will be necessary to inform you that the {US$25.5M} Twenty five million five Hundred Thousand United States Dollars) intended for capitalization of the investments are presently in the custody of a private security company here in Johannesburg, South Africa which we enquire to transfer out of South Africa immediately for the said investment purposes.

You may have heard of the present crisis in Zimbabwe caused by Land use act of the government of Robert Mugabe in which his government has arbitrarily reclaimed and acquired all farm lands owned by the white farmers in the country. This has caused a historical displacement of the white folks who are known to be the country’s main farmers, and also killing and imprisonment of thousands of these white farm owners by the ruthless government forces. My husband in his good joined the international community in condemning and speaking out against this uncivilized and bizarre policy of the government.

As a result of this matter, a group of assailants suspected to be government forces attacked and killed my Husband in cold blood in our farm last year. Seeing that the entire moyos family was in threat of extinction, I immediately fled Zimbabwe to South Africa with my son and daughter, where we have been since then as refugee under the United Nation camps. Prior however, to my husband?s untimely death he had sold some of his farm lands including those of some of his white farmer associates who had transferred ownership of their farm lands to my husband to forestall the government acquiring them.

He secretly sent the proceeds {US$25.5M} Twenty five million five Hundred Thousand United States Dollars) to South Africa. And deposited it in a metal box with a private security company here in Johannesburg.

I now contact you for immediate assistance in lifting the funds out of South Africa for investments in your country. Every needful arrangement through which the transfer will be affected to your account has been made. And for helping us actualize this matter, we have agreed to offer you 25% of the total money, 5% will be mapped out for the expenses we may incur during this transaction then 70% will be for my family. Considering the nature of this matter, we require that it be handled most discreetly.

Kindly contact me or my son “JOSEPH” using the above email address, or by telephone on +27- 83-372-5196.upon receipt of this letter for Execution details and other necessary discussion. In anticipation of your trusted and genuine assistance

I remain,
yours sincerely
Mrs. JULIA MOYO (for the family).

Get Tiscali Broadband From £15:99

Source control and Vault diff

Our entire dev team is soon to embark on a project that will become pretty much all-consuming for the next several months, and we’ve been talking about source control. We’ve been using VSS for a long time, mainly because we already have it. But when you lose an entire day of productivity across the entire dev team, because VSS can’t do the branch on account of a corrupted data store that takes more than eight hours to repair, it’s time to look around.

We’re pretty much in agreement about the qualifications of our dream source-control system. The #1 feature we want is the ability to check something in, but not have that change hit the official build until it’s been code reviewed and system tested.

Borland StarTeam has that capability (though it remains to be seen just how much we have to pay to get that feature). It’s got a built-in bug database, too, and it should be able to automatically tie individual check-ins to individual bugs/enhancements (which is a dream feature of mine). We’re investigating a couple of other high-end source-control systems as well, but I’ll have a good chance to get up close and personal with them at BorCon — I’m taking a preconference tutorial on how to write tools that integrate with StarTeam (#2010, Sunday afternoon).

Microsoft’s Team System might hold some promise, if they’d just get off their asses and start talking about pricing. They refuse to even hint at what the bundling and pricing are going to be. It could be $50 a developer, it could be $50,000, it could be free. And, of course, it won’t be released until sometime (probable translation: December) next year.

Also on our radar is SourceGear Vault, which is much more reasonably priced (around $200 per developer, instead of “it’s too expensive for us to print the price on our Web site” for the top-end version of StarTeam). Vault has some of our “nice to have” features, like atomic check-in. It doesn’t have the “must be code reviewed before it can be part of the build” dream feature (not surprising given its price range). But one thing it does have is a positively dreamy diff tool. Here are a couple of screenshots:

It can do diffs within a line. This is a feature I’ve wished for in VSS for I don’t know how long. (Let’s see, how long have I been using VSS…?) Any time I rename a variable, all VSS cares to tell me is that more than half the lines in my method have changed. Vault’s diff will actually tell me that it’s just the variable name that’s changed. Sweet!

This one really got me. Vault can diff across line breaks. Is that cool, or what? (This is especially nice since we changed our coding standards, oh, about three years ago, to say that the “begin” of a Delphi begin..end block should now be on its own line, not the end of the line with the ‘for’ or ‘if’ or ‘while’. And of course, not all of the code has been brought up to standard yet. VSS would just show us gray lines whenever we fixed one of these, and if the condition changed too, we might miss it. Vault can show us that the only thing that changed was a line break.)

Vault is meant to be a drop-in replacement for VSS, which means it’s got VSS’s design limitations — for example, if you’re going to branch off the release version, you have to create a new folder for it (my understanding is that StarTeam, and some others, let you maintain multiple branches within the same folder tree). However, this closeness of design does mean that, if we’re going to change source-control systems before our Big Project, Vault is really the only contender; we don’t have time right now for the steeper learning curve for something like StarTeam. But after the Big Project, we may be ready to switch to something high-end (budget permitting), so it wasn’t clear whether it’s worth it to shell out money for Vault now, only to possibly spend more later.

But I think Vault’s diff makes that decision a lot easier…

(A warning, though: Don’t do a diff on two multi-megabyte PDF files. It’s not so good at noticing that these are binary files. It works, more or less, but it takes a while.)

Avalon Ho

Microsoft is going to strip some features out of Longhorn, the next version of Windows, so that they can release it as early as 2006 (instead of, last I heard, 2007 or later, except in the extremely unlikely event of further schedule slips).

Interestingly, as part of this announcement, they also did a 180° on their former stand on Avalon, the Longhorn UI library. Avalon will have lots of cool new features like a new document model, full flow layout, and transparent declarative data binding, just to name a few of the more interesting ones off the top of my head. Microsoft has been adamant, up to this point, in saying that Avalon would only be available with Longhorn, that they would not make Avalon available on earlier OSes.

That had made Avalon a real yawner around here, since we knew that our client base wouldn’t even start buying Longhorn until at least a good two or three years after it was released, and there was no way we could start writing Avalon-only software until two or three years after that, when it started to become reasonably prevalent among our clients.

Well, guess what? Now they’re going to backport Avalon to earlier OSes. A quote from the article:

By making Avalon and Indigo work on older machines, Microsoft hopes more developers will want to write software that takes advantage of the new technologies. Had they been Longhorn-only features, the concern is that developers would have held off writing software until there was a critical mass of machines running that operating system.

Um. Duh.

It wouldn’t have been all bad, because MS was intending to take their time and do it right. (“Microsoft’s top executives had characterized Longhorn as a major overhaul of the operating system and stressed that its release would not be determined by trying to hit a specific ship date.”) Which would have been a fabulous deal for the engineers actually writing Longhorn. How often do you get that kind of project? Throw in all the bells and whistles you like, make a product that’s as mind-blowingly cool and drop-dead sexy as you can imagine, and never worry about deadlines. Sounds like every programmer’s dream job.

Not much of a dream for the rest of us, though, and it looks like they’ve finally figured that out. Hooray! Only twenty-eight more months until Longhorn! (No estimate given on how much longer after that until Avalon is backported to Windows XP.)

Tree “Encryption”

In his July 2004 Crypto-Gram newsletter, Bruce Schneier mentioned an “encryption” program he had run across. The program is called Tree and is made by a company called ICS Atlanta.

The title of Schneier’s write-up about this algorithm is titled “The Doghouse: ICS“. Here’s a brief excerpt:

How is Tree different? Well, for one thing, it “uses no math.” I’m not quite sure how that’s possible on a computer, but that’s what Tree’s creator claims. From an e-mail exchange: “…99.99% of the people out there use math to encode and they use math to ‘break’ the code. Since we don’t really use math, it would be quite hard to break.”

Not only do they not use math, they don’t have a key. “Tree does not use a ‘key’…. I just put in text, hit ‘encode’ and poof, there is the encoded message, to decode, I put in coded messages, hit ‘decode’ and poof, done. That’s it. No key.”

Poof. I like that. Poof.

I can just see it. A saboteur just stole your top-secret formula for cold fusion, the formula that’s going to make conventional power obsolete and make you a multi-trillionaire overnight. But you’re resting easy, because you know that the file is securely encrypted with Tree. They’ll never break the code. They’ll never beat you to market, or even to the patent office.

And then you get a phone call. And a voice says, “Poof. Neener neener neener.” Click.

But wait! There’s more!

Now, I haven’t actually seen the company’s Web site yet, because “The website you have requested has exceeded its daily bandwidth quota of 56MB and has been temporarily de-activated … [W]e encourage you to upgrade to one of our PREMIUM hosting plans starting at only $4.95/month.” (Now, that’s what I call a professional Web presence.)

But Schneier’s August Crypto-Gram newsletter includes reader comments from someone who did see their Web site, and elaborated a bit more. (Go to the Comments from Readers in that issue, and scroll down a couple pages. The comments in question are second to last, from Owen Yamauchi.) Again, I encourage you to read it for yourself, but a few more choice quotes:

– “Tree is a file encryption/decryption program designed to foil all current methods of ‘snooping’ of private data by the very means of how Tree encodes data.” Yup. They do it with a secret algorithm, and most current methods of cryptanalyzing ciphertext involve knowledge of the algorithm. You can’t even use brute force, since Tree doesn’t have a key to brute-force! Wow!

– “Do Any Governmental Agencies Have This Program? As Of 5/2004, The Answer Is No.” You’d think government agencies would recognize the value of the world’s safest encryption, wouldn’t you? Silly them.

Immediately following that — this is the best part of all — is another reader comment: a rebuttal from the owner of ICS Atlanta, which I will not even attempt to describe and do not hope to understand. I only know that it’s among the funniest things I’ve read in my life.

Visual Studio strangeness

Just goes to show that Delphi 8 isn’t the only IDE that does incomprehensible things now and then.

I just got our latest code from VSS and tried to compile our solution in Visual Studio. I got an error list a mile long, because, of course, VS isn’t bright enough to, oh, stop compiling when it gets a compiler error. No, it just goes right on its merry little way, compiling the rest of the solution without a care in the world. And since one of the projects failed to compile, the old version of its assembly is still lying around, so it compiles all the other projects in the solution against the old version of that assembly — but against the newer version of any other assemblies that did compile successfully. So, of course, the errors snowball, because the versions expect different properties, different method signatures, etc. And then, to top it all off, it shows the errors in some sort of wacky reverse-chronological-yet-not-quite-reverse-chronological order, so that the errors you need to see are very nearly at the bottom of the list (about 5 or 10 lines up, usually, though sometimes more), and the chain-reaction errors (from linking against the old version of an assembly that didn’t compile) are at the top. So helpful. So very, very helpful it is indeed. One can only hope that Whidbey and MSBuild will be a little more intelligent about the whole thing. Here’s hoping fervently.

But I digress.

Anyway, it turns out that the first-generation errors were on a class we had descended from the Xceed Grid‘s Cell class. The compiler was saying things like “GridControl doesn’t have a property of type GridControl”.

Mind you, nothing (relevant) had changed. I looked through the diffs to make sure. The project file hasn’t changed in weeks. The source file it was complaining about hasn’t changed in weeks. It just… wouldn’t compile.

Eventually I puzzled out the reason. Visual Studio had arbitrarily, capriciously, and with malice aforethought decided to load the wrong version of the Xceed Grid assembly. (Not any of the other Xceed assemblies. Not even the other Xceed assemblies that themselves reference the newer grid assembly.) It just up and loaded version 1.1 of Xceed.Grid.dll instead of version 2.1. It even had the gall to pretend it was supposed to do this — when I clicked on the project’s Xceed.Grid.dll reference in Solution Explorer, it merrily told me the path it had loaded from, and the version it had loaded. Meanwhile, the project file explicitly lists the exact version that it’s supposed to load (and it ain’t 1.1), and even specifies the exact path where that version of the assembly can be found.

Visual Studio actually went to the wrong drive to load the older version. That’s how bound and determined it was to make my day… interesting.

The fix was simple: I closed the solution, deleted the entire Xceed Grid 1.1 directory from my (second) hard drive, and reopened the solution. (cue singing angels) And all is now well with the world.

Still, I’m… disturbed… at the lengths it had to go to to screw up. It had to work at it. It really had to work at it.

Apparently, GMail isn’t yet XHTML-compliant

For a while now, I’ve been subscribed to get e-mails whenever someone posts something to the FxCop forum. (How primitive. I’m still waiting for them to get their act together and start providing RSS feeds like a civilized Web site.)

As soon as I got my GMail account, I started sending the forum notifications there. And let me tell you, GMail’s threading features are nice for reading mailing-list e-mails. It automatically groups all the messages with the same subject, and lets you read an entire thread at once, on a single screen. Very slick.

The only problem is, GMail strips out all the line breaks. So the entire message gets rendered as a single paragraph, with no formatting at all. Ouch. Reading source-code samples is downright painful. Reading text is downright painful, if there are more than a few paragraphs and they’re not split up in a sane way. At first I figured everyone was just a silly newbie, but once it started happening to posts from people I had read before, it dawned on me that something wasn’t right.

So this morning I decided to figure out why. GMail lets me view the full headers and source of the original message, so I did. Looked fairly normal; there was a text version and an HTML version, in multipart/alternative format, which everyone should speak. Both the plain-text and the HTML versions had line breaks (or line-break tags) where they ought to be. Back in the GMail window, it was obvious they were showing the HTML version, because there were placeholders for the GotDotNet image banner at the top.

Okay, do a View Source on the GMail window.

Heh. Or not. All I see is a message saying “Javascript is disabled in your browser”, together with a few JavaScript calls, all mashed together on one line. Makes it hard to see how GMail rendered my message, doesn’t it?

Powernarwhal to the rescue. FireFox lets you select text, and then view the source for just that selection, and it works even for HTML that was rendered by JavaScript. Cool.

So here’s the deal: The message arrived with some <table> tags, and those came through intact, as did their relatives <tr>, <td>, etc. The <img> tags were tweaked, of course, to hide the images; but they also came through. <span>? No problem.

The message included some other, mysterious tags — the <ThreadTitle> tag, for example. I’m not quite sure why they put that one in, since nobody’s going to have a clue what to do with it. GMail apparently wondered the same thing, because they stripped it out. The text inside it came through; the tag itself did not. Interesting.

That’s not the only tag they stripped out, either. The <br/> tags were gone as well. (Sure explains the missing line breaks in a hurry, doesn’t it?)

I suspect (though I haven’t checked) that <br> tags (without the “/”) do come through okay, and that there’s a bug in their regex. Duly reported via their feedback system. It’s really weird that they would lose XHTML-compliant tags, because they apparently convert all the tags to XHTML casing (all-lowercase) as part of their rendering — <Span> in the e-mail is rendered as <span> by GMail. Unlike, say, my blog’s GUI editor, which insists on making all the tag names all-caps (ouch).

Amusing Delphi 8 debugger error

I really hope Diamondback, whenever it comes out, will be more stable than Delphi 8 has been.

I just got this error message when trying to do a Step Over in Delphi 8’s debugger:

Visible in the background, as you can see, is the current location (blue background, green arrow), as well as the source for the location I’m attempting to step to (the next line).

And yet Delphi 8 continues to win awards. I should’ve gone into marketing.

New Delphi keyword needed: broken;

So Delphi has several keywords you can use to flag units, methods, classes, etc. with various warnings. If you call a method that’s flagged as deprecated;, the compiler will warn you that the method is, well, deprecated, and you shouldn’t use it anymore, because it’ll be gone from a future version of the library. platform; warns you that the method is specific to a platform; e.g., it may work only on Win32, and not on Linux.

After a debugging session today, I found a situation that calls for a new keyword: broken;.

Delphi 6’s TStream, in its Read method, makes use of untyped var parameters — one of the few Delphi features that I view with extreme distaste. You pass the variable you want to read data into — you don’t pass a pointer to it, you pass the variable itself. The compiler sees that the function declares an untyped var parameter, so what the compiler passes, behind the scenes, is a pointer; but you code as if it were a direct variable, rather than a pointer to a variable. (I’d much rather they actually admit it when a function needs to take a pointer. Hence my distaste. But that’s how Borland coded TStream, so I’m stuck with it.) The Write method does something similar, although I think it takes untyped const parameters — same idea, but the method isn’t allowed to change the value.

Untyped var parameters (and untyped const parameters) are, unfortunately, just that — entirely untyped. What the function really gets, aside from syntax, is an untyped pointer. Among other things, that means the function has no way to do a SizeOf on that parameter, so the Read method has to take a second parameter that tells how many bytes to read.

So in Delphi 6, you would write code like this:

procedure DoSomething(AStream: TStream);
  TArrayOfByte = array of Byte;   // dynamic array, heap-allocated
  B: Byte;
  I: Integer;
  A: TArrayOfByte;
  AStream.Read(B, SizeOf(B));     // reads one byte into B
  AStream.Read(I, SizeOf(I));     // reads one integer into I
  SetLength(A, 256);
  AStream.Read(A[0], Length(A));  // reads an array of 256 bytes into A

Note the syntax of the third call to Read. Yes, you pass the first element of the array (the place you want to start reading to), not the array itself. If you pass the array itself, Bad Things™ happen, because your 256 bytes will overwrite the A variable (which is actually a pointer to the heap-allocated array), thus smashing the reference, and then go on to tromp on the rest of your stack. It doesn’t take long before you learn to pass the first element instead. (Now, if the function had taken pointers in the first place…)

Well, Delphi 8, being a .NET compiler, doesn’t allow untyped var parameters, because (duh) they’re untyped, and therefore not typesafe, and therefore very .NET-unfriendly. So the Read and Write methods were changed for D8. Now they’re heavily overloaded. There’s an overload that takes a byte, an overload that takes an integer, an overload that takes an array of bytes, and it’s all good (as long as you’re not writing an entire record, which is a no-no in .NET anyway). All good, except for backward combatability. See, the new overloads only take one argument. Code written for Delphi 6 always passes two arguments, so if they only gave us the new overloads, old code wouldn’t compile.

Borland is usually pretty good about backward compatibility, so every version of Read has two overloads. The byte version can either have one parameter (just the byte — the preferred form for .NET) or two parameters (the byte and a length). So your old code compiles. Oh, it compiles just wonderfully (as long as the compiler isn’t being too flaky today). But actually, oh, running is a different matter.

See, if you call the overload that takes a byte and a length, and you give a length of 1, it’ll work great. If you call the overload that takes an int and a length, and you give a length of 4, it’ll work great. There’s even some code in there that lets you call the int overload, and pass a length of 2, or even 1, and it’ll only read two (or one) bytes from the stream, then fill the return value’s high bytes with zeroes. Cool.

The two-parameter overloads are all marked with the platform; directive. So if you use them, you get a compiler warning stating that this method is specific to a platform. Not a bad idea, I thought at first. After all, you really do want to change your code to use the new overload. The warning makes it kind of a pain when you’re writing a unit that you’ll be sharing between a Win32 app and a .NET app, but it’s still good, right?

Uh, no. What they don’t tell you, when they say it’s specific to a platform, is that the platform it’s specific to is not the platform you’re compiling for!

If you call the Read overload that takes a byte and a length, and you pass a length of, say, 256, Delphi 8 will read one byte, and then advance the stream position by 256 bytes. If you didn’t know how it worked back in Delphi 6, this would almost make sense. Kind of. Handy way to skip over unused areas of the file, maybe.

But this completely breaks the third Read in the sample code above. You try to read an array of 256 values, and you get — an array with a good first element, and the rest… zero. Kind of throws off your hash function.

Which brings me back to my proposal. Instead of marking the two-parameter overloads as platform;, I suggest a new broken; keyword, with a new compiler warning: “Dude, this method is broken. Don’t use it.”

procedure Read(var Value: Byte; Length: Integer); overload; broken;

The scary thing is, there are a few places I’d use that directive in my own code.

Adobe Liposuction

I saw this article a while back, but had to hunt today to find it again. That makes it a good candidate for a blog post, so I can find it again next time.

So anyone who’s recently used Adobe Reader (recently = since the name change from Acrobat Reader) knows that it takes a disgusting amount of time to start up. This is because it’s loading zillions of plug-ins that nobody needs. You know, the e-book plug-in, the encryption plug-in, the USB toothbrush plug-in, etc.

Hence: How to use liposuction to repair Adobe Reader 6