Archive for May, 2007

A bit of everything

Tuesday, May 29th, 2007

Today was a really good day, at least for summer break. I got to see my girlfriend again (second time in the last week… woot), got a long-standing WikiBench todo done, and found some pretty nasty bugs in Mono’s implementation of the 2.0 framework TryParse methods for integer types.

Somewhere in there I sent a form letter to the three Indiana congressmen urging them not to support the IPPA of 2007. I’d encourage you to do the same.

WikiBench now has proper support for blacklisting anonymous users, as well as blocks of IP addresses. You can ask it to blacklist, say “192.168.0.0/8″ and every edit coming from an anonymous user in that range will be reported. Combined with state persistence, as I just blogged about, this is really useful. I also toyed with the idea of allowing a user to maintain multiple user-defined blacklists, but am not certain when or if this will happen.

Coming soon to WikiBench: watchlist and citation builder pads.

(I should really release a beta soon…)

WikiBench: Persistence

Friday, May 25th, 2007

One of the things I’d been dreading implementing in WikiBench is state persistence. This is, however, very important. When the user closes the application, they should find it in the same state they left it in when they open it later.

This is a tricky one to get right, though. Because one of the goals is portability, I can’t rely on certain paths to exist. Fortunately the CLI has a nifty answer to this one. A simple call to Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) will return a user-specific path where configuration files can be saved. On *nix this is $HOME/.config and on Windows it’s %APPDATA%, which is typically %USERPROFILE%\Application Data.

The format of the configuration file should also be portable. XML was the natural choice.

Then I had to deal with how to let addins hook into configuration loading and saving process. If I were going for pure efficiency I would have forced addins to deal with XmlReaders and XmlWriters. This would be painful at best. While more of a memory hog, I decided to just maintain an XmlDocument in memory.

I went through several design ideas (one of which I implemented and later had to remove) before deciding on a refactoring of the IAddinEntry interface. The initial goal of this interface was to provide a way for addins to execute code immediately after being loaded, before anything else happened, and then to clean up after the addin was unloaded. The more I thought about it, the more this seemed like the perfect place to deal with configuration data.

So I converted this interface to a class. It retained its two main methods, Enter() and Exit(). I added a property that can be used by subclasses to get the XmlElement that encloses all of the addin’s data. I also added another method, UpdateConfig(). This is called just before the configuration file is written, and is guaranteed to be called only after a call to Enter(), but before a call to Exit(), which is important for addins that do set-up and tear-down of structures that need to be persisted.

So there are just two events an addin needs to deal with to persist state: Enter(), where the state is restored, and UpdateConfig(), where the state is saved. Exit() is intentionally not involved in state persistence.

This system allows a great deal of flexibility; addins can either push updates to the configuration document as they happen, or wait for WikiBench to notify them of the impending save and store their data then. Which is the appropriate technique will depend on how the addin works.

Three bits of WikiBench now use this system. WikipediaChangeStream persists the list of wikis to stream changes from, the Recent Changes pad persists the filter selection, and the Blacklist pad persists the items in the blacklist.

Well, it finally happened…

Monday, May 21st, 2007

I got a car! They just had some work done on it so it should be working for a while yet. Not bad for $500.

Manhood

Wednesday, May 16th, 2007

Some of you may know that I celebrated my 21st birthday recently. So I guess I’m legally an adult according to the law, which means that I should be mature enough to choose how much of my time I want to spend drunk. Apparently turning 21 is that life-changing, I guess, according to the government anyway. I think I’ll stay sober, thanks.

It got me thinking though. Does our society really have a grasp on what it means to be a man? If popular culture is to be believed, the measure of manhood is how much sex you can get, how many different people you get it with, how much pain you inflict on said persons, and how big your porn collection is. Oh, and throw some racism in for good measure.

It’s amazing how many of my close friends subscribe to this “ideal.” There are some things I can tolerate; nobody’s perfect. But the way society tells men to treat women is so bizarre, and frequently conflicting. We have on the one hand rap “music” with its utilitarian view (and that’s being generous) and sitcoms that glorify cheating, and on the other we have advertisements for diamond stores and … uhm, well, I just sat here for about five minutes trying to come up with another counterexample and couldn’t think of anything. Suffice it to say that society has some complex on this subject. But I think it’s fair to say that the dominant message is that women are devices for the amusement and pleasure of man, and if you don’t like the one you’ve got you can throw her away and get another.

This is absolutely sickening. Maybe it’s just me. Maybe it’s the fact that my parents have been outstanding role models on this subject. Maybe I’m a dinosaur… at 21. But every time I hear this message (and it’s impossible to avoid today) I get enraged. To me a woman has always been someone you treat with respect and courtesy. You don’t make jokes about her behind her back to impress your buddies. You don’t order her around like your slave. You don’t tell her you’re working late so you can go do it with some whore at your workplace.

This message from society isn’t how to be a man, it’s how to be an animal. It’s degrading to women and to men. Where did honor go?

I’m not trying to rant (well, maybe a little). I just think that it’s time men reclaim manhood — real manhood, not this degenerated replacement we are spoonfed by culture.

JavaScript Queues

Tuesday, May 15th, 2007

One of the most annoying parts of VandalSniper from a maintenance perspective was how the “JavaScript Queue” was run. To perform some complex action such as rolling back an article and posting a warning to the talk page of the editor required a sequence of JavaScript snippets to be run, one each time the browser finished loading a page. But the way this was implemented was absolutely horrendous. (But it was my first C# project, so I’m okay with that.)

When the queue was started, the entire window was set insensitive to prevent the user from messing with the fragile sequence of events that would take place. Two variables local to the main window class were set: a Queue containing the snippets to run, and a WebBrowser on which to execute these snippets. Once the queue was empty, or the script reported an error, these variables would be set to null and the main window made sensitive again.

Ick. Aside from being horribly annoying to the user (I mean we’ve got multiple browser tabs here… why shouldn’t they be able to use another?) it was just plain hackish.

I just finished implementing this same idea in WikiBench and I think I’ve done a lot better this time. I already have a BrowserTabState class that represents the state of one tab. Instances of this class are passed around as sort of identifiers, as well as being handles into a tab’s state. I added a boolean Locked property to this class; when set to true, all of the browser’s navigation controls are disabled, excluding the stop button. This includes the browser, the address entry, and the close tab button in the tab label. Other tabs remain functional. Oh, and the stop button that remains enabled will, when clicked, raise an event on the BrowserTabState instead of stopping navigation. This can be handled to abort whatever operation is in progress and restore control to the user.

The other part of this puzzle is the new JavaScriptQueue class. It just needs to be instantiated, given a BrowserTabState and an array of strings to work with, and it will manage all of the events.

Now this wouldn’t be complete without a little bit of an ugly hack. Part of the reason the entire main window was disabled in VandalSniper was because of the pads below the browser; if an item in the Recent Changes pad was clicked, for example, the browser would navigate away from the page that the JavaScript snippets expected it to be on. In WikiBench this could happen either through BrowserTabState.LoadUrl() or BrowserTabState.InvokeJavaScript(). The solution? These methods simply don’t work when BrowserTabState.Locked is true. I added two more methods: BrowserTabState.LoadUrlThroughLock() and BrowserTabState.InvokeJavaScriptThroughLock(). Things that expect to be working while a tab is locked (such as JavaScriptQueue) use these methods; things that don’t, like the recent changes pad, use the regular methods. A little bit screwy, but not a terrible solution.

I’ve added the “Report to AIV” user menu item both as a proof of concept for this system, and… well, because it was in VandalSniper, and that’s the feature set I’m copying.

What’s in a name?

Sunday, May 13th, 2007

Quite a bit, if you’re Gtk#.

I’ve implemented the popup user menu in WikiBench.MediaWikiIntegration, along with the extension points for other addins to insert their own menu items into the menu. They can either provide a type extension using a class that derives Gtk.MenuItem, or a custom extension node provided by MediaWikiIntegration to add a separator. It was working perfectly… well, almost.

If you are using the Clearlooks GTK+ engine then you know that when you hover over a menu item, the text color changes from black to white. Lots of other themes do this too. Well, the text on one of the menu items in my popup menu was not, and it happened to be a menu item provided by an addin. So, naturally, I start poking at this phenomenon.

Is it because the class I’m instantiating is in another assembly? Nope.

What about the fact that it’s instantiated using reflection? Nope again.

So I gave up and went to bed. Today I started digging around a bit more, and finally gave up again.

Later I decided to refactor a few classes, and one of the ones on the list was the menu item that was acting funky. The class was named BlacklistUserMenu, and since the other classes I’d defined were named things like TalkMenuItem and BlockLogMenuItem, I renamed it to BlacklistMenuItem for consistency. Then I compiled and ran the program to make sure my changes worked.

They did. In fact they really worked, because now the menu item text was correctly turning white when the mouse was on it. Just to make sure I wasn’t imagining it, I renamed the class back and sure enough the text color didn’t change.

I’m not sure whose fault this is, GTK+ or Gtk#, but it’s certainly one of the more interesting bugs I’ve seen. Who would have thought that the name you give a class could affect its behavior?

Glue-free JSCall#

Tuesday, May 8th, 2007

One of my goals during this rewriting of VandalSniper as a more general-purpose browser has been to reduce or eliminate the dependency on platform-specific glue libraries. JSCall# uses a C/C++ library to interact with the DOM, and this is just one more hurdle to be jumped over on the road to portability. Who wants to set up a build environment against Mozilla on Windows? Not me.

So I started fiddling around with Gecko# some, and discovered that it’s possible — and simple, really — to eliminate the glue library. To place a call to JavaScript from the CLI, it’s as simple as calling WebControl.LoadUrl() passing a string like “javascript:someFunction()”. This does change the return from WebControl.Location, but this can be worked around easily enough.

To make calls back, I copied an idea from JSCall#. The call is placed by constructing a string containing the function name and argument list, and the document title is set to this string, then immediately set back to what it was. This is picked up by the WebControl.TitleChange event handler, where the pieces are pulled apart into an array, the function name mapped to a delegate, and the delegate invoked with the arguments.

One of the cool things about the “javascript:” method of calling functions is that it seems to work just as well for whole function libraries, even those with newlines in them. The only caveat I’ve discovered is that if there is any //-style comment in the JavaScript, everything after it will be ignored. It seems that while embedded newlines are okay, they aren’t really treated as newlines. WikiBench does nothing to correct for this; it’s assumed that addins know about this. While I’d love to have it strip such comments out, that would require some parsing work (”//” can be embedded in a string safely, for example).

It’s one big kludge, but it works remarkably well.

More on WikiBench

Tuesday, May 8th, 2007

What WikiBench looks like right nowI’ve been hacking on WikiBench some more. The primary addition is the recent changes pad, which you can see in the screenshot. It is a separate addin that hooks into the WikipediaChangeStream addin to provide a list of changes to the user. Clicking a row in the list will display that diff in the browser, as expected.

The preferences dialog shows off the preferences pane provided by the WikipediaChangeStream addin for managing which Wikimedia projects to monitor changes from.

A lot is probably going to change between now and the public beta, but this is a pretty darn good start.

More HD-DVD fanart!

Monday, May 7th, 2007

To further test US copyright law, I have created more art that incorporates the released AACS processing key that the MPAA is sending DMCA takedown notices over. Due to the size of the image I am making it available exclusively at deviantART.

The image uses 24-bit sections of the key as the colors for text elements.

I wonder… can the MPAA send takedown notices against every image that contains these colors?

Space Fur - AACS Version

Thursday, May 3rd, 2007

Many of you are aware of the publication of an AACS processing key that can be used to decrypt any HD-DVD movie currently released. The MPAA is sending DMCA takedown notices left and right.

When this happened with DeCSS, people responded by making art out of the DeCSS code. I’ve done the same with this key. Just convert it to an RGB PPM, strip the header, and look at the low-order bit of each component of each pixel.

By the way, this image is copyrighted by me. I wonder if I’ll get a DMCA takedown notice over material that I own?

US copyright law is nuts.

Update 2007-05-21: I said “low-order byte” when it’s in fact the low-order bit. This has been corrected.