Firefox Sync Server

Type
Status

Today I set up a Firefox Sync server.

I use Firefox on my computer at work and at home. I wish that there was a way to synchronize my browsing history and tabs and whatnot.

Well, it turns out there is. If you go to the Tools menu, you can set up sync.

But I was like "Dude there's no way I'm going to do that. I don't want my private data living up on some server for anyone to see."

Well, it turns out that:
1) The data is encrypted before it's sent to the server, but more importantly:
2) You can set up your own server!

Here's their instructions on setting up a sync server. Note that you also have to set up a registration server.

They wrote them as separate parts, and I'm sure that they have it nicely partitioned into separate databases and stuff, but I just created one database for the sync server, and then added the one extra table from the registration server instructions.

They act like it's very hard to set up the sync server, and they "strongly recommend" setting up the minimal sync server. I respectfully disagree.

1. Their instructions for the minimal server will leave you with a configuration in which apache can write to a directory that code is executed out of.
2. The regular server is quite easy to set up if you have any familiarity with webapps.
3. The minimal server doesn't do user registrations. Instead, it gives you a script to add users. However, I couldn't figure out how to instruct firefox to log in when I'd created my account with this script. I needed a "sync key" and I don't believe I was given one. By contrast, with the regular server, I created my account through the browser's interface and it totally gave me a sync key.

So, now I've got my very own sync server. I can sync my firefox with peace of mind.

And if you want to use my server, here's what to do:
In Firefox 4 or 5, go to Tools > Sync setup. Say you want to create a new account. Say you want to use a custom server. That server is: https://weave.pirateship.org/

Fill in your username and password and you are golden. Don't worry, I will not be able to read your information.

Your rating: None Average: 3.5 (4 votes)

Updating diaspora

Updated: Mon, Jul 11, 2011 - 11:05pm
Type
Status
Concerning

Okay, I just updated my Diaspora server to the latest code. It's got some fancy updates like a "like" button.

I just wanted to make a quick note on updating it. This probably applies to any Rails app that uses Jammit.

After updating the code, make sure to delete the precompiled javascript and css files. Otherwise, you'll be running the new templates with the old css/js, and things will break.

The built assets live under public/assets. It's okay to delete them. Jammit will rebuild them from public/javascripts and public/stylesheets, based on the specification in config/assets.yml.

I should make sure that this instruction gets onto the Diaspora wiki.

Another quick note: I was finding that, in Firefox, the autoresize jquery plugin wasn't working correctly. It turns out that it was the fault of neither Firefox nor autoresize. It was the fault of the It's All Text firefox plugin I was running. I should make sure that the It's All Text people and the autoresize people are aware of this, but I'm not sure there's anything either of them can do.

Your rating: None

Wireless Mesh Networking

We've seen censorship of the internet in many countries lately. We're seeing poor regulation of the internet in the US. In order to fight this trend, we need to have the people own the network.

Enter Wireless Mesh Networking. People can buy low-cost wifi routers and keep them in their homes. Flash them with a special firmware based on OpenWRT and they can become a mesh network of their own. Communicate with friends and neighbors over the radio.

There have been several wireless mesh networking projects in many cities all around the world. I attended the Wireless Battle Mesh in Spain, so that I could figure out how to add Ann Arbor to that list.

Soon, there will be a real website about this. Until then, please read our mailing list.

Also, on the plane on the way back from the conference, I wrote up everything I knew into a handy guide.

Your rating: None Average: 5 (3 votes)

Vim modelines

Type
Status
Concerning

I edit a few different types of files with a few different indentation styles. Now, my favorite text editor is vim, and that supports using a config file to set your indentation style, but since I use a few of them, one config file won't work for me. Now, I'm sure you could also set a different style per filetype -- for example, python indents two spaces, C uses tabs displayed as four spaces. But that doesn't work, because different projects sometimes choose different styles, even though they use the same type of file.

Well, it turns out that you can store your preferred indentation setup (or any other vim commands) right there in the file you're working on. I've been aware of this for awhile, because I've seen the commands in files I've worked on. But I always forget the exact syntax of it. I usually end up looking for a file that has this, and then copying it out and tweaking it.

But now I know the magic word, so I could google it. These things are called "modelines". Here's a comprehensive howto on the vim wiki:
Modeline Magic

In short, here's how to do it (in a C file):

  1. // vim: ts=4:noet:sw=4

That's "tabstop = 4", "do not expand tabs (i.e. use tabs not spaces)", and "shift by four characters when using the >> command".

There. Now I know how to look this stuff up.

Your rating: None Average: 2.7 (3 votes)

Unattended DVD Ripping

Updated: Sun, Feb 14, 2010 - 2:42am
Type
Status
Concerning

I recently purchased a large number of movies from a very cool video store which was closing. It was a terrible disaster. Sure, I got a bunch of DVDs from it. But I did not gain access to any new movies -- I could have rented all these any time I wanted. Instead, the amazing collection in the possession of the video store is now split up in the hands of a bunch of individuals like me. It is not a collection anymore, and is far, far less useful to the community.

But this is a technical blog, not a library science blog. So where could I be headed with this?

Well, I don't want to sit around and import all these DVDs by hand. I want to set up a machine so that I can just drop a DVD in there and walk away, and have it rip the DVD for me. I got a headless computer and set it on my network. It's got a DVD drive, a large hard drive, and a samba server.

I set up ivman to respond to the dvd insertion event and to fire a script.

I edited /etc/ivman/IvmConfigActions.xml. Here is a stripped-down version of that file:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <ivm:ActionsConfig version="0.2" xmlns:ivm="http://www.eikke.com/ivm">
  3.  
  4. <!-- This is what I added -->
  5. <ivm:Match name="hal.volume.disc.is_videodvd" value="true">
  6. <ivm:Option name="exec" value="/opt/ripdvd.sh '$hal.block.device$'" />
  7. </ivm:Match>
  8.  
  9. </ivm:ActionsConfig>

I based that entry off of a sample that was left in the comments of the Debian ivman package's version of IvmConfigActions.xml. The comment shows how to mount the dvd and then play it with mplayer.

My version of the file runs my ripdvd.sh script, which runs Handbrake to rip the dvd. I also decorate the script with some beeps to let me know that it's working, and eject the disc when done.

Note that, while Debian provides a Handbrake package, I installed it from source instead. In building it, it downloads the source code of all of its codec dependencies and builds them.

Here's the text of my ripdvd.sh script.

  1. #!/bin/sh
  2.  
  3. # Acknowledge that we are starting
  4. beep -f 1400 -l 250
  5.  
  6. DVD="$1"
  7. HANDBRAKE=/opt/handbrake/bin/HandBrakeCLI
  8. LOG="logger -p daemon.info -t ripdvd.sh "
  9. OUTDIR="/var/Data/Movies/Imports/"
  10.  
  11. function beep_success() {
  12. beep -f 750 -l 80 -r 5 -D 20
  13. }
  14.  
  15. function beep_failure() {
  16. beep -f 200 -l 900
  17. }
  18.  
  19. function dvdrip() {
  20. $LOG "Beginning rip of $DVD"
  21. local LABEL=`file -s "$DVD" | cut -f 2- -d "'" | cut -f 1 -d "'" | sed -e 's/ *$//'`
  22. $LOG "$DVD contains $LABEL"
  23. $LOG $HANDBRAKE --verbose 9 --input "$DVD" --longest --output "$OUTDIR/$LABEL.avi" --size 600 --native-language eng --aencoder lame
  24. $HANDBRAKE --verbose 9 --input "$DVD" --longest --output "$OUTDIR/$LABEL.avi" --size 600 --native-language eng --aencoder lame 2>&1 > $OUTDIR/HandBrake.log
  25. local STATUS="$?"
  26. $LOG "Finished importing $LABEL from $DVD (status = $STATUS)"
  27. return $STATUS
  28. }
  29.  
  30. if dvdrip; then
  31. beep_success
  32. else
  33. beep_failure
  34. fi
  35.  
  36. eject

I have also attached the ripdvd.sh script for download.

Your rating: None Average: 4.5 (2 votes)
AttachmentSize
ripdvd.sh.txt919 bytes

It's All Text!

Type
Status
Concerning

One of my favorite Firefox extensions these days is It's All Text!. This extension lets you use alternative text editors to edit the text in text boxes.

Now, big wimps like to edit their text in WYSIWYG editors. Not me. I like to use vim.

Okay, so "It's All Text!" allows us to give a command line to start a text editor. What command do we give to start vim?

Well, we could use gvim. But I vastly prefer to run vim in my normal gnome terminal.

Therefore, I created a script, /opt/termvim/termvim, which reads:

  1. #!/bin/sh
  2.  
  3. gnome-terminal --command="vim $@"

After making it executable, I can then set my editor in firefox by going to Tools > It's All Text! > Preferences. For "Editor", I set /opt/termvim/termvim.

Boom. I can use vim on the web.

Your rating: None Average: 4.5 (2 votes)

Fun with acpid

Updated: Fri, Feb 12, 2010 - 2:29am

It doesn't seem glamorous, but it is indeed possible to have fun with acpid. acpid is a daemon that sits and listens for acpi events from the kernel. When it gets an event, it fires the rules you have configured.

Okay, so what's the use?

Let's start with a simple one. On my laptop, when it's unplugged and I shut the lid, I want the laptop to suspend. Now, these days, I'm using Ubuntu on my laptop. Ubuntu is configured with this behavior automatically. But I've found that it doesn't always work. Also, even when it works, it can be slow. The sleep-when-lid-is-shut behavior is controlled by gnome-power-manager. It seems strange to me that we would have this behavior be controlled by something so far up the stack. X and gnome may have a lot on their minds. Also, I may not even be running X.

Fortunately, acpid is much lower in the stack. It'll be running, X or no.

So we can program the sleep behavior into the acpid config files.

In Ubuntu, we are interested in the directory /etc/acpi. There are a bunch of scripts there that are fired in response to acpi events. The ones we are interested in are /etc/acpi/lid.sh and /etc/acpi/power.sh. They respond to the lid and the AC adaptor, respectively. (In Arch Linux, there is only one script, /etc/acpi/handler.sh. Instead of editing files, you'll be editing different parts of that file).

You'll notice that /etc/acpi/lid.sh calls /etc/acpi/local/lid.sh.pre before it runs, and /etc/acpi/local/lid.sh.post when it's done. We will edit the "pre" file, so that we don't get in the way of new versions of acpid from the distro. Note that these "pre" and "post" scripts must be marked as executable, or the main scripts will ignore them and not run them.

This is what I put in the lid.sh.pre script:

  1. #!/bin/sh
  2.  
  3. grep -q closed /proc/acpi/button/lid/*/state
  4. if [ $? = 0 ] ; then
  5. grep -q off-line /proc/acpi/ac_adapter/*/state
  6. if [ $? = 0 ] ; then
  7. pm-suspend
  8. fi
  9. fi

With this script, when the lid is shut, it will check if the power is plugged in. If not, it'll put the computer to sleep. We also need to do it the other way: When the power plug is removed, we need to check if the lid is shut.

For this, we look at the power.sh script, which fires when the power plug is removed or put in.

Unfortunately, ubuntu does not provide a power.sh.pre and power.sh.post. That means that when we make changes to this file, we may have to be a little careful when we update acpid.

The first thing I did was to add lines to call power.sh.pre and power.sh.post to the power.sh script.

My power.sh script now reads:

  1. #!/bin/sh
  2.  
  3. test -f /usr/share/acpi-support/key-constants || exit 0
  4.  
  5. . /usr/share/acpi-support/policy-funcs
  6.  
  7. [ -x /etc/acpi/local/power.sh.pre ] && /etc/acpi/local/power.sh.pre
  8. if [ -z "$*" ] && [ `CheckPolicy` = 0 ]; then
  9. exit;
  10. fi
  11.  
  12. pm-powersave $*
  13. [ -x /etc/acpi/local/power.sh.post ] && /etc/acpi/local/power.sh.post

Putting these lines in here allows me to put the main part of the code in /etc/acpi/local/power.sh.pre. The text of this is exactly the same as the text of lid.sh.pre.

So that was pretty fun, right? I've got a couple more things here.

I had a pretty old computer that I was working on once. I often found that Firefox would run away with the processor and cause such high load that it would take a minute or more just to get access to a console to kill firefox.

So I used acpid to hook up the power button to automatically kill firefox. When firefox runs away with the cpu, I hit the power button. That runs the /etc/acpid/powerbtn.sh script.

Just like with power.sh, this does not have the "pre" and "post" hooks. Therefore, I add those hooks. Here is my powerbtn.sh script:

  1. #!/bin/sh
  2. # /etc/acpi/powerbtn.sh
  3. # Initiates a shutdown when the power putton has been
  4. # pressed.
  5.  
  6. # Skip if we just in the middle of resuming.
  7. test -f /var/lock/acpisleep && exit 0
  8.  
  9. [ -x /etc/acpi/local/powerbtn.sh.pre ] && /etc/acpi/local/powerbtn.sh.pre
  10. # If gnome-power-manager, kded4, dalston-power-applet or xfce4-power-manager
  11. # are running, let them handle policy This is effectively the same as
  12. # 'acpi-support's '/usr/share/acpi-support/policy-funcs' file.
  13.  
  14. if pidof gnome-power-manager kded4 dalston-power-applet xfce4-power-manager > /dev/null; then
  15. exit
  16. fi
  17. [ -x /etc/acpi/local/powerbtn.sh.post ] && /etc/acpi/local/powerbtn.sh.post
  18.  
  19. # If all else failed, just initiate a plain shutdown.
  20. /sbin/shutdown -h now "Power button pressed"

Then, in /etc/acpi/local/powerbtn.sh.pre, I add, simply,

  1. #!/bin/sh
  2. pkill firefox

So there you have it. Fun with acpid. That was fun, right?

Your rating: None

Drupal intra-linking problems solved

Updated: Thu, Feb 11, 2010 - 3:37pm
Type
Status
Concerning

Sometimes, when using Drupal, I find that I want to link to some of my older posts. However, I often have a couple of development checkouts of my site. Consider the case where I have the live site, which can be reached at http://iheartryan.com/, and I have a development checkout, http://localhost/iheartryan/. Now, say I'm trying to link to my Rhythmbox Playlist Folders post. How should I make this link? I have a couple choices:

  1. http://iheartryan.com/post/rhythmbox-playlist-folders
  2. /post/rhythmbox-playlist-folders

Neither of these will totally work for my purposes. For example, let's say I choose to make a full, absolute path, like #1 above, then when I look at this page in my development checkout, the link will point to the post on the live server. I can't navigate around internally on my dev checkout.

Choice #2 might help with that problem. It is a link to the post on whatever server I happen to be looking at. The problem is that my dev checkout has a different path. So choice #2 will give us a link to: http://localhost/post/rhythmbox-playlist-folders. What we need is a link to http://localhost/iheartryan/post/rhythmbox-playlist-folders.

I have a solution that will cover most of the cases. If you implement this solution on your site, then you can just make a link to /post/rhythmbox-playlist-folders, and it will be translated to /post/rhythmbox-playlist-folders, so it will work on any checkout.

To implement this solution, we will make some changes in a module and some changes in your site's theme.

First, the module. We need to have a module that implements hook_nodeapi. For all the sites I do, I always end up with some custom modifications, so let's say we have a module called "custom". (Technically, I could take the changes I'm about to present and release it as a module, but it is incomplete without the theme changes, and it doesn't seem like it should be a whole module release). In our custom module, I will implement hook_nodeapi:

  1. function custom_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  2. switch($op) {
  3. case 'view':
  4. $node->content['body']['#value'] = preg_replace_callback(
  5. '/<([^>]*)(src|href)="([^"]*)"/i',
  6. "_custom_twiddle_links",
  7. $node->content['body']['#value']);
  8.  
  9. break;
  10. }
  11. }
  12.  
  13. function _custom_twiddle_links($matches) {
  14. $url = $matches[3];
  15. if (preg_match('|^[a-z][^:]*://|', $url)) {
  16. // It's an absolute url. Return the whole thing as given.
  17. $retval = $matches[0];
  18. } elseif (strpos($url, "/") === 0) {
  19. // It's an absolute url on this host. Fix it with the right base path.
  20. $retval = "<{$matches[1]}{$matches[2]}=\"".base_path().ltrim($matches[3],"/")."\"";
  21. } else {
  22. // It's a relative url. Return the whole thing as given.
  23. $retval = $matches[0];
  24. }
  25.  
  26. return $retval;
  27. }

This will replace the links when displaying nodes.

There's still the problem of blocks. That's why we edit the site's theme.

We edit blocks.tpl.php to start with this:

  1. <?php
  2. /**
  3.  * If a link starts with /, it should be relative to the base_path of the site,
  4.  * not to the actual server root.
  5.  */
  6. if (!function_exists("_block_twiddle_links")) {
  7. function _block_twiddle_links($matches) {
  8. $url = $matches[3];
  9. if (preg_match('|^[a-z][^:]*://|', $url)) {
  10. // It's an absolute url. Return the whole thing as given.
  11. $retval = $matches[0];
  12. } elseif (strpos($url, "/") === 0) {
  13. // It's an absolute url on this host. Fix it with the right base path.
  14. $retval = "<{$matches[1]}{$matches[2]}=\"".base_path().ltrim($matches[3],"/")."\"";
  15. } else {
  16. // It's a relative url. Return the whole thing as given.
  17. $retval = $matches[0];
  18. }
  19.  
  20. return $retval;
  21. }
  22. }
  23.  
  24. if ($block->module == 'block') {
  25. $block->content = preg_replace_callback(
  26. '/<([^>]*)(src|href)="([^"]*)"/i',
  27. "_block_twiddle_links",
  28. $block->content);
  29. }
  30. ?>

This will fix the links for blocks.

That's the best I can do. This solution is not elegant. Perhaps there can be a a fix at the Drupal core level, so that we won't have to apply these dirty hacks. Perhaps this hack could be adjusted to have a token like [BASE_PATH], instead of working on all server-absolute links.

Perhaps there could even be a solution using the existing token module. Please tell me if you know of one.

Your rating: None Average: 4 (3 votes)

utf8 lessons

Type
Status

The other day, I was working on a Drupal site. I based the theme for the site on the Zen theme (ver 1.1).

I was experiencing a very strange problem: I could not save any of the changes I made on the theme configuration page. I tried to change the logo. I tried to make it display the slogan. Nothing worked.

I started editing the database by hand, throwing serialized php arrays in there to set the settings I wanted. I watched in horror as I SELECTed the row, loaded the page, and SELECTed the row again, only to find that somehow my settings had been overwritten with the defaults.

"Is this some bug in the zen theme?" I thought. If so, it would be pretty major. Someone surely would have caught this by now.

No. No it wasn't. It turns out that my mysql database was using latin1 encoding rather than utf8. The settings for the theme included a fancy unicode character as the "breadcrumb separator". This caused the database to freak out and throw nonsense into the "variable" table. When I inspected the SELECT statements carefully, I found that the edit I made by hand did not get faithfully transferred into the database. This caused the serialized php array to be invalid. Drupal then helped me by sticking the default values in there, just to have something that made sense.

latin1 encoded datbases cause nothing but problems. utf8 databases have nothing but solutions.

So I dumped my data, dropped the database, recreated it using utf8 explicitly, and then reloaded my data. I was saved.

(this was the create-database syntax I used.

  1. CREATE DATABASE cooldrupaldatabase CHARACTER SET utf8;

Okay, but why? Why do I need to set that explicitly. We live in a utf8 world. Why would utf8 be the default?

It turns out that I had solved this problem awhile ago on another computer, so you'll have to excuse me for not having the links anymore.

Debian feels that backwards compatibility is the most important thing with their mysql package. They don't switch the default to utf8 because this will somehow break backward compatibility with debian systems that have been running for a long time? I guess? This is what they say. Ubuntu carries forward the debian mysql package, including this default setting.

So, to fix it, you can add a file to your /etc/mysql/conf.d that tells it to default to utf8. I have attached the file. Once again, I'm sorry that I forgot where I got it from.

Your rating: None Average: 4.3 (4 votes)
AttachmentSize
utf8.cnf348 bytes

Rhythmbox daap download queue

I sometimes use rhythmbox to download music from other people's daap shares. I wish I had a better interface to the download queue. Right now, there's just a progress bar. I want to see what songs are being downloaded. If a share suddenly goes down, I want to be able to delete those things from the queue without stalling the rest of it. Or set things to pause and resume later when the share comes back online.

Your rating: None Average: 5 (2 votes)