Shallow Thoughts : : Jun
Akkana's Musings on Open Source Computing and Technology, Science, and Nature.
Sat, 29 Jun 2013
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
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
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?
- Start with small but complete working examples to introduce each
new hardware component.
- Provide complete .ino files, not just code snippets.
- Skip pushbuttons, but do try to cover AnalogInOutSerial and PWM output.
Or at least have printed handouts explaining the PWM outputs and LED fading.
- Turnkey kits are good: the less "connect the blue wire to pin 7,
the green one to pin 8" the better. For things like cars, I'd
like something already wired up with battery and shield,
"Just add Arduino".
- Keep a closer eye on the afternoon projects -- try to make sure
each team has something they're proud to show off.
Thanks again to the great volunteers! I'm looking forward to giving
this workshop again.
Tags: robots, arduino, education, hardware, programming, maker
[
20:36 Jun 29, 2013
More education |
permalink to this entry |
]
Sun, 23 Jun 2013
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: arduino, hardware, maker
[
21:43 Jun 23, 2013
More hardware |
permalink to this entry |
]
Thu, 20 Jun 2013
Homeowner tip of the day:
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.
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: misc
[
22:49 Jun 20, 2013
More misc |
permalink to this entry |
]
Sat, 15 Jun 2013
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: shell, zsh, xchat
[
21:31 Jun 15, 2013
More linux/cmdline |
permalink to this entry |
]
Sun, 09 Jun 2013
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: firefox, mozilla, debugging, linux, debian, ubuntu, dbus
[
20:08 Jun 09, 2013
More linux |
permalink to this entry |
]
Wed, 05 Jun 2013
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: emacs, editors, html
[
22:48 Jun 05, 2013
More linux/editors |
permalink to this entry |
]
Sun, 02 Jun 2013
I was pretty surprised at something I saw visiting someone's blog recently.
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: spam, tech, web
[
19:59 Jun 02, 2013
More tech/web |
permalink to this entry |
]