comments edit

Walt highlights the first reported case of prosecution for Wi-Fi theft.

I agree with Walter when he says that…

If I were the defendant’s lawyer, I would argue that (assuming its unencrypted) making a wireless network available to the public is tacit permission for others to use the network. With permission there is no unauthorized use, and no criminal activity.

Although sorry Walt, I’m not quite buying your alternative argument about “squatter rights” or “adverse possession”. A Wi-Fi network doesn’t suffer quite the scarcity as land (it’s orders of magnitude easier to create a new network than it is to create land).

Besides, no matter how long someone has been leeching off an unencrypted network, I feel the owner of the network always has to right to switch on encryption at any time. In a manner, it is similar to identity theft. I don’t care how long a thief has been using a victim’s identity, that thief should never have squatter’s rights or the right to attempt adverse possession on the identity.

comments edit

This caught my attention from Meta-Douglasp. From the home page…

It is well known that people don’t always ‘speak their minds’, and it is suspected that people don’t always ‘know their minds’. Understanding such divergences is important to scientific psychology.

This web site presents a method that demonstrates the conscious-unconscious divergences much more convincingly than has been possible with previous methods. This new method is called the Implicit Association Test, or IAT for short.

I completed the Asian American-European American IAT and was relieved with the following result:

Your data suggest little or no automatic ethnic association with American or Foreign

Considering that I’m hapa, I’d have some serious self hate issues if I automatically associated with one over the other. ;)

comments edit

I don’t know who these people are, but How To Rockstar just wrote up my blog with a very nice review (thanks guys, I see you got the check I sent).

Seriously though, when someone says something this glowing about my blog, you gotta wonder when they are going to hit me up for money. Here’s a flattering (almost sycophantic) snippet…

While most of the writing is tech-ish, it’s still damn-damn good. The opinions of this one man whose influence is so far-reaching as to be invisible are probably worth reading just to learn what everyone else is going to be thinking tomorrow. Or next year. Or five years from now. Or yesterday.

I’m happy to oblige. Five years from now, everyone will be thinking “Haacked? Nah, never heard of him.”. Oh, and also in five years, we’ll be remaking blogs rather than movies.

Dude, remember back in the day when we had Gizmodo. We’re going to do a remake, but instead of gadgets, it’s going to feature lizards. It’s going to be awesome.

Anyways, I can’t wait to tell our friends Tim and Laura who already call me and my wife “Rockers” as in “Rocker Phil”.

comments edit

Flag The United States is like your family, it’s got its problems and can seem dysfunctional at times, but you gotta love it, and it sure beats being in some of them other countries.

So a toast to July 4th, the day the British learned that outsourcing key operations to those whose goals don’t align with their own can lead to disastrous results.

Note: I am not inherently against outsourcing, and in fact am a big fan of it when it is strategic. However, too many businesses use it as a cover for their mismanagement. You also don’t outsource your key competencies and critical services. And when you do outsource, you get what you pay for, so make sure your partners goals align with your own. When the Hessians just want your money, they’re toast.

comments edit

Dr. Evil It’s an odd quirk of our taste for “round” numbers that we tend to celebrate milestones that are multiples of a power of ten. For example, a 10th anniversary is somehow more significant than a 6th anniversary. Likewise, a 100th post is more significant than a 73rd post.

Kim Il Jong This post reaches a different sort of milestone, it is my 666th post. Yes, this post bears with it the mark of the beast. I dedicate this post to pure eeeeevil.

Evil Calvin Not having a reputation evil, my first step is to gauge my current evil quotient via the “How evil are you?” website. Unfortunately I rated quite good on the Evil-o-meter. There was certainly work to do.

So chomped down on my Cuban cigar, fired up Internet Explorer (evil-o-meter rising) and navigated to the evil overload list. Using Powerpoint (+2 on the evil-o-meter) I copied the list verbatim (DMCA anyone?) and started committing them to memory.

After getting a bit bored, I spent a little time doing some stem cell research and even tried my hand at human cloning. I thought about having an abortion, but as I am male, had a tough time getting pregnant. So I changed tactics and bought an H2 and drove it into a nature preserve while smoking an illegal substance and drinking a forty.

At this point, I realized that to really get the evil-o-meter soaring, I should SPAM people. Not only should I create SPAM, I should write a web service to do so. I wrote one that returned an ADO.NET DataSet of email addresses and websites with comments enabled so that others could join in the SPAMination. Soon all the world would know about all the latest Texas Hold-Em websites.

Oh, did I mention that application is written with only one line of code? And there are no comments. And I used HTML Tables and NO CSS. It’s covered in Hungarian Notation. And I have promoted it as an example of “SOA”. And the application connects to the (non-normalized) database using the SA account without a password. I used inline sql without using parameterized queries. Yes, Satan himself is starting to get worried here. But then again, I personally didn’t write this code, I off-shored it to a sweatshop in China that employs overworked six year olds to hack out the code.

Evil Bert After all this hard work, I relaxed to a game of Dungeons & Dragons while watching a little sesame street to absorb the evil that is Bert. This led to an internal debate about which character is more evil, Barney or Bert?

Evil Barney After studying this mathematical proof of Barney’s evil and this essay, “Why is Barney Considered Evil”, I concluded that indeed, Barney is more evil.

I considered creating a Marketing website without an RSS feed, but not even I was ready to go that far.

After all that, I went back to retake the evil survey. It turns out that I may have done a bit too much research as the site declared that I wasn’t evil but clinically insane. Not bad for a day’s work. I wonder what post should I dedicate to insanity?

[Listening to: Thriller - Michael Jackson - HIStory, Past, Present And Future, Book 1 (Compilation) (Disc 1) (5:57)]

sql comments edit

I’m not sure if this is common knowledge, but you can place template parameters in your SQL scripts and evaluate them within query analyzer. I think I learned this one a long time ago from a former fantastic SysAdmin, turned DBA, turned Developer, Tyler.

Here’s an example of a short script that makes use of a template variable.

`SELECT * FROM <tableName, varchar(32), 'MyTable'>`

Paste that into SQL Query Analyzer and hit CTRL+SHIFT+M. A dialog to replace the template parameters will pop up like so

Replace Template Parameters
Dialog

Just fill in the values and hit return and you’re ready to run the script.

The format for a template parameter is <parameterName, sql data type, default value>.

comments edit

In a previous post I mentioned a problem I was having with implementing RFC3229. Well I got that one fixed, but realized that I had another very subtle bug. One that is potentially encouraged by the examples in the spec.

Before I begin, please realize that the examples are not an implementation specification. They are simply examples of how one might implement this RFC. Having said that, many implementors will probably conform to the examples as I did.

At issue is that all the examples show an integer entity tag value. Presumably this would be the id of the feed item (or post) within your backend database. In Subtext, this value maps to an integer primary key field that is an auto-incrementing identity.

So suppose you have a blog an a reader with an RFC3229-compliant aggregator makes a request for your feed. It might look like

GET /Rss.aspx HTTP/1.1Host: haacked.comIf-None-Match: "100"A-IM: feed, gzip

The “100” represents the last feed item that the aggregator making the request saw. The server presumably does a lookup to return all feed items with an ID that is greater than this number, creates a feed with those items, and sends that to the client. Bandwidth is saved as the entire feed doesn’t need to be sent, just the items with an id greater than 100.

Now suppose you had posted five items since the aggregator last made a request. The response header might look like:

HTTP/1.1 226 IM UsedETag: "105"IM: feed, gzipDate: Thu, 30 Jun 2005 23:48:05 GMTCache-Control: no-store, im

Your server is telling the aggregator client, “Hey! The last item you are getting has an e-tag of 105. Make sure to send the value 105 in your next request.”

Well at least that’s how I implemented it in Subtext. The problem is that this implementation has a very subtle bug. Can you see the problem?

Since the table that stores blog entries has its id field as an identity, I am assured that a newer element has a higher id than an older element, so that’s not necessarily the problem. The problem is that Subtext (and I presume other blogging engines) allows the author to create a post that is not published.

So suppose a blogger create a post with an ID of 106 that isn’t published. This same blogger then creates and publishes a post with an ID of 107. The next request for the feed will get just item 107 and the server response will look like

HTTP/1.1 226 IM UsedETag: "107"IM: feed, gzipDate: Fri, 01 Jul 2005 01:15:03 GMTCache-Control: no-store, im

Now say that the blogger fixes up the oh so important post 106 and finally publishes it. The next request for the feed from that aggregator will look like

GET /Rss.aspx HTTP/1.1Host: haacked.comIf-None-Match: "107"A-IM: feed, gzip

Your server will send the aggregator all feed items with an id greater than 107, completely skipping the newly published item 106. This poor aggregator completely misses out on the beauty and sublime writing that was surely within post 106.

In order to rectify this situation, I need to add a DatePublished field to my database table and use that to as the entity tag and to determine which items an aggregator has and hasn’t seen. That will ensure that important posts aren’t ignored from RFC3229 compliant aggregators.

comments edit

Jaw Fragment From the title of his post, Dream Hangovers, I thought Robb was going to tell some story about another night of too much drinking and the painful consequences afterwards. Instead he talks about how realistic dreams can often influence your mood the following day.

A few nights ago I had a dream in which I kept biting down on something hard. I spat the foreign object into my hand and was surprised to find a molar. For some reason, losing my teeth is a typical nightmare for me when I’m anxious. However this time, it was much more intense than before.

After spitting out a few teeth, I noticed I was biting on something much larger that felt like a rock or a piece of plaster. I spit it out and it my hand was a gleaming pale chunk of my jaw. Another chunk came out and I rushed to the bathroom to look in the mirror. When I opened my mouth, my entire lower jaw caved in and blood started filled up my mouth and pouring into the sink along with white pieces of my jaw. It reminded me of a river full of floating icebergs. That’s when I woke up in a cold sweat breathing very hard, furtively checking all my teeth with my tongue.

After a few moments of abject terror, I calmed down and thanked my lucky stars that all my teeth were there.

comments edit

You kind of get the feeling that Keith Brown has a beef with soap exceptions when he writes that SoapException Sucks. I won’t rehash everything he says here, but the gist of his complaint is that when throwing an exception from within a web service, the exception gets wrapped by a SoapException. What’s so bad about that? As Keith relates, the Message property of the SoapException class intersperses your fault string with a load of other crap you really don’t care about. Also, the InnerException doesn’t get serialized into the SOAP fault packet, so it is always null on the client side.

A couple solutions proposed within his comments require putting a try/catch around the body of every method and construct a suitable SoapException by hand. This just didn’t sit well with me (neither did the burrito I just ate) as it seemed quite repetitive. I figured there had to be a better way. If only there were some way to inject code after a SOAP method is called and before the XML payload is delivered to the client. Fortunately there is. SOAP Extensions!

The solution I hacked together here is to build a custom SoapExtensionAttribute used to mark up a method. If that method throws an exception, the original exception information is serialized into the detail element of the soap exception.

The key here is to remember that SOAP is at its core simply XML text messages being sent back and forth between computers. A SoapExtension lets you peek under the hood and manipulate the actual messages going in and out.

There are three classes involved in this solution, SerializedExceptionExtensionAttribute, SerializedExceptionExtension and SoapOriginalException. I’ll briefly go over each one.

SerializedExceptionExtensionAttribute is a very simple Attribute class that inherits from SoapExtensionAttribute. When applied to a target, this attribute has a property that indicates what type of SoapExtension to use for that target.

SerializedExceptionExtension inherits from SoapExtension and for the most part looks like your typical MSDN example of a soap extension in which you override ChainStream, store the old stream in a member variable, and replace it with a new stream. For the sake of illustration, I will highlight a few methods that make this extension somewhat interesting (at least for me)…

public override void ProcessMessage(SoapMessage message)
{
    if(message.Stage == SoapMessageStage.AfterSerialize)
    {
        _newStream.Position = 0;
        if(message.Exception != null && message.Exception.InnerException != null)
        {
            InsertDetailIntoOldStream(message.Exception.InnerException);
        }
        else
        {
            CopyStream(_newStream, _oldStream);   
        }
    }
    else if(message.Stage == SoapMessageStage.BeforeDeserialize)
    {
        CopyStream(_oldStream, _newStream);
        _newStream.Position = 0;
    }
}

void InsertDetailIntoOldStream(Exception exception)
{
    XmlDocument doc = new XmlDocument();
    doc.Load(_newStream);
    XmlNode detailNode = doc.SelectSingleNode("//detail");

    try
    {
        detailNode.InnerXml = GetXmlExceptionInformation(exception);
    }
    catch(Exception exc)
    {
        detailNode.InnerXml = exc.Message;
    }

    XmlWriter writer = new XmlTextWriter(_oldStream, Encoding.UTF8);
    doc.WriteTo(writer);
    writer.Flush();
}

In the method ProcessMessage, you can see that the code waits till after the method has been serialized to XML (represented by SoapMessageStage.AfterSerialize) and is ready to be sent back to the client. That’s where the exception detail is injected into the stream, assuming an exception did occur.

InsertDetailIntoOldStream finds the detail node within the serialized stream and inserts exception information into that node. In order to make this information useful to both non .NET clients and .NET clients, the exception information is formatted as XML. However, in one of the nodes of that XML, I serialize the exception using a BinaryFormatter. That way, a .NET client can gain access to the full original exception.

string GetXmlExceptionInformation(Exception exception)
{
    string format = "<Message>{0}</Message>"
        + "<Type>{1}</Type>"
        + "<StackTrace>{2}</StackTrace>"
        + "<Serialized>{3}</Serialized>";
    return string.Format(
        format,
        exception.Message,
        exception.GetType().FullName,
        exception.StackTrace,
        SerializeException(exception));
}

string SerializeException(Exception exception)
{
    MemoryStream stream = new MemoryStream();
    IFormatter formatter = new  BinaryFormatter();
    formatter.Serialize(stream, exception);
    stream.Position = 0;
    return Convert.ToBase64String(stream.ToArray());
}

Security Note!, for a production system, you probably don’t want to serialize the original exception as it will contain a stack trace and could give out more information than you wish clients to the service to have. For debugging, however, this is quite useful.

Allow me to walk through how you can apply these classes in your own code. Below, I’ve written a method that simply throws an exception. You can see that I marked it with the SerializedExceptionExtension attribute.

[WebMethod, SerializedExceptionExtension]
public string ThrowNormalException()
{
    throw new ArgumentNullException("MyParameter", "Exception thrown for testing purposes");
}

Now on the client, I simply make a call to the web service within a try/catch clause. In the snippet below, you’ll notice that I wrap the thrown exception with the SoapOriginalException class. That class is a helpful wrapper that knows how to deserialize an exception serialized using this technique. The original exception is accessed via the InnerException property.

void CallService()
{
    TestService proxy = new TestService();
    try
    {
        proxy.ThrowNormalException();
    }
    catch(SoapException e)
    {
        SoapOriginalException realException = new SoapOriginalException(e);
        Console.WriteLine(realException.InnerException.Message);
    }
}

If you’d like to try this technique out yourself and provide a critique, download the ExceptionInjectionWithSoapExtension.zip source files here. There are certainly some enhancements that could be made to the code to make it even more useful. Let me know if you make improvements.

comments edit

Real Madrid Wohoo! The little lady and myself will be in attendance as we watch Zinedine Zidane, Beckham, Ronaldo, Owen, Roberto Carlos and the rest of Real Madrid completely overpower and dismantle the lackluster Galaxy when they play an exhibition game at the Home Depot Center in Carson.

It’ll be interesting to see if Landon Donovan can scrape together a worthy performance in the face of such talent and show that he’s ready for the world stage.

I remember when living in Madrid, Spain just how revered Real Madrid is. They are a storied team with a rich history and a fantastic roster this year. Of course, too much star power can sometimes be a detriment, as we learned with the lakers last year, and as we saw this year as second place Real Madrid were upstaged by Barcelona for the Spanish League title.

comments edit

Steven Clarke has an interesting post about the usability (or lack thereof) of the Factory Pattern.

In simple terms, the usability issue strikes when a developer knows she needs an instance of object Foo. So she tries to new one up like so…

Foo foo = new Foo();

Unfortunately Foo looks like this…

public class Foo

{

ÂÂÂÂprivate Foo() {}

}

Notice the private constructor? VS.NET’s intellisense dutifully tells her that she can’t create an instance of Foo in this way. So now how is she supposed to create her beloved Foo? The answer is that there’s probably a FooFactory laying around somewhere that’ll do just that for her. So now she has to go rooting around looking for that class, her rhythm and flow being disturbed in the process.

So is the answer to simply throw out the Factory pattern? Dear god no! This is one of those cases where perhaps the IDE could be a bit more helpful. Imagine if we could markup the class like so…

public class Foo

{

ÂÂÂÂ/// <summary>

ÂÂÂÂ/// Try using the FooFactory to create this class.

ÂÂÂÂ/// </summary>

ÂÂÂÂprivate Foo() {}

}

And that comment would show up when trying to directly create an instance of Foo. Wouldn’t that be wonderful? Or for you attribute lovers, maybe an attribute would be a better option.

[Factory(typeof(FooFactory))]

public class Foo

{

ÂÂÂÂprivate Foo() {}

}

Either way, the goal is to give the forlorn developer some help via Intellisense. All that API creators need to do is to add a bit of information to their classes and voila! Intellisense to the rescue. You’ve rescued the usability of the factory pattern.

[Listening to: Victorious - Tiësto - Parade of the Athletes (4:38)]

comments edit

If you’re a fan of NPR and KCRW, make sure your voice is heard. The House will soon vote on budget cuts for public broadcasting and the issue is being painted as a liberal vs conservative battle.

I believe it is impossible for a person to be truly objective, but as far as news programs go, I think NPR does a great job of it. I think both sides of the political spectrum appreciate receiving news without the sensationalism and fear mongering so prevalent from its puerile cousin, television news. Here is the letter from KCRW in full…


Message from KCRW General Manager Ruth Seymour\ Dear KCRW Listener,

I am writing you about an unfolding crises in Congress with regard to public broadcasting. Proposed funding cuts now before the full House pose a serious threat to public radio and television – and to KCRW.

The proposed cut is 25% to KCRW’s CPB grant this October and next October as well. Moreover adding the proposed additional cuts to PBS childrens’ programs and station digital conversion – the total reduction adds up to a whopping 45%!

Facility funding, which provided oportunities for stations to modernize and extend their service has already been zeroed out. These are the grants that helped KCRW purchase it’s first modern transmitter in 1979 and launch NPR’s Morning Edition. Later they enabled KCRW to extend sevice to Ventura and the Antelope Valley.

If these cuts stand, KCRW may lose over $1,000,000 from its operating revenue. This would severely impact KCRW’s local programming and our ability to sustain NPR.

The Corporation for Public Broadcasting is the independent organization created by Congress to support public broadcasting and act as a heat shield against political interference. But now, ironically, the Corporation itself is providing the heat.

Chairman Ken Tomlinson has politicized matters by framing the issue of balance on news programs as liberal versus conservative. We vehemently object to this characterization which is intended to put public broadcasting on the defensive and influence program decisions.

  • We cherish our editorial independence and the political diversity of the audience we have attracted.
  • We believe in objective journalism, free from political constraints.
  • While we welcome constructive criticism, we reject partisan judgements masquerading as impartial analysis.

We can’t reverse the funding cuts by ourselves. We need your help.

THE MOST IMPORTANT VOICE IN PUBLIC BROADCASTING IS YOURS!

Please register your opinion by contacting your Congressional Representative right away.

The full House votes next Thursday or Friday.

Find your Congressional Representative at:\

http://kcrw.convio.net/site/R?i=wkbWt29jsWNpftH33vy4eg.

Sincerely,

Ruth Seymour\ KCRW General Manager

Visit KCRW.com for additional information and background:

comments edit

Lemmings Dare may singlehandedly be responsible for delaying Longhorn, VS.NET 2005, Yukon and many other products as legions of programmers (Microsoft and otherwise) lose productivity by spending their time playing DHTML Lemmings, a faithful javascript reproduction of the classic game Lemmings.

Lemmings is probably one of the most popular games I’ve never played until now. It is quite addicting.

comments edit

You know what, I do want to express myself, okay. And I don’t need 37 pieces of flair to do it.

Sand SharksNo. I need a Flickr Badge! For those of you reading this from an aggregator, you’ll need to take a step out of the comfort of the aggregator into the scary world of “web browsing” and view my page from a browser to see the flickr badge on the right.

I know, I’ve gushed about Flickr in the past, but I like how easy they make it to integrate into your own website. They also allow you to put up a a nifty Flash version of a badge, but I settled for the simple HTML badge.

Now if you’re concerned about such things as XHTML validating markup, you really need to quit being so anal and get a life. Having said that, let me show you some small tweaks you’ll need to make so that your flickr badge validates as XHTML 1.0 Transitional (I haven’t tried strict yet). Us anal types can’ go around with invalid markup, now can we?

When you create your badge, Flickr will give you some code to inject into your web page. The first step is to take the style element and either move it inside the head element of your page or scrape its guts and slap them inside a css file.

After that, you’ll notice that there’s a script tag just before a tr tag. That tag essentially is a javascript repeater that repeats the following tr block. If you move it, you break the badge. Unfortunately, it doesn’t validate as is so I haacked it (get it? “haacked it” As in hack? Oh Never mind) by placing the script within a caption element.

Finally, I went through and replaced all the ampersands within the URLs with &amp;. After that, voila! My homepage is back to being valid XHTML 1.0. Do I get a trophy or win prizes for this work? No. But I do get to sport this nifty piece of geek flair. Valid XHTML
1.0!

comments edit

From the Lessig blog I learned that Microsoft is releasing its spec for “Simple Feed Extensions” under a Creative Commons Attribution-ShareAlike license, often referred to as a “CopyLeft” . People are free to modify and redistribute the spec so long as the modifications are licensed under a similar license.

This shows a couple things about Microsoft. First, that it is not (and probably never has been) a mono-culture. Secondly, that groups within Microsoft get it when it comes to RSS and know how to play nice. Bravo!

comments edit

RSS Now repeat after me, “RSS is designed to be extended.”

Good. Now repeat it again. It’s old hat that Microsoft has engaged in some perhaps anti-competitive practices in the past, often referred to as their “embrace and extend” philosophy. But embracing and extending isn’t always a bad thing.

Of course, I should expect a knee-jerk reaction against the announcement from the Slashdot crowd, but it seems they’re not the only ones up in arms.

What’s interesting about these reactions is the amount of misinformation and ignorance being spewed forth. Suddenly, “extend” has become a derogatory label. Yet these very same people will laud an application like Eclipse for its…gasp!…extensibility (and rightly so).

In this case, it’s hard to find a shred of so called “evil” in this announcement by Microsoft. They’ve chosen a CopyLeft license for Pete’s sake! You don’t get more open than that. You even have Lawrence Lessig applauding this, remember him? He“s the lawyer who helped the DOJ mount its Supreme Court showdown with Microsoft.

Face it folks, you’re just wrong this time. Microsoft releasing extensions to RSS is not going to be the death knell for RSS. An extension does not change or make proprietary the original RSS specification. As I said before, RSS is designed to be extended. Anyone can extend RSS. Heck, even I proposed an RSS extension, albeit one that gained just about zero traction (although I may sneak it into Subtext just to satisfy my megalomaniacal urges).

comments edit

Just curious if any of my fantastic readers (or Google searchers, welcome. Nothing but love for ya) have experience with using Quickbooks Online. If so, let me know in the comments what your experience with it has been. Thank you.

subtext comments edit

Subtext Logo I’ve been intentionally quiet about how Subtext is progressing (apart from a couple minor posts on how to obtain the code via CVS). My reticense is certainly not from lack of excitement or enjoyment of the project. Working on Subtext has been about the most enjoyable software development project I’ve ever had the pleasure to work on. So much so, that I’ve fallen a bit behind on my “real” work. Unfortunately this has caught up to me as I now have two projects with a potential third not far behind to work on (Yes, I know. A good problem to have, so quitcher belly-aching). This is very exciting for me as it may herald the beginning of a company. But it also means I need to slow down on Subtext a bit.

The reason I have been so reticent about Subtext up to this point is that we have not yet had a release. It was suggested to me that I probably should’t have waited to make the original Subtext announcement until I had a first release. This is definitely good advice for one who is starting an open source project. However, it may have helped in my case that I was building on an existing project familiar to many. And the few who did jump at the chance to help have been invaluable in what progress we’ve made so far.

What progress you ask? Well as you can see in this post, we are making great progress in having a nice logo. This is not the final logo, but probably really close. As you know, if a project has a nice logo, the code must really be nice. ;)

Subtext is progressing nicely in other areas too. So much so that I upgraded my blog to Subtext after a particularly withering comment spam attack. Subtext hasn’t yet completely eradicated comment spam, but it definitely has made a difference already.

In any case, I hoped not to talk much about it until we did have a release, but here I am anyways blabbing my mouth fingers. The goal of the first release is to generate excitement about the project and have many more contributors help with the next release. By talking about it now rather than waiting, I hope to try and encourage people to contribute before the first release. As my involvement declines for a few months (hopefully at most), I hope to have others pick up some of the slack and carry the torch sub forward.

Project Website\ If you’re interested in tracking the progress of subtext, check out our new project website at http://subtextproject.com/. It is definitely a work in progress, but it has plenty of instructions for how to get the latest source code and how to contribute. Not only that, the site itself is in our CVS repository. So if you want to contribute to our documentation efforts (please! please!), you can submit patches to the project site.

Roadmap\ Also be sure to check out the updated Roadmap.

Well that’s it for me. I spent today on some Subtext housekeeping to clear the way for others to make some nice progress. I’ll probably be much more quite for a few months, though I will respond to emails and such and continue to try and guide the process. It’s been and continues to be fun sailing.