#!/bin/bash
# *** variables ***
# filename
system=`uname`
if [ "$system" = "Darwin" ]; then
db_file="/var/mobile/Library/AddressBook/AddressBook.sqlitedb"
else
db_file="AddressBook.sqlitedb" # for debugging
fi
# property values
phone=3
email=4
address=5
# label values
mobile=1
home=2
work=4
# key values
street=1
state=2
zipcode=3
city=4
countrycode=5
# *** functions ***
# helpMsg() returns a help message
function helpMsg() {
echo "
iPhone Contacts Script
by Yuri
List of recognized commands:
.backup - make a backup copy of the Address Book
.help - display this message
.info - display contact information
.new - create a new contact
.refresh - respring the iPhone springboard
.search - search contacts by name
.quit - exit the script"
}
# formatPhoneNumber() formats a phone number with parentheses and dashes
formatPhoneNumber() {
if [ ${#1} = 10 ]; then
val="(${1:0:3}) ${1:3:3}-${1:6:4}"
elif [ ${#1} = 7 ]; then
val="${1:0:3}-${1:3:4}"
else
val=$1
fi
echo "$val"
}
# getSortCode() converts the first argument to a suitable "sort" value for iPhone Contacts
# "Key" is: (ASCII code - 64) x 2 + 39
function getSortCode() {
oldstring=`echo $1 | tr "[:lower:]" "[:upper:]"`
for i in $(seq 0 $((${#oldstring} - 1))); do
char=${oldstring:$i:1}
char=`printf "%d\n" "'$char"`
code=$((($char-64)*2+39))
char=$(printf "\\$(printf "%03o" $code)")
newstring="$newstring$char"
done
echo $newstring
}
# insertName() creates a new contact. $1 is the first name, $2 is the last name
function insertName() {
if [ "${#}" -lt 1 ]; then
echo "Too few arguments."
else
if [ "${#}" = 1 ]; then
first=`echo $1 | sed s/\'/\'\'/`
last=""
firstsort=`getSortCode $first | sed s/\'/\'\'/`
lastsort=$firstsort
else
first=`echo $1 | sed s/\'/\'\'/`
last=`echo $2 | sed s/\'/\'\'/`
firstsort=`getSortCode $first | sed s/\'/\'\'/`
lastsort=`getSortCode $last | sed s/\'/\'\'/`
fi
sqlite3 $db_file <<SQL_INSERT_1
INSERT INTO ABPerson (First, Last, Note, Kind, FirstSort, LastSort, CreationDate, ModificationDate, StoreID, FirstSortSection, LastSortSection, FirstSortLanguageIndex, LastSortLanguageIndex)
VALUES ('$first', '$last', 'Auto-created by bash script', 0, '$firstsort', '$lastsort', 254356088, 254356088, 0, '${firstsort:0:1}', '${lastsort:0:1}', 0, 0);
SQL_INSERT_1
fi
}
# listAll() displays all contacts and returns a string
function listAll() {
sqlite3 $db_file 'SELECT ROWID, First, Last FROM ABPerson ORDER BY LastSort, FirstSort;' | sed 's/|/: /' | sed 's/|/ /'
}
# listOne() displays all info for a given contact
function listOne() {
name=`sqlite3 $db_file <<SQL_SELECT_1
SELECT First, Last
FROM ABPerson
WHERE ROWID=$1;
SQL_SELECT_1`
if [ -n "$name" ]; then
echo "Contact: $name" | sed 's/|/ /'
echo "Mobile: "`sqlite3 $db_file <<SQL_SELECT_2
SELECT value
FROM ABMultiValue
WHERE record_id=$1 AND property=$phone AND label=$mobile;
SQL_SELECT_2`
echo "Home: "`sqlite3 $db_file <<SQL_SELECT_3
SELECT value
FROM ABMultiValue
WHERE record_id=$1 AND property=$phone AND label=$home;
SQL_SELECT_3`
echo "Work: "`sqlite3 $db_file <<SQL_SELECT_4
SELECT value
FROM ABMultiValue
WHERE record_id=$1 AND property=$phone AND label=$work;
SQL_SELECT_4`
echo "E-mail: "`sqlite3 $db_file <<SQL_SELECT_5
SELECT value
FROM ABMultiValue
WHERE record_id=$1 AND property=$email;
SQL_SELECT_5`
parent_id=`sqlite3 $db_file <<SQL_SELECT_6
SELECT UID
FROM ABMultiValue
WHERE record_id=$1 AND property=$address;
SQL_SELECT_6`
if [ -n "$parent_id" ]; then
echo "Address: "`sqlite3 $db_file << SQL_SELECT_7
SELECT value
FROM ABMultiValueEntry
WHERE parent_id=$parent_id AND key=$street;
SQL_SELECT_7`
echo " "`sqlite3 $db_file << SQL_SELECT_7
SELECT value
FROM ABMultiValueEntry
WHERE parent_id=$parent_id AND key=$city;
SQL_SELECT_7`", "`sqlite3 $db_file << SQL_SELECT_8
SELECT value
FROM ABMultiValueEntry
WHERE parent_id=$parent_id AND key=$state;
SQL_SELECT_8`" "`sqlite3 $db_file << SQL_SELECT_9
SELECT value
FROM ABMultiValueEntry
WHERE parent_id=$parent_id AND key=$zipcode;
SQL_SELECT_9`
else
echo "Address: "
fi
echo "Note: "`sqlite3 $db_file <<SQL_SELECT_12
SELECT Note
FROM ABPerson
WHERE ROWID=$1;
SQL_SELECT_12`
fi
}
# updateMultiValue() creates/updates phone numbers/addresses
updateMultiValue() {
if [ $# -lt 4 ]; then
echo "Too few arguments."
else
query=`sqlite3 $db_file <<SQL_SELECT_1
SELECT value
FROM ABMultiValue
WHERE record_id=$1 AND property=$2 AND label=$3;
SQL_SELECT_1`
if [ -z "$query" ]; then
sqlite3 $db_file <<SQL_INSERT_1
INSERT INTO ABMultiValue (record_id, property, label, value)
VALUES ($1, $2, $3, '$4');
SQL_INSERT_1
else
sqlite3 $db_file <<SQL_UPDATE_1
UPDATE ABMultiValue
SET value='$4'
WHERE record_id=$1 AND property=$2 AND label=$3;
SQL_UPDATE_1
fi
fi
}
# searchByName() searches the database
searchByName() {
if [ "${#}" -lt 1 ]; then
echo "Too few arguments."
else
if [ "${#}" = 1 ]; then
result=`sqlite3 $db_file <<SQL_SELECT_1
SELECT ROWID, First, Last
FROM ABPerson
WHERE First LIKE '$1' OR Last LIKE '$1';
SQL_SELECT_1`
else
result=`sqlite3 $db_file <<SQL_SELECT_2
SELECT ROWID, First, Last
FROM ABPerson
WHERE First LIKE '$1' AND Last LIKE '$2';
SQL_SELECT_2`
fi
echo "$result" | sed 's/|/: /' | sed 's/|/ /'
fi
}
# updateNote() adds a note to a contact
updateNote() {
if [ $# -lt 2 ]; then
echo "Too few arguments."
else
sqlite3 $db_file <<SQL_UPDATE_1
UPDATE ABPerson
SET Note='$2'
WHERE ROWID=$1;
SQL_UPDATE_1
fi
}
# *** execution starts here ***
# a little warning
if [ "$1" != "--skip-warning" ]; then
echo "******************************************************
A shell script to manipulate iPhone Contacts
by Yuri, Feb 09
This script may permanently corrupt or damage your
address book. Use at your own risk!
******************************************************"
echo -n "Type \"ok\" to continue > "
read answer
if [ "$answer" != "ok" ]; then
exit
fi
fi
# loop until user chooses to quit
cmd=-1
while true; do
case "$cmd" in
[0-9]*) # contact id
info=`listOne $cmd`
if [ -z "$info" ]; then
echo "Cannot find contact #$cmd."
else
echo
echo "$info"
echo
echo "Enter new contact info. Press <Enter> to skip an entry."
echo "Include no spaces, dashes, or parentheses in phone numbers."
echo
echo -n "New mobile number > "
read val
if [ -n "$val" ]; then
val=`formatPhoneNumber "$val"`
updateMultiValue $cmd $phone $mobile "$val"
echo "Mobile number updated to: $val"
fi
echo -n "New home number > "
read val
if [ -n "$val" ]; then
val=`formatPhoneNumber "$val"`
updateMultiValue $cmd $phone $home "$val"
echo "Home number updated to: $val"
fi
echo -n "New work number > "
read val
if [ -n "$val" ]; then
val=`formatPhoneNumber "$val"`
updateMultiValue $cmd $phone $work "$val"
echo "Work number updated to: $val"
fi
echo -n "New e-mail address > "
read val
if [ -n "$val" ]; then
updateMultiValue $cmd $email $mobile "$val"
echo "E-mail address updated to: $val"
fi
echo -n "Add a note > "
read val
if [ -n "$val" ]; then
updateNote $cmd "`echo "$val" | sed s/\'/\'\'/`"
echo "Note added: $val"
fi
echo
info=`listOne $cmd`
echo "$info"
echo
fi
;;
.backup)
backup="$db_file.backup"
i=0
while [ -e "$backup" ]; do
backup="$db_file.backup$i"
i=$(($i + 1))
done
cp "$db_file" "$backup"
;;
.help) # .help
echo "`helpMsg`"
echo
;;
.info) # display contact info
echo -n "Contact number > "
read cmd
info=`listOne $cmd`
if [ -z "$info" ]; then
echo "Cannot find contact #$cmd."
else
echo
echo "$info"
fi
echo
;;
.new) # .new
echo -n "New name > "
read name
insertName $name
echo
searchByName $name
echo
;;
.refresh) # .refresh
if [ "$system" = "Darwin" ]; then
restart
else
echo "Unable to respring this device."
fi
;;
.search) # .search
echo -n "Name to search > "
read name
searchByName $name
;;
.quit) # .quit
if [ "$system" = "Darwin" ]; then
restart
fi
exit
;;
*) # anything else
listAll
echo
echo "Enter the number of a contact to edit."
echo "Enter .help for a list of commands."
;;
esac
echo -n "Contacts > "
read cmd
done