Archive for August, 2009

Applescripted airport connection

Monday, August 31st, 2009

My university uses a closed network connection available in all its buildings. To connect on my Mac I have to set up a a network each time. This only entails

  1. Clicking on the airport symbol
  2. Selecting Other...
  3. Typing in the network name
  4. Selecting LEAP
  5. Entering my username and password

The wireless on my older mac laptop is some what weak so repeating these few steps is tedious and worth script (only my username is ever remembered even after repeated connections).

Here’s a script to connect to a hard-coded network with a hard-coded username (the password of course is not hard-coded):


property passwd : ""
set network_name to "NYU-ROAM2"
set user_name to "abc123"
set results to do shell script "airport -s " & network_name
if results does not start with "No scan results for network" and results is not equal to "No networks found" then
	set passwd to text returned of (display dialog "Username:
" & user_name & "
Password:" default answer passwd default button 2 with icon 2 with title "Airport Roam-o-matic" with hidden answer)
        set results to do shell script "airport -A" & network_name & " --password=\"<" & user_name & "/" & passwd & ">\" 2>&1"
        if results starts with "Error" then
                display dialog "Could not connect to " & network_name & ".

Probably the password you entered did not match your username: " & user_name & "." buttons {"OK"} default button 1 with icon 0 with title "Airport Roam-o-matic"
        end if
else
        display dialog network_name & " network not found." buttons {"OK"} default button 1 with icon 0 with title "Airport Roam-o-matic"
end if

Note: My network lets me fake a LEAP username and password using this <username/password> WEP password.

Note: For more general use just replace the first two lines with:


set network_name to text returned of (display dialog "Enter the network name:" default answer "" default button 2 with icon 2 with title "Airport Roam-o-matic")
set user_name to text returned of (display dialog "Enter your username:" default answer "" default button 2 with icon 2 with title "Airport Roam-o-matic")

Update: I added passwd as a property so that it is remembered. Also, I made the prompt contain the username and look a little prettier.

Note: If you get an error like sh: airport: command not found, then you’ll need to run this in Terminal.app:


sudo ln -s /System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport /usr/sbin/airport

Search current Safari selection on wikipedia etc.

Friday, August 21st, 2009

I love SafariSIA, but to shave even more seconds off a search query I’ve made the following applescript which uses the current selection on the current safari page and searches that as a query on wikipedia (or whatever site you’d like to change it to):



-- some pieces adapted from
-- http://scriptbuilders.net/files/safariselectiontoscripteditordebugger1.0.1.html

-- If Safari isn't running, notify and terminate.
tell application "System Events"
	if (exists process "Safari") is false then
		display dialog "Safari isn't running. The script will now terminate." buttons ¬
			{"OK"} default button 1 with icon 0
		return
	end if
end tell

tell application "Safari"
	-- If no document, notify and terminate.
	if (exists document 1) is false then
		display dialog "No Safari document was found. The script will now terminate." buttons ¬
			{"OK"} default button 1 with icon 0
		return
	end if
	
	-- Attempt to get the selected text. Notify and terminate if no selection.
	try
		set selected_text to (do JavaScript "getSelection()" in document 1) as string
		if selected_text is "" then
			error
		end if
	on error
		-- Advise user to copy and paste text into new script document 'cause somethin' failed.
		set selected_text to text returned of (display dialog "Safari was unable to obtain the selected text. Copy and paste " & ¬
			"it into the new document which has been created in Script Editor." buttons ¬
			{"OK"} default answer "" default button 1 with icon 1)
		
	end try
	
	-- construct url with selected text as query
	set theURL to "http://www.wikipedia.org/search-redirect.php?search=" & selected_text & "&language=en&go=++%3E++&go=Go"
	make new document at end of documents with properties {URL:theURL}
end tell

Change the set theURL to ... line to whatever site you’d like to search. For example:

Google Images:


set theURL to  "http://images.google.com/images?q="&theURL&"&hl=en&btnG=Search+Images"

Google Maps:


http://maps.google.com/maps?client=safari&rls=en&q="&theURL&"&oe=UTF-8&um=1&ie=UTF-8&sa=N&hl=en&tab=wl

English to spanish dictionary look up on WordReference:


set theURL to  "http://www.wordreference.com/es/translation.asp?tranword="&theURL

Mininova (sorted by number of seeds):


set theURL to "http://www.mininova.org/search/"&theURL&"/seeds"

Printable Drink Coasters

Monday, August 17th, 2009

Why bother buying expensive drink coasters or stealing cardboard ones from bars? Print out a few of my printable drink coasters whenever you need to protect your important furniture. Currently there are two styles:

Circle:

Printable circle drink coaster

Square:

Printable square drink coaster

Note: Try coloring these in with crayons.

Update: Here’s another design by request.

Star:

Printable star drink coaster

Update: I made a pdf with two circle, one square and one star coasters ready for printing:

Pad images to fit 4 by 6 photo paper bash script using imagemagick

Sunday, August 16th, 2009

I was a little dismayed that I couldn’t use my previously mentioned applescript to pad images with colors other than black. A shrewd observer will also notice that the Image Events suite resamples when it pads resulting in some annoying re-anti-aliasing.

I wrote the following bash script to the same task as the applescript from the command line:


#!/bin/bash

USAGE="Usage: $0 [--replace] [--padcolor=color] ratio imagefile(s)
  ratio              is a float equal to long dimension / short dimension to pad 
                     to fit a 4\"x6\" card, divide 6 by 4 giving ratio = 1.5
  --replace or -f    option to overwrite original images with padded versions,
                     default is to preppend 'pad-[ratio]-' to each naee
  --padcolor= or -c= option to change pad color from default black. Takes a
                     color can be any Imagemagick color or hex color:
                     (See http://www.imagemagick.org/script/color.php)
"
if [ "$#" == "0" ]; then
  echo "$USAGE"
  exit 1
fi

replace=false
if [ "$1" == "--replace" -o "$1" == "-f" ]
then
  echo "Overwriting existing image files..."
  replace=true
  shift
fi

padcolor="black"
if [ `echo "$1" | grep "^\(--padcolor\)\|\(-c\)="` ]
then
  padcolor=`echo "$1" | sed "s/^.*=//"`
  shift
  echo "Using $padcolor as pad color..."
fi

ratio=`echo "$1" | grep "^[0-9]*\.\?[0-9]\+$\|^[0-9]\+\.$"`
if [ "$ratio" == "" ]
then
  echo "$USAGE"
  exit 2
fi
shift
while (( "$#" )); do
  image="$1"
  dir=`dirname "$image"`
  base=`basename "$image"`
  if ! $replace 
  then
    base="pad-$ratio-$base"
  fi
  if wh=`identify -format "%w %h" "$image" 2>/dev/null`
  then
    width=${wh%% *}
    height=${wh#* }
    if [ $height -gt $width ]
    then
      # vertical
      long=`echo "$height/$width > $ratio" | bc -l`
      if [ $long -eq "1" ] 
      then
        # taller than ratio
        newwidth=`echo "$height/$ratio" | bc -l`
        newwidth=`echo "($newwidth+0.5)/1" | bc`
        newheight="$height"
      else
        # shorter than ratio
        newwidth="$width"
        newheight=`echo "$width*$ratio" | bc -l`
        newheight=`echo "($newheight+0.5)/1" | bc`
      fi
    else
      # horizontal
      long=`echo "$width/$height > $ratio" | bc -l`
      if [ $long -eq "1" ] 
      then
        # wider than ratio
        newwidth="$width"
        newheight=`echo "$width/$ratio" | bc -l`
        newheight=`echo "($newheight+0.5)/1" | bc`
      else
        # skinnier than ratio
        newwidth=`echo "$height*$ratio" | bc -l`
        newwidth=`echo "($newwidth+0.5)/1" | bc`
        newheight="$height"
      fi
    fi
    printf "Padding into $base..."
    convert -size "$newwidth"x"$newheight" xc:"$padcolor" .padcanvas.miff
    composite -gravity center "$image" .padcanvas.miff "$dir"/"$base"
    rm .padcanvas.miff
    echo "DONE"
  else
    echo "$image is not a proper image...skipping."
  fi
  shift
done

I have not completely bullet proofed the above but it should get the job done.

Here’s the same before and after shots to show what this script does:

Original Padded with black Padded with transparent pixels
Long horizontal before Long horizontal after Long horizontal after
Short horizontal before Short horizontal after Short horizontal after
Long vertical after Long vertical after Long vertical after
Short vertical before Short vertical after Short vertical after

Look closely at the last column, the images are padded with transparent pixels! Could be useful for web posting.

Rounding floats to ints with bc in bash

Sunday, August 16th, 2009

I’ve seen a lot of bizarre attempts to round floating point numbers to integers in bash. Here’s my cheap hack using bc:


echo "($float+0.5)/1" | bc 

If your floating point number is in a variable called float then this will round up or down accordingly. As in 1.0 and 1.4 round to 1, while 1.5 and 1.9 round to 2.

Cell phone silencer

Sunday, August 16th, 2009

I’m going to start manufacturing cell phone silencers. They’ll resemble simple throw pillows, but with a slim pocket down the top for you to hide your cell phone while your at the movies or theater rendering its ring silent. Here’s a photo with an x-ray revealing the hidden, quieted phone. Cell phone silencer pillow

Pad images to fit 4 by 6 photo paper using applescript

Sunday, August 16th, 2009

I recently got my 4″ by 6″ prints from an online photo printing site. Most of the images had been arbitrarily cropped to fit the paper. I wrote an applescript to pad images to fit on a 4″ by 6″ print, so that the site wouldn’t need to adjust my images. The script doesn’t change the size of the image to 4″ by 6″, it just pads the image in one direction to fit a 4 by 6 or 6 by 4 ratio, whichever requires the least padding.


on open (listOfFiles)
	set replace to button returned of (display dialog "Replace existing files?" buttons {"Yes", "No"})
	repeat with this_file in listOfFiles
		set the new_file_name to (this_file as string)
		if replace = "No" then
			set parsed_path to my parse_file(this_file)
			set full_name to item 2 of parsed_path & "." & item 3 of parsed_path
			set input_name to ""
			repeat while input_name = ""
				set input_name to text returned of (display dialog "Save padded version of " & full_name & " as:" default answer full_name)
			end repeat
			if input_name does not end with item 3 of parsed_path then
				set input_name to input_name & item 3 of parsed_path
			end if
			set new_file_name to item 1 of parsed_path & ":" & input_name
		end if
		try
			tell application "Image Events"
				launch
				set this_image to open (this_file as string)
				
				set this_list to dimensions of this_image
				set width to (item 1 of this_list as integer)
				set height to (item 2 of this_list as integer)
				
				-- rotate to simplify things
				if height is greater than width then
					if height / width > (6.0 / 4.0) then
						pad this_image to dimensions {height * (4.0 / 6.0), height} --with pad color {255,255,255}
					else
						pad this_image to dimensions {width, width * (6.0 / 4.0)} --with pad color {255,255,255}
					end if
				else
					if width / height > (6.0 / 4.0) then
						pad this_image to dimensions {width, (width / (6.0 / 4.0))} --with pad color {255,255,255}
					else
						pad this_image to dimensions {(6.0 / 4.0) * height, height} --with pad color {255,255,255}
						-- not wide enough
					end if
				end if
				
				save this_image in new_file_name with icon
				close this_image
			end tell
		on error error_message
			display dialog error_message
		end try
		
	end repeat
	quit application "Image Events"
end open

-- given a file (or folder) return a list containing 
--   the path to its parent directory, 
--   its name without its file extension, and 
--   its file extension
on parse_file(this_file)
	set default_delimiters to AppleScript's text item delimiters
	-- if given file is a folder then strip terminal ":" so as to return 
	-- folder name as file name and true parent directory
	if last item of (this_file as string) = ":" then
		set AppleScript's text item delimiters to ""
		set this_file to (items 1 through -2 of (this_file as string)) as string
	end if
	set AppleScript's text item delimiters to ":"
	set this_parent_dir to (text items 1 through -2 of (this_file as string)) as string
	set this_name to (text item -1 of (this_file as string)) as string
	-- default or no extension is empty string
	set this_extension to ""
	if this_name contains "." then
		set AppleScript's text item delimiters to "."
		set this_extension to the last text item of this_name
		set this_name to (text items 1 through -2 of this_name) as string
	end if
	set AppleScript's text item delimiters to default_delimiters
	return {this_parent_dir, this_name, this_extension}
end parse_file

Save this in a script and then drag some images onto the script.

Here’s some before and after shots to show what this script does:

Original Padded
Long horizontal before Long horizontal after
Short horizontal before Short horizontal after
Long vertical before Long vertical after
Short vertical before Short vertical after

Note: If you are running Mac OS X 10.5 then you can uncomment the with pad color {255,255,255} lines to change the padding color from the default black to white or any other color.
Note: I’m using my (hopefully) bulletproof file path parse function, parse_file, which I have recently posted about.

Extract directory name, file name with root and extension in Applescript

Sunday, August 16th, 2009

I posted earlier about using my last_offset function to extract the directory name and base name of a POSIX paths in applescript. This proves to be much more useful with URLs than Mac OS X file paths, especially because the default is not POSIX in applescript rather to use colons to separate files.
So I want to write a pure applescript bulletproof extractor for directory name and file name with extension.
Here’s some problems right up front:
Using Finder I can’t make a new folder called:
“foo:bar”
Finder won't make directories with colons
But using Finder I can make a new folder called “foo/bar”
Finder will (sort of) make directories with slashes
although examining that directory in Terminal I see that the slash / is interpreted as an escaped colon
\:, shown here:
Terminal will make colon directory
Now on the Terminal command line I can not make a directory called “foo/bar”
Terminal won't make slash directory
but on the Terminal command line I can make a directory called “bar:foo”
Terminal will make colon directory
but examining that directory back in Finder I see that there the colon becomes a “/” again.
Finder will change colons in names to slashes
Using Script Editor and treating the alias of one of these shape-shifting directories as a string, the character renders as a slash.
Script Editor treats character as a slash
These will be our extreme test cases for a bulletproof directory name and file name extractor in applescript.
Here’s my attempt:


-- given a file (or folder) return a list containing 
--   the path to its parent directory, 
--   its name without its file extension, and 
--   its file extension
on parse_file(this_file)
	set default_delimiters to AppleScript's text item delimiters
	-- if given file is a folder then strip terminal ":" so as to return 
	-- folder name as file name and true parent directory
	if last item of (this_file as string) = ":" then
		set AppleScript's text item delimiters to ""
		set this_file to (items 1 through -2 of (this_file as string)) as string
	end if
	set AppleScript's text item delimiters to ":"
	set this_parent_dir to (text items 1 through -2 of (this_file as string)) as string
	set this_name to (text item -1 of (this_file as string)) as string
	-- default or no extension is empty string
	set this_extension to ""
	if this_name contains "." then
		set AppleScript's text item delimiters to "."
		set this_extension to the last text item of this_name
		set this_name to (text items 1 through -2 of this_name) as string
	end if
	set AppleScript's text item delimiters to default_delimiters
	return {this_parent_dir, this_name, this_extension}
end parse_file

Fullscreen <div> with more content below

Saturday, August 15th, 2009

Looking back at my “make any java applet you find on the web fullscreen” post, that the more interesting code is not the php I used to build the <applet> tag with width=100% and height=100%, but the css that I use to get the applet fullscreen and still have the form and instructions appear below the applet.
Here’s the css for a fullscreen <div> and a second <div> below (where you have to scroll down to see its contents):


html, body { 
  height: 100%; 
  margin: 0; 
  padding: 0; 
  width: 100%; 
} 
#fullscreen {
  height: 100%;
  width: 100%;
}

Then in your page you can just have something like:


<div id="fullscreen" style="background-color:#4F5">
Fullscreen!
</div>
<div style="background-color:#45F">
Under the fullscreen!
</div>

Example: A fullscreen image with text below.

Link to compose new email in gmail

Friday, August 14th, 2009

This is certainly no secret or hack and in fact is well known and documented all over the web. Nonetheless I’ll post it here. Clicking on this link will open a new window and compose a new message in gmail. If you aren’t signed in you will be prompted to sign in, but after you sign in you’ll immediately be composing an email (not viewing your inbox as default).
https://mail.google.com/mail/?fs=1&view=cm&shva=1&su=
Note: If you want to program with this just start adding values to the end of the url above. I have already added a blank subject by ending the above url with &su=, so to add a subject just add a string to the end of the url above. For body, to, cc, and bcc fields use &body=, &to=, &cc=, &bcc= all with strings after word. Depending on your browser you may need to URI escape your field values.