iPhone and Linux

Monday, November 23, 2009

Deleting iPhone language packs

Every iPhone application has the option of including language packs. There come in the form of a seperate directory for every language the app supports. Inside those directories are files with various strings in that language that the app may use. Some apps may not support any additional languages and some may support 20.

They say (and I don't know who *they* are) that removing them can increase the phone's performance. I don't know how accurate that is, but it obviously does increase free space on the phone.

So here is one way to remove them from MobileTerminal, or any other command line program that can run commands on the phone.

First, log in as root by whatever means you wish. Either su in MobileTerminal, ssh root@IP, or whatever.

Run this command to update the locate database: updatedb

Now, we want to build a list of directories to delete by using the locate command to find all the language packs. Luckily, they are all found in *.lproj directories, so we start with locate lproj.

The output will include all the files in an .lproj directory, so let's use a grep regular expression to get only the directories. locate lproj | grep -E lproj$ will output only files that end with lproj, so it will output English.lproj, but not English.lproj/somefile.txt

Now we want to filter out the directories we want to keep. In my case, all I want to keep is English. On the iPhone, English can be either en.lproj or English.lproj so I piped the output to grep -v to filter out both: grep -E -v -i '(en.l|English)'

It may be simpler to grep the one at a time with -v and -i. "-v" is like a 'reverse grep' which displays everything except the string you specify and "-i" makes it case insensitive.

The official iPhone apps usually use long names like "English" and "Italian" while other apps will often use "en" and "it", so be sure to look for long and short names.

So, if you wanted to keep German, you could run this to save it to a text file:
locate lproj | grep -E proj$ | grep -v -i "XXXXXX.lproj" > langpacks.txt
Just add | grep -v -i "XXXXXX.lproj" for any languages you don't want deleted, and remember to add a grep for both long and short names.

Once you're sure everything looks safe to delete, then run this command:
while read file; do rm -rf "$file"; done < langpacks.txt
To recap: if you're certain you only want English languages on your phone, run this:
updatedb 
locate lproj | grep -E proj$ | grep -E -v -i '(en.l|English)' > langpacks.txt
while read file; do rm -rf "$file"; done < langpacks.txt
I deleted over 3000 language pack directories with this, and I only have less than 2 pages of apps installed.

Wednesday, November 11, 2009

A simple backup script

Unfortunately, this can't run from a SpringBoard icon as it takes too long to execute. iPhone apps are supposed to tell the system when they've finished loading or else the system assumes they're hung and kills them. I'm looking for a workaround, as I have 3 scripts I want to run that way but which get killed every time.

To use this script, put a list of files you want to back up in /var/mobile/backuplist. It will copy them to /var/mobile/backup/, tar and bzip2 them, then scp them to your computer using ssh keys, which I explained earlier. It could obviously use regular scp if you don't mind typing the password.
#! /bin/sh 
cd /var/mobile
while read line; do cp -r $line /var/mobile/backup/; done < backuplist
tar -cf backup.tar /var/mobile/backup
bzip2 backup.tar
scp -i ~/.ssh/KEY ~/backup.tar.bz2 USER@IP:/PATH/TO/DESTINATION
rm -rf backup
rm backup.*

Tuesday, November 10, 2009

Iphone Panic Button

There was a thread at Macrumors where someone asked if there were any apps which could delete your sensitive files if someone took your phone. The poster's situation was that they were in school and if they were caught with a phone, they had to turn it over and the teacher would go through it looking for anything against school rules.

This can be done with a short shell script ran from SpringBoard using the method I posted about earlier.

There are several ways of doing it depending on your threat model. You could delete the files, but what will happen to the SMS app if you delete it's database? Will it crash or create a new one? If it crashes, you may not be able to use it until you get home and copy a new .db file to the phone. If you don't have one, you may even need to restore.

A smarter way is to simply hide the files from our SpringBoard script and unhide them with another script which is hidden on the phone and ran from MobileTerminal. This should be good enough for most people and these scripts accomplishes that.

Create a text file and list all the files and directories you want to hide. Don't worry about spaces or anything, just make a normal list with the full path to the files/directories, one per line. This example assumes you run the script from a fake app called Panic and the file list is in Panic.app.
#! /bin/sh 
while read line; do
dir=$(dirname "$line")
file=$(basename "$line")
mv "$line" "$dir"/."$file";
done < /Applications/Panic.app/filelist.txt
Files will be hidden in the same directory as their original location. If you want to move them all to a different directory, change "$dir"/."$file" to /path/to/another/directory/."$file"

Put this next script anywhere you want and run it from MobileTerminal to unhide the files. You may notice it's almost the same script, only one variable on the mv line has changed places.
#! /bin/sh 
while read line; do
dir=$(dirname "$line")
file=$(basename "$line")
mv "$dir"/."$file" "$line";
done < /Applications/Panic.app/filelist.txt
Now this is cool. You could (sorta) run this remotely if you have the Prowl app, you just need the person with the phone to cooperate a little. You can add this to panic's plist file:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>panic URL</string>
<key>CFBundleURLSchemes</key>
<array>
<string>panic</string>
</array>
</dict>
</array>
Then go to Prowl's folder, find "Redirections.plist" and add this:
<key>Key</key>
<string>Panic</string>
<key>URL</key>
<string>panic:</string>
Then open Prowl and create a redirection based on the app name "Panic" and select panic from the list.

Send a Prowl notification from home using "panic" in the application field. When the notification pops up on the phone, a person can choose whether to view or close it like an SMS. If they select view, it will run the panic script and hide your files. However, if they select "close", it does nothing. You could just as easily rename the panic icon to "Bank Info" or "Nekkid Chicks" and trick them into running it. I just think it's cool.

Saturday, November 7, 2009

Send copied text from iPhone to Linux desktop final

I tweaked the script enough to finish out the subject. I think it's pretty foolproof. Set up the script from my last post on the phone and use this script on the computer.

Note, I switched from xsel to xclip to put the contents into the computer's clipboard. xsel had problems taking standard input but xclip does so reliably.

#! /bin/sh
cd /path/to/plist/directory
file=com.hitoriblog.pasteboardstacker.plist
link=$(awk 'BEGIN{ RS="</string>"}{gsub(/.*<string>/,"")}1{print $RS;exit}') $file

# send the text to the clipboard
echo $link | xclip

# If the text is a link, this will create
# an html file which you've pre-bookmarked in Firefox
if
echo "$link" | head -1 | grep http > /dev/null
then
cd /path/to/html/file/dir
echo -n '<html>
<head>
<title>Reverse Prowling</title>
<meta http-equiv="REFRESH" content="0;url=' > iLink.html
echo "$link" >> iLink.html
echo '></HEAD>
<BODY>
Redirecting to $link...
</BODY>
</HTML>' >> iLink.html

else
# if the text is not a link, this will
# display the text in the html file
# which you bookmarked in Firefox.
# It will appear as plain text when Firefox opens it
echo "$link" | sed 'N;s/\n/<br>/g;P;D;' | tr -d  > iLink.html
fi

Changing the blog template

I'm getting frustrated with blogger. It took me forever to figure out how to post code as blogger doesn't have builtin code tags like most forums do. Now, if I have a long string, it gets cut off on the right side by the sidebar. Why doesn't it word wrap it?

There is probably a simple solution but I don't know, or care about, CSS enough to make the blog look pretty. So here we are with a new template. Nice and plain.

Old style. notice how it cut off half of the scp command


New style. Scp command is there, if you scroll.

Friday, November 6, 2009

Send copied text from iPhone to Linux desktop Redux

That last post using mailx to send the iPhone's clipboard contents tested great then started failing. I tried to work out the bugs but it didn't cooperate. Mailx crashes often when executed from a SpringBoard icon and the sed line tests well then stops working for some unknown reason.

I finally gave up and found a better, faster, and more reliable alternative, and that's to use an auto-login to scp the clipboard file to the PC, where processing can take place.

Setting up scp to auto-login is pretty simple. It involves creating a keypair and moving the private key to the iPhone, then logging in to the computer with that key. Here is a more detailed guide.

Once the auto-login is set up, use this script on the iPhone:

#! /bin/sh
cd /var/mobile
scp -i ~/.ssh/KEY ~/Library/Preferences/com.hitoriblog.pasteboardstacker.plist USERNAME@IPADDRESS:/PATH/TO/PUT/THE/FILE


Now you can do the text processing on the computer. I will tweak that soon-tomorrow if I have the time- and post the results.

Thursday, November 5, 2009

Send copied text from iPhone to Linux desktop

I use Prowl for everything. One frequent use is sending text and links from my PC to the iPhone, but what about sending text and links from the phone to the PC? There is no dedicated method for doing this that I am aware of. I usually open the mail app and mail it to myself. But that takes time, pops up a Prowl notification and leaves mail running and I like to keep the mail app killed.

Why not a single tap method to send the phone's clipboard contents to my desktop? Why not also put it directly into the clipboard on my computer? While I'm at it, if it's a link, why not have a Firefox bookmark already configured to go there?

This is all done in Linux with KDE, but should work with other desktops and probably other Unix systems. It's pretty simple but requires sending email on the iPhone's command line and receiving email on the computer's command line. I used mailx and getmail respectively, so I will assume anyone who can set those up can read these scripts and customize them for their system. But as a warning, the way it is written, it downloads all email, looks for one email with a keyword, then deletes all email. I set up a seperate email address just for this purpose, but keep that in mind if you use command line email.

The iPhone script requires a jailbroken phone, Pasteboardstacker and nail (a.k.a. Heirloom mailx). Pasteboardstacker is an clipboard app that keeps a list of the things you've copied. You double tap the status bar and the list pops up, allowing you to select any of the items to be pasted. It is used here because the phone's clipboard is hard to descramble and Pasteboardstacker's contents are easy. Nail/mailx is a command line email sender. One tip, put your config info in /var/mobile/.mailrc. Nowhere else seems to work, neither does using nail.rc.

The first line extracts the last thing you copied from Pasteboardstacker's plist, the second line emails it to you, prepended by the string "SendiLinkHome". Pretty simple.

#! /bin/sh
file=~/Library/Preferences/com.hitoriblog.pasteboardstacker.plist
text=$(cat $file | sed -e '0,/<string>/d' -e '/<\/string>/,$d')
echo "SendiLinkHome $text" | mail "user@address.com"
You can now use my earlier post as a guide to getting that to run from a SpringBoard icon to send your clipboard contents home with one tap.

On the computer side, you need a way to get email such as getmail and optionally, xsel. Xsel is a command line tool that you can use to put things in the clipboard. If you run this command "echo sometext | xsel -p" then use your mouse to paste, it will paste "sometext".

This script does this: if there is new mail, it looks for "SendiLinkHome" and, if found, it takes the text you sent from your phone and does the following things:

1) it sends the contents to the clipboard using xsel
2) if the text is a link to a webpage, it creates a webpage named "iLink.html" which will redirect to that link. Why? Because you can create a file names "iLink.html", open it in your browser and bookmark it. Now when this script runs, that link will redirect to the link you sent from your phone.
3) if the text is not a link, it still puts it into iLink.html with no html formatting. Now when you click the bookmark, it will just display the text. This may be useful if you want to use the text online.

#! /bin/sh
if
getmail -r /path/to/getmailrc | grep Retrieved
then
cd ~/Mail/new
link=$(cat *localhost | grep -A 1000 SendiLinkHome | sed 's/SendiLinkHome //g')
rm *localhost
# send the contents to the clipboard
echo "$link" | xsel -p


# create an html file which is pre-bookmarked in Firefox
if
echo "$link" | grep http > /dev/null
then
echo -n '<html>
<head>
<title>Reverse Prowling</title>
<meta http-equiv="REFRESH" content="0;url=' > /path/to/iLink.html
echo "$link" >> /path/to/iLink.html
echo '></HEAD>
<BODY>
Redirecting...
</BODY>
</HTML>' >> /path/to/iLink.html

# if it's not a link, put the text in
# iLink.html anyway so it can still be
# opened by firefox. Optionally, put it in
# a text file on the desktop or wherever it may be useful.
else
echo "$link" > /path/to/iLink.html
fi
fi

Blog Archive