Well, That Was Stupid

So I got a spam today that Spambayes didn't catch. I was reading my email and this one popped up, and I would've just fed it to Spambayes, except that Don Park's been posting on phishing websites that imitate well-known companies. I had noted that some of these phishers redirect you to the real site and popup a window over the site prompting you for personal information. This particular spam I got gave the recipient explicit instructions to that effect:
This message was sent by the Citi Cards Email Verification Server to verify your email address. You must complete this process by clicking on the link below and entering in the small window your Citibank ATM full Card Number and Pin that you use on ATM. (Please make sure that pop-up windows are enabled in your Internet Browser, otherwise you will not be able to see the small window) This is done for your protection, because some of our members no longer have access to their email addresses and we must verify them.
So, wanting to see exactly what scam they were setting up, I clicked on the link. There were 2 mistakes here:
  1. IE is my default browser
  2. I run as admin at work (because certain corporate standard software won't run otherwise).
In any case, the site came up and McAfee kindly informed me that it found and cleaned JS/Downloader-FU, VBS/Psyme, and Downloader-FU. I'm hoping that was all there was out there. I also noticed a popup window almost off the bottom of the screen, which I'm assuming was the one that did the dirty work, at that point I didn't care, I was closing windows as fast as possible. The moral: never, ever click on a link in a spam. Forget scientific curiosity, you just don't want to go near them.

— Gordon Weakliem at permanent link

Adding Value to a Syndicated Feed

Dare Obasanjo argues that RSS and Atom are interchangeable and goes on to point out that most Atom feeds have fewer features than RSS. The same is true for my own feeds, though I've been thinking about importing all the RSS 2.0 features into my Atom feed. Still, Dare's point is that they're equivalent (which is true unless you really care about things like modified dates or the semantics of <link>), and this makes me wonder what sort of things Atom could do to really add value. The link tag seems like the most promising area. For example, navigation via rel='next' and rel='prev' are somewhat interesting. I've also been thinking about adding links with rel='related' to my entries, so that I can give attribution or track a line of thought without explicitly linking in the content. I also noticed rel='source' and rel='via', which seem to be a way to thread, though I'm not quite getting the meaning of the source of source, so to speak.

— Gordon Weakliem at permanent link

Best Practices for .NET Web Service Clients

I've been working on a SOAP web servicse project for about 2 1/2 years now, and we've been in production for almost 21 months. Lately I've started to realize that the default client proxy generated by WSDL.EXE (or VS.NET) has a few quirks that can kill you in a production environment. Here's my short list of best practices. Some of them depend upon your specific situation, so consider your situation before implementing them:
  1. Implement Logging: When you go to your vendor with a problem, the best place to start is with what went on the wire. There's a sample in the SDK that shows how to start, couple this with a good logging package, and you've got tracing that you can turn on and off at runtime.
  2. Implement PreAuthenticate: There's a property named PreAuthenticate on System.Web.Services.Protocols.SoapHttpClientProtocol class (the base for all .NET web service client proxies) which is supposed to send credentials with the SOAP message. Unfortunately, it doesn't do anything. If you're working with a service that requires Basic authentication, you'll save an exchange of messages by sending credentials on your request, instead of forcing a challenge.
  3. Disable 100-Continue: The rationale for having a web service client send an Expect: 100-Continue on each request is that it prevents the client from sending a large amount of data on a request that the server will reject, primarily in the case where the service is secured and requires authentication. If you implement PreAuthenticate, and you're using Basic authentication (or any scheme that's not challenge response), this behavior is a net loss; you do an extra exchange of packets, wasting a hundred milliseconds in the best case. If you are using challenge-response authentication, then you'll need the initial challenge, so it's better to leave Expect: 100-Continue on in that case.
One easy way to do accomplish #2 and #3 on this list is to override GetWebRequest in your client proxy. Here's a sample that implements the optimizations listed above:
protected override System.Net.WebRequest GetWebRequest(Uri uri)
{
  HttpWebRequest request = 
    (HttpWebRequest)base.GetWebRequest(uri);
  if (this.PreAuthenticate)
  {
    // since the PreAuthenticate property doesn't seem to do anything, 
    // we write our own authorization header.
    NetworkCredential nc = this.Credentials.GetCredential(uri,"Basic");
    // only if we have credentials for basic auth
    if (nc != null)
    {
      request.ServicePoint.Expect100Continue = false;
      byte[] credBuf = 
        new UTF8Encoding().GetBytes(nc.UserName + ":" + nc.Password);
      request.Headers["Authorization"] = "Basic "+ 
        Convert.ToBase64String(credBuf);
    }
  }
  return request;
}

— Gordon Weakliem at permanent link