Shallow Thoughts : : Jun

Akkana's Musings on Open Source Computing and Technology, Science, and Nature.

Sat, 29 Jun 2013

Teaching Robotics to High School Girls at GetSET

[GetSET Robots and Sensors workshop] Wednesday I taught my "Robotics and Sensors" workshop at the SWE GetSET summer camp.

It was lots of fun, and definitely better than last year. It helped that I had a wonderful set of volunteers helping out -- five women from CodeChix (besides myself), so we had lots of programming expertise, plus a hardware engineer who was wonderfully helpful with debugging circuits. Thanks so much to all the volunteers! You really made the workshop!

We also had a great group of girls -- 14 high school seniors, all smart and motivated, working in teams of two.

How much detail?

One big issue when designing a one-day programming workshop is how much detail to provide in each example, and how much to leave to the students to work out. Different people learn differently. I'm the sort who learns from struggling through a problem, not from simply copying an example, and last year I think I erred too much in that direction, giving minimal information and encouraging the girls to work out the rest. Some of them did fine, but others found it frustrating. In a one-day workshop, if you have to spend too much time working everything out, you might never get to the fun stuff.

So this year I took a different approach. For each new piece of hardware, I gave them one small, but complete, working example, then suggested ways they could develop that. So for the first example (File->Examples->Basic->Blink is everyone's first Arduino exercise), I gave everyone two LEDs and two resistors, and as soon as they got their first LED blinking, I encouraged them to try adding another.

It developed that about half the teams wired their second LED right next to the first one, still on pin 13. Clever! but not what I'd had in mind. So I encouraged them to try moving the second LED to a different pin, like pin 12, and see if they could make one LED turn on while the other one turned off.

Another challenge with workshops is that people work at very different speeds. You have to have projects the fast students can work on to keep them from getting bored while the rest are catching up. So for LEDs, having a box full of extra LEDs helped, and by the time we were ready to move on, they had some great light shows going -- tri-colored blinkers, fast flashers, slow double-blinks.

I had pushbuttons on the tentative agenda but I was pretty sure that we'd skip that part. Pushbuttons are useful but they aren't really all that much fun. You have to worry about details like pull-down resistors and debouncing, too much detail when you have only six hours total. Potentiometers are more rewarding. We went through File->Examples->03.Analog->AnalogInput, and a few teams also tried LED fading with File->Examples->03.Analog->AnalogInOutSerial.

Music

[GetSET Robots and Sensors workshop] But then we moved on to what was really the highlight of the day, piezo speakers. Again, I provided a small working example program to create a rising tone. The Arduino IDE has no good speaker examples built in, so I'd made a short url for my Robots and Sensors workshop page, is.gd/getset, to make it easyto copy/paste code. It took no time at all before their speakers were making noise.

I was afraid they'd just stop there ... but as it turned out, everybody was energized (including me and the other volunteers) by all the funny noises, and without any prompting the girls immediately got to work changing their tones, making them rise faster or slower, or (with some help from volunteers) making them fall instead of rise. Every team had different sounds, and everybody was laughing and having fun as they tweaked their code.

In fact, that happened so fast that we ended up with plenty of time left before lunch. My plan was to do speakers right before lunch because noise is distracting, and after you've done that you can't to concentrate on anything else for a while. So I let them continue to play with the speakers.

I was glad I did. At least three different teams took the initiative to search the web and find sample code for playing music. There were some hitches -- a lot of the code samples needed to be tweaked a bit, from changing the pin where the speaker was plugged in, to downloading an include file of musical notes. One page gave code that didn't compile at all. But it was exciting to watch -- after all, this sort of experimentation and trial-and-error is a big part of what programmers do, and they all eventually got their music projects working.

One thing I learned was that providing a complete working .ino file makes a big difference. Some of the "music on Arduino" pages the girls found provided C functions but no hints as to how to call those functions. (It wasn't obvious to me, either.) Some of my own examples for the afternoon projects were like that, providing code snippets without setup() and loop(), and some teams were at sea, unsure how to create setup() and loop(). Of course I'd explained about setup() and loop() during the initial blink exercise. But considering how much material we covered in such a short time, it's not reasonable to expect everybody to remember details like that. And the Arduino IDE error messages aren't terribly easy to read, especially showing up orange on black in a tiny 3-line space at the bottom of the window.

So, for future workshops, I'll provide complete .ino files for all my own examples, plus a skeleton file with an empty setup() and loop() already there. It's okay to spoon feed basic details like the structure of an .ino file if it gives the students more time to think about the really interesting parts of their project.

Afternoon projects

[Working on the robotic car] After lunch, the afternoon was devoted to projects. Teams could pick anything we had hardware for, work on it throughout the afternoon and present it at the end of the workshop. There were two teams working on robotic cars (sadly, as with so many motor projects, the hardware ended up being too flaky and the cars didn't do much). Other teams worked with sonar rangefinders, light sensors or tilt switches, while some continued to work on their lights and music.

Everybody seemed like they were having a good time, and I'd seen a lot of working (or at least partly working) projects as I walked around during the afternoon, but when it came to present what they'd done, I was a little sad. There was a lot of "Well, I tried this, but I couldn't get it to work, so then I switched to doing this." Of course, trying things and changing course are also part of engineering ... that sentence describes a lot of my own playing with hardware, now that I think of it. But still ... I was sad hearing it.

Notes for next time

So, overall, I was happy with the workshop. I haven't seen the evaluation forms yet, but it sure seemed like everybody was having fun, and I know we volunteers did. What are the points I want to remember for next time?

Thanks again to the great volunteers! I'm looking forward to giving this workshop again.

Tags: , , , , ,
[ 20:36 Jun 29, 2013    More education | permalink to this entry | comments ]

Sun, 23 Jun 2013

Arduino and Servos

[Servo wired up to Arduino, without separate battery] My quest to make physical things move with Arduinos continues as we ramp up to Wednesday's GetSET workshop.

A few nights ago I finally broke out some old airplane servos and hooked them up to the Arduino. Don't know why I'd never gotten around to that, but I hadn't.

I had to decode the wire colors, aided by this excellent Connector Types page from Servo City. The GWS Naro servo I chose, with a JR plug, has a red wire (power), a brown wire (ground) and an orange wire (signal). Easy enough.

The Arduino software has a built-in Servo library, with instructions on wiring things up and a sample "Sweep" program to run the servo through its paces. Easy. I hooked it up and in just a few minutes I had the servo arm sweeping. Servos are so easy!

Or so I thought. The next day, I tried turning it into a real application, and that's where my problems started. I added a couple of photoresistors to my basic servo circuit and wrote a quick sketch to hook up the servo and print the output from the photoresistors to the serial port, as a first step before making it actually move the servos in response to the light coming in.

And ... nothing. Not only did I not get any output on my serial console, but I couldn't even open the serial console -- /dev/ttyACM0 didn't exist on my computer, or if it did, I got an error trying to open it. I couldn't even download new versions of the sketch, since those, too, are downloaded over the ACM0 serial device.

It turns out that servos, like larger motors, need a separate power source. Sometimes you can get away with powering them from the Arduino's 5v supply, but sometimes it will lead to flaky results.

This is contrary to every tutorial I found on the web. The official Arduino.cc Servo library documentation says "The power wire is typically red, and should be connected to the 5V pin on the Arduino board." and adds "Note that servos draw considerable power, so if you need to drive more than one or two, you'll probably need to power them from a separate supply (i.e. not the +5V pin on your Arduino). Be sure to connect the grounds of the Arduino and external power supply together."

And the Adafruit motor shield documentation says, "Servos are powered off of the same regulated 5V that the Arduino uses. This is OK for the small hobby servos suggested. If you want something beefier, cut the trace going to + on the servo connectors and wire up your own 5-6V supply!"

Basically, everywhere you turn people will tell you that for one or two servos, there's no point in fussing with a separate power supply. But when I went to the #arduino IRC channel, the experts there assured me that all the web tutorials were wrong, and that power was almost certainly my problem -- even with a single tiny GWS Naro servo.

And sure enough, when I added a 7.4v li-po battery as the power source for the servo, all my problems went away. Serial communication worked fine, and the servo was less jumpy. It's probably less risky to the Arduino, too.

The weirdest part of all this? When I tried to power it all off the Arduino's power supply (from USB), the servo was working fine, moving to wherever I told it. It was just serial communications to the PC that was failing.

I still have yet to find a good, simple way to power servos if you can't power them off the Arduino's 5v supply. Apparently their maximum voltage is 6V, and it's risky giving them any more than that. Right now I have a 7.4V li-po pack going through a speed controller; I'm not using the speed controller for anything except voltage regulation. Pretty silly.

I tried using a 4 AA pack, but that didn't seem to have enough oomph to power the servos. Maybe the answer is to add a 5v voltage regulator to the circuit, but that makes it a little difficult for robotics classes.

So, anyway, don't believe what you read on the net. That little 5v port is not a reliable power source even for one small hobby servo. Spread the word! And have fun playing with servos, whatever you end up using as a power source.

Tags: , ,
[ 21:43 Jun 23, 2013    More hardware | permalink to this entry | comments ]

Thu, 20 Jun 2013

The wonders of a pressure washer

Homeowner tip of the day:

[Before and after pressure washing] We've been repairing our fence and deck at home. One down side to that is that the new boards don't match the old boards at all. The old boards are grey and weathered.

At least, I always thought they were grey because they were weathered. But it turns out that no, they were just dirty. (Funny how that happens to fence posts and deck rails that sit outside for twenty years.)

The answer is a wonderful device called a pressure washer. You hook it to a hose, plug it in, and it shoots out a high-pressure spray of water that cleans anything. The results are phenomenal. Turns out that under that grey exterior, there's wood that actually looks like wood!

It does expose some flaws, too. It strips off all the sealant we've put on over the years, and it also strips off any part of the wood that's damaged or weakened. So some of the wood comes out looking a little, well, furry. But a little sanding would take care of that. Using a lower speed setting and a wider spray pattern helps.

[Before and after pressure washing] It's even more amazing to watch the pressure washer in action, and see the color change as it happens. Here's an up-close look.

We looked into renting a pressure washer, but apparently the ones available for rent are huge gas-powered monstrosities more likely to rip the fence apart rather than just clean the dirt off. And the rental fee is about what it costs to buy a brand new electric pressure washer. Ours is nothing special, just the one that was on sale at the local Harbor Freight.

The only bad thing about the pressure washer is that it makes you want to spend all your time sitting outside watching the wood dry to see how the colors will come out. On second thought, on a nice summer Saturday afternoon, maybe that's not such a bad thing!

Update: several years later, I still think pressure washers are pretty neat tools. But I'm regretting posting this, because it turns out there are so many spammers who try to spam every page containing the phrase "pressure washer" with their buy-online links. This article may be the biggest spam magnet on my entire site.

I'm leaving the page up, but I want to stress that we bought the one from the brick and mortar store Harbor Freight -- they put it on sale quite regularly, and coupons are easy to find -- and that if you buy online from a place with "pressurewasher" in the URL, there's a good chance that you're rewarding spammers. My apologies to any pressure washer companies out there who don't spam.

Tags:
[ 22:50 Jun 20, 2013    More misc | permalink to this entry | comments ]

The wonders of a pressure washer

Homeowner tip of the day:

[Before and after pressure washing] We've been repairing our fence and deck at home. One down side to that is that the new boards don't match the old boards at all. The old boards are grey and weathered.

At least, I always thought they were grey because they were weathered. But it turns out that no, they were just dirty. (Funny how that happens to fence posts and deck rails that sit outside for twenty years.)

The answer is a wonderful device called a pressure washer. You hook it to a hose, plug it in, and it shoots out a high-pressure spray of water that cleans anything. The results are phenomenal. Turns out that under that grey exterior, there's wood that actually looks like wood!

It does expose some flaws, too. It strips off all the sealant we've put on over the years, and it also strips off any part of the wood that's damaged or weakened. So some of the wood comes out looking a little, well, furry. But a little sanding would take care of that. Using a lower speed setting and a wider spray pattern helps.

[Before and after pressure washing] It's even more amazing to watch the pressure washer in action, and see the color change as it happens. Here's an up-close look.

We looked into renting a pressure washer, but apparently the ones available for rent are huge gas-powered monstrosities more likely to rip the fence apart rather than just clean the dirt off. And the rental fee is about what it costs to buy a brand new electric pressure washer. Ours is nothing special, just the one that was on sale at the local Post Tools.

The only bad thing about the pressure washer is that it makes you want to spend all your time sitting outside watching the wood dry to see how the colors will come out. On second thought, on a nice summer Saturday afternoon, maybe that's not such a bad thing!

Tags:
[ 22:49 Jun 20, 2013    More | permalink to this entry | comments ]

Sat, 15 Jun 2013

Autocompleting xchat channel log filenames in zsh

Sometimes zsh is a little too smart for its own good.

Something I do surprisingly often is to complete the filenames for my local channel logs in xchat. Xchat gives its logs crazy filenames like /home/akkana/.xchat2/xchatlogs/FreeNode-#ubuntu-us-ca.log. They're hard to autocomplete -- I have to type something like: ~/.xc<tab>xc<tab>l<tab>Fr<tab>\#ub<tab>us<tab> Even with autocompletion, that's a lot of typing!

Bug zsh makes it even worse: I have to put that backslash in front of the hash, \#, or else zsh will see it either as a comment (unless I unsetopt interactivecomments, in which case I can't paste functions from my zshrc when I'm testing them); or as an extended regular expression (unless I unsetopt extendedglob). I don't want to unset either of those options: I use both of them.

Tonight I was fiddling with something else related to extendedglob, and was moved to figure out another solution to the xchat completion problem. Why not get zsh's smart zle editor to insert most of that annoying, not easily autocompletable string for me?

The easy solution was to bind it to a function key. I picked F8 for testing, and figured out its escape sequence by typing echo , then Ctrl-V, then hitting F8. It turns out to insert <ESC>[20~. So I made a binding:

bindkey -s '\e[20~' '~/.xchat2/xchatlogs/ \\\#^B^B^B'

When I press F8, that inserts the following string:

~/.xchat2/xchatlogs/ \#
                    ↑ (cursor ends up here)
... moving the cursor back three characters, so it's right before the space. The space is there so I can autocomplete the server name by typing something like Fr<TAB> for FreeNode. Then I delete the space (Ctrl-D), go to the end of the line (Ctrl-E), and start typing my channel name, like ubu<TAB>us<TAB>. I don't have to worry about typing the rest of the path, or the escaped hash sign.

That's pretty cool. But I wished I could bind it to a character sequence, like maybe .xc, rather than using a function key. (I could use my Crikey program to do that at the X level, but that's cheating; I wanted to do it within zsh.) You can't just use bindkey -s '.xch' '~/.xchat2/xchatlogs/ \\\#^B^B^B' because it's recursive: as soon as zsh inserts the ~/.xc part, that expands too, and you end up with ~/~/.xchat2/xchatlogs/hat2/xchatlogs/ \# \#.

The solution, though it's a lot more lines, is to use the special variables LBUFFER and RBUFFER. LBUFFER is everything left of the cursor position, and RBUFFER everything right of it. So I define a function to set those, then set a zle "widget" to that function, then finally bindkey to that widget:

function autoxchat()
{
    LBUFFER+="~/.xchat2/xchatlogs/"
    RBUFFER=" \\#$RBUFFER"
}
zle -N autoxchat
bindkey ".xc" autoxchat

Pretty cool! The only down side: now that I've gone this far in zle bindings, I'm probably an addict and will waste a lot more time tweaking them.

Tags: , ,
[ 21:31 Jun 15, 2013    More linux/cmdline | permalink to this entry | comments ]

Sun, 09 Jun 2013

Debugging a Firefox freeze on Ringtail and Sid

I recently went on an upgrading spree on my main computer. In the hope of getting more up-to-date libraries, I updated my Ubuntu to 13.04 "Raring Ringtail", and Debian to unstable "Sid". Most things went fine -- except for Firefox.

Under both Ringtail and Sid, Firefox became extremely unstable. I couldn't use it for more than about fifteen minutes before it would freeze while trying to access some web resource. The only cure when that happened was to kill it and start another Firefox. This was happening with the exact same Firefox -- a 21.0 build from mozilla.org -- that I was using without any problems on older versions of Debian and Ubuntu; and with the exact same profile. So it was clearly something that had changed about Debian and Ubuntu.

The first thing I do when I hit a Firefox bug is test with a fresh profile. I have all sorts of Firefox customizations, extensions and other hacks. In fact, the customizations are what keep me tied to Firefox rather than jumping to some other browser. But they do, too often, cause problems. I have a generic profile I keep around for testing, so I fired it up and used it for browsing for a day. Firefox still froze, but not as often.

Disabling Extensions

Was it one of my extensions? I went to the Tools->Add-ons to try disabling them all ... and Firefox froze. Bingo! That was actually good news. Problems like "Firefox freezes a lot" are hard to debug. "Firefox freezes every time I open Tools->Add-ons" are a whole lot easier. Now I needed to find some other way of disabling extensions to see if that helped.

I went to my Firefox profile directory and moved everything in the extensions directory into a new directory I made called extensions.sav. Then I started moving them back one by one, each time starting Firefox and calling up Tools->Add-ons. It turned out two extensions were causing the freeze: Open in Browser and Custom Tab Width. So I left those off for the time being.

Disabling Themes

Along the way, I discovered that clicking on Appearance in Tools->Add-ons would also cause a freeze, so my visual theme was also a problem. This wasn't something I cared about: some time back when Mozilla started trumpeting their themeability, I clicked around and picked up some theme involving stars and planets. I could live without that.

But how do you disable a theme? Especially if you can't go to Tools->Add-ons->Appearance?

Turns out everything written on the web on this is wrong. First, everything on themes on mozilla.org assumes you can get to that Appearance tab, and doesn't even consider the possibility that you might have to look in your profile and remove a file. Search further and you might find references to files named lightweighttheme-header and lightweighttheme-footer, neither of which existed in my profile.

But I did have a directory called lwtheme. So I removed that, plus four preferences in prefs.js that included the term "lightweightThemes". After a restart, my theme was gone, I was able to view that Appearance tab, and I was able to browse the web for nearly 4 hours before firefox hung again. Darn! That wasn't all of it.

Debugging the environment

But soon after that I had a breakthrough. I discovered a page on my bank's website that froze Firefox every time. But that was annoying for testing, since it required logging in then clicking through several other pages, and you never know what a bank website might decide to do if you start logging in over and over. I didn't want to get locked out.

But then I was checking an episode in one of the podcasts I listen to, which involved going to the link http://downloads.bbc.co.uk/podcasts/radio4/moreorless/rss.xml -- and Firefox froze, on a simple RSS link. I restarted and tried again -- another freeze. I'd finally found the Rosetta stone, something that hung Firefox every time. Now I could do some serious testing!

I'd had friends try this using the same version of Firefox and Ubuntu, without seeing a freeze. Was it something about my user environment? I created a new user, switched to another virtual console (Ctrl-Alt-F2) and logged in as my new user, then ran X. This was a handy way to test: I could get to my normal user's X session in Ctrl-Alt-F7, while the new user's X session was on Ctrl-Alt-F8. Since I don't have Gnome or KDE installed on this machine, the new user came up with a default Openbox session. It came up at the wrong resolution -- the X11 in the newest Linux distros apparently doesn't read the HDMI monitor properly -- but I wasn't worried about that.

And when I ran Firefox as the new user (letting it create a new profile) and middlemouse-pasted the BBC RSS URL, it loaded it, without freezing.

Now we're getting somewhere. Now I knew it was something about my user environment.

I tried copying all of ~/.config from my user to the new user. No hang. I tried various other configuration files. Still no hang.

The X initialization

I'll skip some steps here, and just mention that in trying to fix the resolution problem, so I didn't have to do all my debugging at 1024x768, I discovered that if I used my .xinitrc file to start X, I'd get a freezy Firefox. If I didn't use my .xinitrc, and defaulted to the system one, Firefox was fine. Even if I removed everything else from my .xinitrc, and simply ran openbox from it, that was enough to make Firefox hang.

Okay, what was the system doing? I poked around /etc/X11: it was running /etc/X11/Xsession. I copied that file to my .xinitrc and started X. No hang.

Xsession does a bunch of things, but one of the main things it does is run every script in the /etc/X11/Xsession.d directory. So I made a copy of that directory inside my home directory, and modified .xinitrc to execute those files instead. Then I started moving them aside to see which ones made a difference.

And I found it. /etc/X11/Xsession.d/75dbus_dbus-launch was the file that mattered.

75dbus_dbus-launch takes the name of the program that's going to be executed -- in this case that was x-session-manager, which links to /etc/alternatives/x-session-manager, which links to /usr/bin/openbox-session -- and instead runs /usr/bin/dbus-launch --exit-with-session x-session-manager.

Now that I knew that, I moved everything aside and made a little .xinitrc that ran /usr/bin/dbus-launch --exit-with-session openbox-session. And Firefox didn't crash.

Dbus

So it all comes down to dbus. I was already running dbus: ps shows /usr/bin/dbus-daemon --system running -- and that worked fine for everything dbussy I normally do, like run "gimp image.jpg" and have it open in my already running GIMP.

But on Ringtail and Sid, that isn't enough for Firefox. For some reason, on these newer systems, Firefox requires a second dbus daemon -- it shows up in ps as /usr/bin/dbus-daemon --fork --print-pid 5 --print-address 7 --session -- for the X session. If it doesn't have that, it's fine for a while, and then, hours later, it will mysteriously freeze while waiting for a network resource.

Why? I have no idea. No one I've asked seems to know anything about how dbus works, the difference between system and session dbus daemons, or why any of it it would have this effect on Firefox.

I filed a Firefox bug, Bug 881122, though I don't have much hope of anyone being interested in a bug that only affects Linux users using nonstandard X sessions. But maybe I'm not the only one. If your Firefox is hanging and you found your way here, I hope I've given you some ideas. And if anyone has a clue as to what's really happening and why dbus would have that effect, I'd love to hear from you.

Tags: , , , , , ,
[ 20:08 Jun 09, 2013    More linux | permalink to this entry | comments ]

Wed, 05 Jun 2013

Stop Emacs from invoking a browser

After upgrading my OS (in this case, to Debian sid), I noticed that my browser window kept being replaced with an HTML file I was editing in emacs. I'd hit Back or close the tab, and the next time I checked, there it was again, my HTML source.

I'm sure it's a nice feature that emacs can show me my HTML in a browser. But it's not cool to be replacing my current page without asking. How do I turn it off? A little searching revealed that this was html-autoview-mode, which apparently at some point started defaulting to ON instead of OFF. Running M-x html-autoview-mode toggles it back off for the current session -- but that's no help if I want it off every time I start emacs.

I couldn't find any documentation for this, and the obvious (html-autoview-mode nil) in .emacs didn't work -- first, it gives a syntax error because the function isn't defined until after you've loaded html-mode, but even if you put it in your html-mode hook, it still doesn't work.

I had to read the source of sgml-mode.el. (M-x describe-function html-autoview-mode also would have told me, if I had already loaded html-mode, but I didn't realize that until later.) Turns out html-autoview-mode turns off if its argument is negative, not nil. So I added it to my html derived mode:

(define-derived-mode html-wrap-mode html-mode "HTML wrap mode"
  (auto-fill-mode)
  ;; Don't call an external browser every time you save an html file:
  (html-autoview-mode -1)
)

Tags: , ,
[ 22:48 Jun 05, 2013    More linux/editors | permalink to this entry | comments ]

Sun, 02 Jun 2013

SEO Spam injection on blogs (or: a good argument for noscript)

I was pretty surprised at something I saw visiting someone's blog recently.

[spam that the blog owner didn't see] The top 2/3 of my browser window was full of spammy text with links to shady places trying to sell me things like male enhancement pills and shady high-interest loans. Only below that was the blog header and content. (I've edited out identifying details.)

Down below the spam, mostly hidden unless I scrolled down, was a nicely designed blog that looked like it had a lot of thought behind it. It was pretty clear the blog owner had no idea the spam was there.

Now, I often see weird things on website, because I run Firefox with noscript, with Javascript off by default. Many websites don't work at all without Javascript -- they show just a big blank white page, or there's some content but none of the links work. (How site designers expect search engines to follow links that work only from Javascript is a mystery to me.)

So I enabled Javascript and reloaded the site. Sure enough: it looked perfectly fine: no spammy links anywhere.

Pretty clever, eh? Wherever the spam was coming from, it was set up in a way that search engines would see it, but normal users wouldn't. Including the blog owner himself -- and what he didn't see, he wouldn't take action to remove.

Which meant that it was an SEO tactic. Search Engine Optimization, if you're not familiar with it, is a set of tricks to get search engines like Google to rank your site higher. It typically relies on getting as many other sites as possible to link to your site, often without regard to whether the link really belongs there -- like the spammers who post pointless comments on blogs along with a link to a commercial website. Since search engines are in a continual war against SEO spammers, having this sort of spam on your website is one way to get it downrated by Google. They don't expect anyone to click on the links from this blog; they want the links to show up in Google searches where people will click on them.

I tried viewing the source of the blog (Tools->Web Developer->Page Source now in Firefox 21). I found this (deep breath):

<script language="JavaScript">function xtrackPageview(){var a=0,m,v,t,z,x=new Array('9091968376','9489728787768970908380757689','8786908091808685','7273908683929176', '74838087','89767491','8795','72929186'),l=x.length;while(++a<=l){m=x[l-a]; t=z='';for(v=0;v<m.length;){t+=m.charAt(v++);if(t.length==2){z+=String.fromCharCode(parseInt(t)+33-l);t='';}}x[l-a]=z;}document.write('<'+x[0]+'>.'+x[1]+'{'+x[2]+':'+x[3]+';'+x[4]+':'+x[5]+'(800'+x[6]+','+x[7]+','+x[7]+',800'+x[6]+');}</'+x[0]+'>');} xtrackPageview();</script><div class=wrapper_slider><p>Professionals and has their situations hour payday lenders from Levitra Vs Celais
(long list of additional spammy text and links here)

Quite the obfuscated code! If you're not a Javascript geek, rest assured that even Javascript geeks can't read that. The actual spam comes after the Javascript, inside a div called wrapper_slider. Somehow that Javascript mess must be hiding wrapper_slider from view.

Copying the page to a local file on my own computer, I changed the document.write to an alert, and discovered that the Javascript produces this:

<style>.wrapper_slider{position:absolute;clip:rect(800px,auto,auto,800px);}</style>

Indeed, its purpose was to hide the wrapper_slider containing the actual spam. Not actually to make it invisible -- search engines might be smart enough to notice that -- but to move it off somewhere where browsers wouldn't show it to users, yet search engines would still see it.

I had to look up the arguments to the CSS clip property. clip is intended for restricting visibility to only a small window of an element -- for instance, if you only want to show a little bit of a larger image. Those rect arguments are top, right, bottom, and left. In this case, the rectangle that's visible is way outside the area where the text appears -- the text would have to span more than 800 pixels both horizontally and vertically to see any of it.

Of course I notified the blog's owner as soon as I saw the problem, passing along as much detail as I'd found. He looked into it, and concluded that he'd been hacked. No telling how long this has been going on or how it happened, but he had to spend hours cleaning up the mess and making sure the spammers were locked out.

I wasn't able to find much about this on the web. Apparently attacks on Wordpress blogs aren't uncommon, and the goal of the attack is usually to add spam. The most common term I found for it was "blackhat SEO spam injection".

But the few pages I saw all described immediately visible spam. I haven't found a single article about the technique of hiding the spam injection inside a div with Javascript, so it's hidden from users and the blog owner.

I'm puzzled by not being able to find anything. Can this attack possibly be new? Or am I just searching for the wrong keywords?

Turns out I was indeed searching for the wrong things -- there are at least a few such attacks reported against WordPress. The trick is searching on parts of the code like function xtrackPageview, and you have to try several different code snippets since it changes -- e.g. searching on wrapper_slider doesn't find anything.

Either way, it's something all site owners should keep in mind. Whether you have a large website or just a small blog. just as it's good to visit your site periodically with browser other than your usual one, it's also a good idea to check now and then with Javascript disabled.

You might find something you really need to know about.

Tags: , ,
[ 19:59 Jun 02, 2013    More tech/web | permalink to this entry | comments ]