Skip to content

Nearly Free Speech

I've used 1&1 since I started mucking about on the web; they had a cheap plan for $3/month with one domain name and a simple LAMP stack. But the price has been going up (now $5/month; still comparatively cheap!), and I'm starting to chafe at the limitations (no SSH shell access, proprietary 404 pages, no languages beside PHP) and I didn't want to shell out for my own virtual server (Rackspace goes as low as $11/month but I'm really cheap). So I was overjoyed when I found Nearly Free Speech.

Continue reading ›

New Amazon Advertising API

Just got an email from Amazon reminding me that "As part of our continued effort to ensure that the Product Advertising API is an efficient and effective advertising tool, we’ve identified opportunities to streamline the API", which is their way of saying that the API exists to make them money. Anything that doesn't serve that purpose is eliminated, however nice it might be for me. Their right, even if they're not right. I've already taken into account the major changes. The only thing is to change the API version to the most recent; in the aws_signed_request routine, change the $params["Version"] line to read $params["Version"] = "2011-08-01"; and that should be it.

Writing CGI scripts

nearlyfreespeech runs with safe mode and safe_mode_gid on, so you can't run shell scripts or other cool things. Usually that's not an issue, but if you do, they let you run CGI scripts, in any of a number of languages. You just have to treat it as a shell script, with a shebang notation of the proper language. There are a few caveats that took me a day to find out:

  1. The correct program is /usr/local/bin/php-cgi (or whereever your server puts PHP), not /usr/local/bin/php. That is the command-line interpreter, which does not output the headers. You can manually do echo "Content-type: text/html\n" etc., followed by a blank line, but who wants to try to debug that?
  2. The script has to be executable. You get a 500 Server Error otherwise. Do a chmod +x scriptname.cgi.
  3. Scripts need the appropriate file and directory permissions to write to the server. Changing the permissions of the server directory is probably too insecure (though for safe mode it's the only way); it's better to set-uid the script, but then keep it under wraps.

So a sample CGI script would be:

#!/usr/local/bin/php-cgi
<?php echo "Hello, world"; ?>

in an executable file with a .cgi extension.

Note that FTP and SFTP can't set the setuid bit, so that if you upload the file (or edit it with an FTP-aware editor like Notepad++), you need to chmod 477 scriptname.cgi again.

Things I Learned About .htaccess, part 2

I've learned some things about .htaccess, but mostly I've learned that programming it is deep black magic. The most important thing is "Don't use mod-rewrite unless you absolutely need to". All the fancy stuff is better off done by the PHP (or whatever language you're using) code.

Don't do:

RewriteEngine On
RewriteBase /
RewriteRule ^([^/\.]+)/$ /index.php?main=$1&part=$1 [QSA,L]
RewriteRule ^([^/\.]+)/([^/\.]+)$ /index.php?main=$1&part=$2 [QSA,L]

to map your site to your index page; do:

FallbackResource /index.php

And in index.php parse the $_SERVER['REQUEST_URI'] to get your page/subpage arguments. Much easier to debug!

And to use FallbackResource you need to be running Apache 2.2, so get a good web host.

Moving the Blog Again

I'm working on moving bililite.com to nearlyfreespeech.net; it's cheaper, more reliable and more hacker-friendly than 1&1. I'll write a post with my experiences and reasons later. But for now just the blog has moved to bililite.nfshost.com/blog, with the plan to move the domain registration for bililite.com to nearlyfreespeech when everything is working and then return the blog to bililite.com/blog. Moving it was straightforward, as I've done it before, but there are some subtleties: nearlyfreespeech runs with safe mode and safe_mode_gid on, so you have to watch file and directory permissions; SaraPin explains exactly how. WordPress loads with the group me and nearlyfreespeech's webserver runs with the group web, so you need to SSH into the account and change the WordPress directory with chgrp -R * web. The file permisssions should be 664 (writeable to self and group, readable to all) and the directory permissions should be 775 (writeable and executable to self and group, executable to all; under UNIX, getting a file from a directory is "executing" it), but the default WordPress installation does that.

If you don't know what that means, you probably shouldn't be using a d.i.y. host like nearlyfreespeech.

And now it works!

Almost. SexyBookmarks's images aren't loading when I use the new code, so I went back to the old version. It slows the page load down anyway, so I may take it off entirely.

And the rest of the bililite site is still at the old host, and some of the sample code (in /blog/blogfiles) uses that, so for now I have a line in my .htaccess to refer it back: RedirectMatch /blog/blogfiles(.*) http://bililite.com/blog/blogfiles$1.

Awesome

My office manager gave me this as a Christmas present. I have a great job.

Nice Javascript library: underscore.js

Modern javascript provides a host of cool functional-programming toys like forEach and reduce, but I'm stuck with IE* at work, which does not. jQuery fills some of those gaps (it has $.each and $.map) but not everything one would want.

Enter underscore.js, which bills itself as "the tie to go along with jQuery's tux."

It doesn't modify any native objects, requiring you to wrap them as _([1,2,3]).map(function(x) {return 2*x;}), which returns [2,4,6]. Chaining has to be explicitly enabled, _([1,2,3]).chain().map(function(x) {return 2*x;}).reduce(function(memo, num){ return memo + num; }, 0) returns 12.

Looks useful.

New jQuery Plugin: showPassword

I put yesterday's unmask password plugin together with the code to automatically create a checkbox to control it, and removed the dependency on jQuery UI.

Download the code.

Example

<input type="password" id="password"/>
$('#password').showPassword('Show Characters as I Type');

Use

$('[type=password]').showPassword(string) creates a checkbox as above with string as the label. If the checkbox is checked then the password field is unmasked. $('type=password').showPassword(true) unmasks the field directly, and $('type=password').showPassword(false) restores masking.

Unmask Password Plugin

I hate password masking—hiding what I'm typing to prevent someone from looking over my shoulder at my passwords. I know when I'm in public and when I'm alone in the house, and it should be my choice to actually see what I'm typing, since it has to have some nonsense combination of characters. Even Jakob Nielsen agrees with me.

The logical thing to do is to have a checkbox that would show the characters, and the easiest way to do that is to change the type of the input element from password to text.

For most browsers, this is nontrivial but doable. You have to detach the element first in order to change its type. But in Internet Explorer, there's no way to change it. One solution is to create a new input element with type text and copy all the other attributes into it, but that seems like overkill. All we need is a way for the user to see what he is typing, so a tooltip-like overlay would work.

This is what I came up with (note that it requires jQuery UI position:

<input type="password" id="password"/>
<label><input type="checkbox" id="check"/> Show characters as I type</label>
try{
  $('<input type="password">').detach().attr('type', 'text');
  $.fn.showPassword = function(shouldShow){
    var type =  shouldShow ? 'text' : 'password';
    return this.each(function(){
      /* from http://stackoverflow.com/questions/540851/jquery-change-element-type-from-hidden-to-input */
      marker = $('<span />').insertBefore(this);
      $(this).detach().attr('type', type).insertAfter(marker);
      marker.remove(); 
    });
  };
}catch(e){
  $.fn.showPassword = function(shouldShow){
    return this.each(function(){
      if (shouldShow){
        var span = $(this).siblings('.showPassword');
        if (span.length > 0){
          span.show();
        }else{
          span = $('<span>').addClass('showPassword').css({
            opacity: 0.9,
            background: 'white',
            position: 'absolute',
            fontFamily: 'sans-serif',
            paddingLeft: '2px'
          }).position({
            at: 'left bottom',
            of: this,
            my: 'left top'
          }).text(this.value).insertBefore(this);
          $(this).keyup(function(){ span.text(this.value); });
        }
      }else{
        $(this).siblings('.showPassword').hide();
      }
    });
  };
}
$('#check').change(function(){
  $('#password').showPassword($(this).is(':checked'));
});

Try this in Internet Explorer as well as a standards browser. The details are different, but the functionality is the same.

HTML5 validator plugin

tl;dr

Download the code. Use $.validateHTML5(callback), where callback (result, data) is a function that is called with the result, a string that can be "valid" if the page validated, "invalid" if it did not, "warning" if it validated but is "in some way questionable", or "not validated" if some error occurred. data is the actual JSON output from the validator.

Continue reading ›