290 lines
7.4 KiB
Plaintext
290 lines
7.4 KiB
Plaintext
|
#!/boot/system/bin/bash
|
||
|
# --------------------------------------
|
||
|
# PERSON2VCARD
|
||
|
# simple script for convertining a person
|
||
|
# into a vcard.
|
||
|
# CC0, jadedctrl@teknik.io
|
||
|
# --------------------------------------
|
||
|
|
||
|
# PERSON INPUT
|
||
|
# --------------------------------------
|
||
|
# convert a given vcard file into a person file
|
||
|
function person_to_vcard {
|
||
|
local person="$1"
|
||
|
|
||
|
if test -n "$OUTPUT_PATH"; then vcard="$OUTPUT_PATH"
|
||
|
else vcard="${person}.vcf"
|
||
|
fi
|
||
|
|
||
|
make_vcard "$vcard"
|
||
|
populate_vcard_person "$vcard" "$person"
|
||
|
finish_vcard "$vcard"
|
||
|
}
|
||
|
|
||
|
# return a properly-formatted colon-delimited address, and a pretty address for
|
||
|
# labels. the former on first line, latter on the second.
|
||
|
function person_address {
|
||
|
local person="$person"
|
||
|
|
||
|
local address="$(catattr -d META:address "$person" 2>/dev/null)"
|
||
|
local city="$(catattr -d META:city "$person" 2>/dev/null)"
|
||
|
local state="$(catattr -d META:state "$person" 2>/dev/null)"
|
||
|
local zip="$(catattr -d META:zip "$person" 2>/dev/null)"
|
||
|
local country="$(catattr -d META:country "$person" 2>/dev/null)"
|
||
|
|
||
|
if test -z "$city" -a -z "$address"; then return 2; fi
|
||
|
echo ";;${address};${city};${state};${zip};${country}"
|
||
|
echo "${address}, ${city}, ${state} ${zip}, ${country}"
|
||
|
}
|
||
|
|
||
|
|
||
|
# VCARD OUTPUT
|
||
|
# --------------------------------------
|
||
|
# create a fresh, blank vcard
|
||
|
function make_vcard {
|
||
|
local vcard="$1"
|
||
|
printf 'BEGIN:VCARD\nVERSION:%s\n' "$VERSION" >> "$vcard"
|
||
|
addattr -t mime BEOS:TYPE text/x-vcard "$vcard"
|
||
|
}
|
||
|
|
||
|
# wrap up the current vcard
|
||
|
function finish_vcard {
|
||
|
local vcard="$1"
|
||
|
date +"REV:%Y%m%d" >> "$vcard"
|
||
|
echo "END:VCARD" >> "$vcard"
|
||
|
}
|
||
|
|
||
|
# populate a vcard with a person's attributes
|
||
|
function populate_vcard_person {
|
||
|
local vc="$1"
|
||
|
local person="$2"
|
||
|
set_vcard_name "$vc" "$(catattr -d META:name "$person" 2>/dev/null)"
|
||
|
set_vcard_org "$vc" "$(catattr -d META:company "$person" 2>/dev/null)"
|
||
|
set_vcard_url "$vc" "$(catattr -d META:url "$person" 2>/dev/null)"
|
||
|
set_vcard_email "$vc" "$(catattr -d META:email "$person" 2>/dev/null)"
|
||
|
set_vcard_phone "$vc" "$(catattr -d META:wphone "$person" 2>/dev/null)" "WORK"
|
||
|
set_vcard_phone "$vc" "$(catattr -d META:hphone "$person" 2>/dev/null)" "HOME"
|
||
|
set_vcard_nick "$vc" "$(catattr -d META:nickname "$person" 2>/dev/null)"
|
||
|
set_vcard_address "$vc" "$(person_address "$person")" "HOME"
|
||
|
set_vcard_photo "$vc" "$person"
|
||
|
}
|
||
|
|
||
|
# set the name and full-name of a vcard.
|
||
|
function set_vcard_name {
|
||
|
local vcard="$1"
|
||
|
local name="$2"
|
||
|
simple_set_vcard "$vcard" "N" "$(infer_name "$name")"
|
||
|
simple_set_vcard "$vcard" "FN" "$name"
|
||
|
}
|
||
|
|
||
|
# set the email of a vcard.
|
||
|
function set_vcard_email {
|
||
|
local vcard="$1"
|
||
|
local email="$2"
|
||
|
simple_set_vcard "$vcard" "EMAIL" "$email"
|
||
|
}
|
||
|
|
||
|
# set a vcard's url attribute.
|
||
|
function set_vcard_url {
|
||
|
local vcard="$1"
|
||
|
local url="$2"
|
||
|
simple_set_vcard "$vcard" "URL" "$url"
|
||
|
}
|
||
|
|
||
|
# set a vcard's organization attribute.
|
||
|
function set_vcard_org {
|
||
|
local vcard="$1"
|
||
|
local org="$2"
|
||
|
simple_set_vcard "$vcard" "ORG" "$org"
|
||
|
}
|
||
|
|
||
|
# set a vcard's nick. only for 3.0 and 4.0; 2.1 doesn't support NICKNAME.
|
||
|
function set_vcard_nick {
|
||
|
local vcard="$1"
|
||
|
local nick="$2"
|
||
|
if test -z "$nick"; then return 2; fi
|
||
|
|
||
|
if test "$VERSION" = "3.0" -o "$VERSION" = "4.0"; then
|
||
|
echo "NICKNAME:${nick}" >> "$vcard"
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
# set a vcard's phone-number of the given type.
|
||
|
function set_vcard_phone {
|
||
|
local vcard="$1"
|
||
|
local number="$2"
|
||
|
local type="$3"
|
||
|
if test -z "$number"; then return 2; fi
|
||
|
if test -z "$type"; then type="HOME"; fi
|
||
|
|
||
|
local prefix=""
|
||
|
if test "$VERSION" = "2.1"; then prefix="TEL;${type};VOICE:"
|
||
|
elif test "$VERSION" = "3.0"; then prefix="TEL;TYPE=${type},VOICE:"
|
||
|
elif test "$VERSION" = "4.0"
|
||
|
then prefix="TEL;TYPE=${type},voice;VALUE=uri:tel:"
|
||
|
fi
|
||
|
|
||
|
echo "${prefix}${number}" >> "$vcard"
|
||
|
}
|
||
|
|
||
|
# sets a vcard's address and address label
|
||
|
# ($addresses is a two-lined string, with the colon-delimited address on top
|
||
|
# and the user-friendly comma-delimited on bottom.)
|
||
|
function set_vcard_address {
|
||
|
local vcard="$1"
|
||
|
local addresses="$2"
|
||
|
local type="$3"
|
||
|
|
||
|
local address="$(echo "$addresses" | head -1)"
|
||
|
local label="$(echo "$addresses" | tail -1)"
|
||
|
local addrstr=""
|
||
|
local labelstr=""
|
||
|
|
||
|
if test "$VERSION" = "2.1" -o "$VERSION" = "3.0"; then
|
||
|
labelstr="LABEL;TYPE=${type}:${label}"
|
||
|
fi
|
||
|
|
||
|
if test "$VERSION" = "2.1"; then
|
||
|
addrstr="ADR;${type}:${address}"
|
||
|
elif test "$VERSION" = "3.0"; then
|
||
|
addrstr="ADR;TYPE=${type}:${address}"
|
||
|
elif test "$VERSION" = "4.0"; then
|
||
|
addrstr="ADR;TYPE=${type};LABEL=\"${label}\":${address}"
|
||
|
fi
|
||
|
|
||
|
if test -z "$address" -o -z "$label"; then return 2; fi
|
||
|
|
||
|
echo "$addrstr" >> "$vcard"
|
||
|
if test -n "$labelstr"; then
|
||
|
echo "$labelstr" >> "$vcard"
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
# embeds the given photo into the vcard file (base64), if possible
|
||
|
function set_vcard_photo {
|
||
|
local vcard="$1"
|
||
|
local photo="$2"
|
||
|
if is_image "$photo"; then ls>/dev/null; else return 2; fi
|
||
|
|
||
|
local mime="$(file --mime-type "$photo")"
|
||
|
local type="$(file "$photo" | awk -F : '{print $1}' | awk '{print $1}')"
|
||
|
echo >> "$vcard"
|
||
|
if test "$VERSION" = "2.1"; then
|
||
|
echo "PHOTO;${type};ENCODING=BASE64:$(base64 -w 79 "$photo")" \
|
||
|
>>"$vcard"
|
||
|
elif test "$VERSION" = "3.0"; then
|
||
|
echo "PHOTO;TYPE=${type};ENCODING=b:$(base64 -w 79 "$photo")" \
|
||
|
>> "$vcard"
|
||
|
elif test "$VERSION" = "4.0"; then
|
||
|
echo "PHOTO:data:${mime};base64,$(base64 -w 79 "$photo")" \
|
||
|
>> "$vcard"
|
||
|
fi
|
||
|
echo >> "$vcard"
|
||
|
}
|
||
|
|
||
|
# generic function for setting simple attrs of vcards.
|
||
|
function simple_set_vcard {
|
||
|
local vcard="$1"; local key="$2"; local val="$3"
|
||
|
if test -z "$val"; then return 2; fi
|
||
|
echo "${key}:${val}" >> "$vcard"
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
# MISC
|
||
|
# --------------------------------------
|
||
|
# takes a trad. comma-delimited address and converts to vcard format
|
||
|
function infer_name {
|
||
|
local names="$1"
|
||
|
|
||
|
local inferred_name=""
|
||
|
local honorific=""
|
||
|
local slot_count=5
|
||
|
local name_count="$(echo "$names" | wc -w)"
|
||
|
for name in $names; do
|
||
|
if is_honorific "$name"; then
|
||
|
honorific="$name"
|
||
|
else
|
||
|
inferred_name="${name};${inferred_name}"
|
||
|
fi
|
||
|
done
|
||
|
|
||
|
local i=""
|
||
|
if test "$name_count" -ne "$slot_count"; then
|
||
|
i="$((slot_count - $name_count - 1))"
|
||
|
|
||
|
while test "$i" -ne 0; do
|
||
|
inferred_name="${inferred_name};"
|
||
|
i="$((i - 1))"
|
||
|
done
|
||
|
|
||
|
if test -n "$honorific" -a "$name_count" -lt "$slot_count"; then
|
||
|
inferred_name="${inferred_name}${honorific};"
|
||
|
fi
|
||
|
fi
|
||
|
|
||
|
echo "$inferred_name"
|
||
|
}
|
||
|
|
||
|
# ok so this is super language-dependant and is omega cringe
|
||
|
# you'll probably have to modify this for your locale
|
||
|
function is_honorific {
|
||
|
local name="$1"
|
||
|
|
||
|
local honorifics="ms. mrs. mr. s-ro s-ano s-ino"
|
||
|
if echo "$honorifics" | grep -i "$name" > /dev/null; then
|
||
|
return 0
|
||
|
else
|
||
|
return 1
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
# check whether or not a file is an image
|
||
|
function is_image {
|
||
|
local file="$1"
|
||
|
file "$file" | grep "image" > /dev/null
|
||
|
}
|
||
|
|
||
|
|
||
|
# INVOCATION
|
||
|
# --------------------------------------
|
||
|
function help {
|
||
|
echo "usage: $(basename $0) [-h] [-v version] [-o path] person"
|
||
|
echo
|
||
|
echo \
|
||
|
"Creates a vcard from the given person file's attributes. By default will
|
||
|
output to a file of the same name with a .vcf file-extension.
|
||
|
-o changes output vcard filename
|
||
|
-v specify vcard version: 2.1, 3.0, or 4.0. Defaults to 4.0.
|
||
|
a random URL, and use it as the vcard's photo URL.
|
||
|
-h print this message."
|
||
|
exit 1
|
||
|
}
|
||
|
|
||
|
|
||
|
VERSION="4.0"
|
||
|
OUTPUT_PATH=""
|
||
|
while getopts ":hUo:v:" arg; do
|
||
|
case $arg in
|
||
|
o) OUTPUT_PATH="$OPTARG";;
|
||
|
v) if test "$OPTARG" = "4.0" -o "$OPTARG" = "3.0" \
|
||
|
-o "$OPTARG" = "2.1"; then
|
||
|
VERSION="$OPTARG"
|
||
|
else
|
||
|
echo "Invalid version number." >&2
|
||
|
exit 3
|
||
|
fi;;
|
||
|
h) help;;
|
||
|
esac
|
||
|
done
|
||
|
|
||
|
shift $(($OPTIND - 1))
|
||
|
remaining_args="$@"
|
||
|
|
||
|
if test -z "$1"; then help
|
||
|
else PERSON="$1"
|
||
|
fi
|
||
|
|
||
|
|
||
|
person_to_vcard "$PERSON"
|