SyncPAppX icon

SyncPAppX

Download SyncPAppX application

You can download SyncPAppX application with a minimum amount of $4.80 or donating more:
Requires OS X 10.4.2 or later

Change log

r1.1 (12 Jan. 2007)

Dowload SyncPAppX script source

You can dowload SyncPAppX script source from sourceforge.net and then wrap application yourself.
You also need Platypus and CocoaDialog.
Requires OS X 10.4.2 or later

SyncPAppX script source code

#!/bin/sh -x

##########################################################################
#
#   SyncPAppX - Syncronize Portable Application
#   $Revision: 1.1
#
#   The Contents of this file are made available subject to the terms
#   of the following license
#
#          - GNU General Public License Version 2.1
#
#   Carlo Gandolfi, January 2007
#
#   GNU General Public License Version 2.1
#   =============================================
#   Copyright 2006 by Carlo Gandolfi (cgand@users.sourceforge.net)
#
#   This program is free software; you can redistribute it and/or
#   modify it under the terms of the GNU General Public
#   License version 2.1, as published by the Free Software Foundation.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#   General Public License for more details.
#
#   You should have received a copy of the GNU General Public
#   License along with this library; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston,
#   MA  02111-1307  USA
#
##########################################################################

# Reset PATH
PATH=/bin:/sbin:/usr/bin:/usr/sbin
export PATH

p_userbase="$1/Contents/Resources"

CD="$p_userbase/CocoaDialog.app/Contents/MacOS/CocoaDialog"
appicon="$p_userbase/appIcon.icns"
cautionicon="$p_userbase/P_${appid}_Caution.icns"
mycautionicon="$1/Contents/Resources/SyncPAppX_Caution.icns"
myappicon="$1/Contents/Resources/appIcon.icns"

NOW=`date "+%y-%m-%d_%H.%M.%S"`
sync_out="/tmp/Sync_${NOW}.txt"

# ========================================================
# CDokmessage
# CocoaDialog Ok/Cancel message box
# $1 "text"
# $2 "informative text"
# $3 "--no-cancel" = don't show a cancel button
# ========================================================

function CDokmessage {
	beep
	"$CD" ok-msgbox  --icon-file "$appicon" \
	--text "$1" --informative-text "$2" "$3"
}

function CDokmessagec {
	beep
	"$CD" ok-msgbox  --icon-file "$cautionicon" \
	--text "$1" --informative-text "$2" "$3"
}

function beep {
	/usr/bin/osascript << EOT
	tell application "Finder"
	beep
	end tell
EOT
}

# ========================================================
# bsd_command_check
# Check that the required BSD command are installed
# ========================================================

function command_check_msg {
message1="One or more *BSD commands* to run Portable $appid were not found on \
this machine. You must install the BSD Subsystem package that is in the \
following folder on disk 1 of your Mac OS X installation DVD:\n/Welcome to Mac \
OS X/Optional Installs.\n\nNow quit."
button=`/usr/bin/osascript << EOT
	tell application "Finder"
	beep
	display dialog "$message1" buttons {"Quit"} \
		with icon caution default button "Quit"
	set result to button returned of result
	end tell
EOT`
if test "$button" == "Quit"; then				# Quit application
	exit 112
fi
}

function bsd_command_check {  	# written by Patrick Luby	
commands="awk cp defaults diskutil echo grep ln mkfifo mkdir mv \
plutil ps rm sed sleep touch rsync"
for i in $commands ; do
	if [ ! -x "/usr/bin/$i" -a ! -x "/bin/$i" -a ! -x "/usr/sbin/$i" -a \
	! -x "/sbin/$i" ] ; then
	    # Return 96 + 16 if a command is not found
		command_check_msg;
		exit 112;
	fi
done
}

# ========================================================
# osx_version_check
# Check that the user is running Mac OS X 10.4.2 or higher
# ========================================================

function version_check_msg {
message1="You are running OS X version $version.\n\
Portable $appid can only be opened on Mac OS X 10.4.2 or higher."
button=`/usr/bin/osascript << EOT
	tell application "Finder"
	beep
	display dialog "$message1" buttons {"Quit"} \
		with icon caution default button "Quit"
	set result to button returned of result
	end tell
EOT`
if test "$button" == "Quit"; then				# Quit application
	exit 113
fi
}

function osx_version_check {	 # written by Patrick Luby	
if [ -x "/usr/bin/sw_vers" ] ; then
    # Return 96 + 17 if it is a bad version
    version=`/usr/bin/sw_vers | grep '^ProductVersion:' | awk '{ print $2 }'`
    case "$version" in
        10.[01234]) version_check_msg ; exit 113;;
        10.[01234].[01]) version_check_msg ; exit 113;;
    esac
fi
}

# ========================================================
# get_p_app
# Select Portable Application to sync
# ========================================================
			
function sync_p_app {	
	case "${s_app}" in
		'Portable Safari') sync_p_safari "Safari";;
		'Portable Mail') sync_p_mail "Mail"; sync_mail_dl "Mail";;
		'Portable iCal') sync_p_ical "iCal";;
		'Portable Address Book') sync_p_addressbook "Address Book";;
		'Portable iChat') sync_p_ichat "iChat";;
	esac
}

function copy_p {
	case "${s_app}" in
		'Portable Safari') copy_p_app "Safari";;
		'Portable Mail') copy_p_app "Mail";;
		'Portable iCal') copy_p_app "iCal";;
		'Portable Address Book') copy_p_app "Address Book";;
		'Portable iChat') copy_p_app "iChat";;
	esac
}

function copy_sync {
		text="Sync or copy Portable Preferences?"
		informativetext="You can sync your Portable preferences to \
local ones or copy local preferences to Portable ones?"
		rv=` "$CD" msgbox --no-newline --icon-file "$myappicon" \
		--text "$text" --informative-text "$informativetext" \
		--button1 "Sync" --button2 "Copy" --button3 "Cancel" `
		if [ "$rv" == "1" ] ; then
			get_p_app
				if [ -n "$rvf" ]; then
					sync_p_app
				else
					exit 0
				fi			
		elif [ "$rv" == "2" ] ; then
			get_p_app
				if [ -n "$rvf" ]; then
					copy_p
				else
					exit 0
				fi		
		elif [ "$rv" == "3" ] ; then	
			exit 0			
		fi
}

function copy_p_app {
	p_userbase="$p_path/Contents/Resources"
	copy_pref="$p_userbase/CopyPref_Done"
	copy_dl="$p_userbase/CopyDL_Done"
	
	function rm_touch {
		if [ -f "$copy_pref" ] ; then
			rm -f "$copy_pref"
		fi
		if [ -f "$copy_dl" ] ; then
			rm -f "$copy_dl"
		fi
	}
	
	if rm_touch ; then
		rv=` CDokmessage "Copy ${s_app} preferences" \
"You can now open your ${s_app} and it will ask you to copy local preferences." \
"--no-cancel" `
		if [ "$rv" == "1" ] ; then
#			open "$p_path"
#			"$p_path/Contents/MacOS/${s_app}"
#			disabled as Portable app open with icon on the dock
			exit 0
		elif [ "$rv" == "2" ] ; then
			exit 0
		fi
	else
	CDokmessagec "Copy ${s_app} preferences error" \
"An error occur while copying local preferences." "--no-cancel" > /dev/null
	exit 0
	fi
}
	
function get_p_app {
	rvf=` "$CD" fileselect --title "Select Portable Application" --text "Please select \
Portable Application to sync:" --with-directory /Volumes --with-extensions .app `
	p_path="$rvf";
	s_app=` defaults read "$p_path/Contents/Info" CFBundleName `
	case "${s_app}" in
		'Portable Safari') ;;
		'Portable Mail') ;;
		'Portable iCal') ;;
		'Portable Address Book') ;;
		'Portable iChat') ;;
		* ) wrong_path;;
	esac
}

function wrong_path {
	cautionicon=$mycautionicon
	rv=` CDokmessagec "Portable Application not selected" \
"You have not selected a compatible Portable Application to sync. \
Try again?"`
		if [ "$rv" == "1" ] ; then
			get_p_app
		elif [ "$rv" == "2" ] ; then
			exit 0
		fi
}

# ========================================================
# quitapp
# Check if local or portable app is open and quit
# ========================================================

function quitapp {
	if ps cx | grep "$1"'$' > /dev/null; then
		rv=` CDokmessage "$1 is already running on this system" \
		"Quit runnig $1 and reopen SyncPApp." "--no-cancel" `
		if [ "$rv" == "1" ] ; then				# Quit application
			exit 0
		fi
	fi
}

# ========================================================

function sync_p_safari {
	quitapp "${1}"
#	appurl=`cat "$p_path/${1}.app/Contents/Resources/script" | \
#	grep 'appurl=' | awk 'BEGIN{FS="="}{print $2}'`

	appurl=com.apple.Safari.plist
	appurl2=Cookies.plist
	appid=${1}

	userplistbase="Library/Preferences"
	usercookiesbase="Library/Cookies"
	userplist="$userplistbase/$appurl"
	userplist2="$usercookiesbase/$appurl2"
	upl="$userplist $userplist2"

	userprefbase="Library"
	userpref="$HOME/$userprefbase/$appid"

	p_userbase="$p_path/Contents/Resources"
	p_userpref="$p_userbase/$userprefbase/$appid"
	
	appicon="$p_userbase/appIcon.icns"

	sync "${1}"
	sync_txt
}

function sync_p_mail {
	quitapp "${1}"

	appurl=com.apple.mail.plist
	appid=${1}

	userplistbase="Library/Preferences"
	userplist="$userplistbase/$appurl"
	upl="$userplist"

	userprefbase="Library"
	userpref="$HOME/$userprefbase/$appid"

	p_userbase="$p_path/Contents/Resources"
	p_userpref="$p_userbase/$userprefbase/$appid"
	
	appicon="$p_userbase/appIcon.icns"
	
	function sync_mail {
		userprefsize=`du -hc "$p_userpref" | cut -f1 | tail -1`
		freesize=`df -h "$userprefbase" | tail -1 | awk '{print $4}'`
		buserprefsize=`du -c "$p_userpref" | cut -f1 | tail -1`
		bfreesize=`df "$userprefbase" | tail -1 | awk '{print $4}'`
		if [ $buserprefsize -lt $bfreesize ] ; then
			rv=` CDokmessage "Sync ${1} Preferences" \
			"Your Portable ${1} Preferences are $userprefsize. \
You have $freesize available. Sync to local ${1}?" `
			if [ "$rv" == "1" ] ; then
				sync "${1}"
			fi
			else
			CDokmessagec "No space to copy ${1} folder" \
			"Your ${1} Preferences are $userprefsize. \
You have $freesize available. There is no enough space. Now quit" \
	"--no-cancel" > /dev/null
		exit 0
		fi
	}

	userdlplist=`defaults read com.apple.mail MailDownloadsPath`
	sync_mail "${1}"
	defaults write com.apple.mail MailDownloadsPath "$userdlplist"

}

function sync_mail_dl {
	appid=${1}

	userplistbase="Library/Preferences"

	userprefbase="Library"
	userpref="$HOME/$userprefbase/$appid"
	
	appicon="$p_userbase/appIcon.icns"
	
	p_dl_folder=` defaults read "$p_path/Contents/Resources/Library/Preferences/com.apple.mail" MailDownloadsPath `
	userdlplist=` defaults read com.apple.mail MailDownloadsPath `
		
	function select_dl {
		if	[ -d "${userdlplist}" ] ; then
			sync_dl "${1}"
			else
			rvdl=` "$CD" fileselect --title "Select ${1} Downloads folder" \
			--text "Locate your \"${1} Downloads\" folder." --with-directory ~/Library --select-directories `
			if [ -n "$rvdl" ] ; then
				userdlplist="$rvdl"; export userdlplist
				sync_dl "${1}"
			fi
		fi	
	}

	function runsyncdl {	# written by Kevin Hendricks 
		rm -f /tmp/hpipe
		mkfifo /tmp/hpipe
		"$CD" progressbar --indeterminate --title "Sycn \"${1} Downloads\" folder" \
		--text "Sync \"$userdlplist\". Please wait..." < /tmp/hpipe &	
		exec 3<> /tmp/hpipe
		echo -n . >&3
		# do all of your work here
		rsync -av "$p_dl_folder/" "$userdlplist" | cat>>"$sync_out"
		exec 3>&-
		wait
		rm -f /tmp/hpipe
	}

	function sync_dl {
		userdlsize=`du -hc "$p_dl_folder" | cut -f1 | tail -1`
		freesize=`df -h "$userprefbase" | tail -1 | awk '{print $4}'`
		buserdlsize=`du -c "$p_dl_folder" | cut -f1 | tail -1`
		bfreesize=`df "$userprefbase" | tail -1 | awk '{print $4}'`
		if [ $buserdlsize -lt $bfreesize ] ; then
			rv=` CDokmessage "Sync \"${1} Downloads\" folder" \
			"Your Portable ${1} Downloads folder is $userdlsize. \
You have $freesize available. Sync to local ${1} Download folder?" `
			if [ "$rv" == "1" ] ; then
				if runsyncdl ; then
					"$CD" bubble --title "${1} Downloads folder sync" \
					--text "Portable ${1} Downloads folder synced to local system \
with success." --icon-file "$appicon"
				else
					"$CD" bubble --title "Sync ${1} Downloads folder error" \
					--text "Empty folder or an error occurred syncing ${1} Downloads folder." \
					--icon-file "$cautionicon"
				fi
			fi
		else
		CDokmessagec "No space to copy \"${1} Downloads\" folder" \
		"Your portable ${1} Downloads folder is $userdlsize. \
You have $freesize available. There is no enough space. \
Now quit." "--no-cancel" > /dev/null
		fi
	}

	function copy_p_dl {
		if [ -d "$p_dl_folder" ] ; then
			beep
			text="Sync Portable \"${1} Downloads\" folder"
			informativetext="Sync Portable \"${1} Downloads\" folder to this system?"
			rv=` "$CD" msgbox --no-newline --icon-file "$appicon" \
			--text "$text" --informative-text "$informativetext" \
			--button1 "Sync" --button2 "Cancel" `
			if [ "$rv" == "1" ] ; then
				select_dl "${1}"
			fi
		fi
	}
	copy_p_dl "${1}"
	sync_txt
}

function sync_p_ical {
	quitapp "${1}"

	appurl=com.apple.iCal.plist
	appurl2=com.apple.iCal.AlarmScheduler.plist
	appurl3=com.apple.iCal.helper.plist
	appid=${1}

	userplistbase="Library/Preferences"
	userplist="$userplistbase/$appurl"
	userplist2="$userplistbase/$appurl2"
	userplist3="$userplistbase/$appurl3"
	upl="$userplist $userplist2 $userplist3"

	userprefbase="Library/Application Support"
	userpref="$HOME/$userprefbase/$appid"

	p_userbase="$p_path/Contents/Resources"
	p_userpref="$p_userbase/$userprefbase/$appid"
	
	appicon="$p_userbase/appIcon.icns"

	sync "${1}"
	sync_txt
}

function sync_p_addressbook {
	quitapp "${1}"

	appurl=com.apple.AddressBook.plist
	appid=${1}

	userplistbase="Library/Preferences"
	userplist="$userplistbase/$appurl"
	
	userprefbase="Library/Application Support"
	userpref="$HOME/$userprefbase/AddressBook"
	
	upl="$userplist"

	p_userbase="$p_path/Contents/Resources"
	p_userpref="$p_userbase/$userprefbase/$appid"
	
	appicon="$p_userbase/appIcon.icns"
	
	sync "${1}"
	sync_txt
}

function sync_p_ichat {
	quitapp "${1}"

	appurl=com.apple.iChat.plist
	appurl2=com.apple.iChat.AIM.plist
	appurl3=com.apple.iChat.jabber.plist
	appurl4=com.apple.iChatAgent.plist
	appurl5=com.apple.iChat.SubNet.plist
	appid=${1}

	userplistbase="Library/Preferences"
	userplist="$userplistbase/$appurl"
	userplist2="$userplistbase/$appurl2"
	userplist3="$userplistbase/$appurl3"
	userplist4="$userplistbase/$appurl4"
	userplist5="$userplistbase/$appurl5"
	upl="$userplist $userplist2 $userplist3 $userplist4 $userplist5"

	userprefbase="Library/Logs"
	userpref="$HOME/$userprefbase/${appid}ConnectionErrors"

	p_userbase="$p_path/Contents/Resources"
	p_userpref="$p_userbase/$userprefbase/$appid"
	
	appicon="$p_userbase/appIcon.icns"

	sync "${1}"
	sync_txt
}

function do_back_up {
	if [ -d "$userpref" ] ; then
		mv "$userpref" "$userpref.${NOW}"
		echo "Back-up folder(s) file(s):" | cat>>"$sync_out"
		echo "$userpref.${NOW}" | cat>>"$sync_out"
	fi
	for i in $upl ; do
		if [ -f "$HOME/$i" ] ; then
			mv -f "$HOME/$i" "$HOME/$i.${NOW}"
			echo "$HOME/$i.${NOW}" | cat>>"$sync_out"
		fi
	done
	echo "#########################" | cat>>"$sync_out"
}

function run_sync {	
	
	function warning_sync {
		beep
		text="Overwrite local $1 Preferences?"
		informativetext="Running sync will overwrite $1 local \
Preferences on this system. Continue sync?"
		rv=` "$CD" msgbox --no-newline --icon-file "$mycautionicon" \
		--text "$text" --informative-text "$informativetext" \
		--button1 "Back-up & Sync" --button2 "Sync" --button3 "Cancel" `
		if [ "$rv" == "1" ] ; then
			do_back_up
			do_sync
		elif [ "$rv" == "2" ] ; then
			do_sync
		elif [ "$rv" == "3" ] ; then
			"$CD" bubble --title "$1 sync cancel" --text "No sync \
performed, SyncPAppX quit without sync." --icon-file "$myappicon" &
			exit 0			
		fi
	}
	
	function do_sync {	# written by Kevin Hendricks
		rm -f /tmp/hpipe
		mkfifo /tmp/hpipe
		"$CD" progressbar --indeterminate --title "Syncing Portable $appid Preferences" \
		--text "Syncing \"$p_path\". Please wait..." < /tmp/hpipe &
		exec 3<> /tmp/hpipe
		echo -n . >&3
		# do all of your work here
		rsync -av --delete "$p_userpref/" "$userpref" | cat>>"$sync_out"
		for i in $upl ; do
			if [ -f "$p_userbase/$i" ] ; then
				rsync -av "$p_userbase/$i" "$HOME/$i" | cat>>"$sync_out"
			fi
		done
		exec 3>&-
		wait
		rm -f /tmp/hpipe
	}	
	warning_sync "${1}"
}

function save_txt {
        mv -f "$sync_out" "$HOME/Documents/Sync-${s_app}_${NOW}.txt"
}

function sync_txt {
	 rv=` "$CD" textbox --title "SyncPAppX log" --no-newline \
	 --informative-text "Save SyncPAppX log text as: \"~/Documents/Sync-${s_app}_${NOW}.txt\"?" \
     --text-from-file "$sync_out" --button1 "Save" --button2 "Cancel" `
     if [ "$rv" == "1" ] ; then
			if save_txt ; then
				appicon="$myappicon"
				CDokmessage "SyncPAppX log text saved" \
				"\"Sync-${s_app}_${NOW}.txt\" file saved in \"~/Documents\" folder." \
				"--no-cancel" > /dev/null
				exit 0
			else
				cautionicon="$mycautionicon"
				CDokmessagec "Error saving Sync log text" \
				"An error occour while saving sync log text. Now quit." \
				"--no-cancel" > /dev/null
				exit 0
			fi
	fi
}


function sync {
	if run_sync "${1}" ; then
		"$CD" bubble --title "$1 sync done" --text "Sync \
$1 end with success." --icon-file "$appicon" &
	else
		CDokmessagec "Sync $1 setup error" \
"An error occour while sync preferences. Now quit." "--no-cancel" > /dev/null
		exit 0
	fi
}
	
# ========================================================

bsd_command_check
osx_version_check
copy_sync

exit 0