#!/bin/sh

set -e

# reset flags
apache_reload_needed=""
runmode="normal"
mac=".mac"
pc=".pc"
xchange=".xchange"

if [ -e /etc/adduser.conf ]; then
	. /etc/adduser.conf
else
	echo "/etc/adduser.conf missing. Exiting..."
	exit 1
fi

[ -f /etc/local/users.conf ] && . /etc/local/users.conf

if [ -e /etc/local/volumes ]; then
	. /etc/local/volumes
else
	# exit silently if this system lacks required hints
	exit 0
fi

XDIRREAL="$XDIR/users/root"

if [ $XCHANGE ]; then
	if [ ! -d "$XDIR" ]; then
		echo "XDIR doesn't exist. Ignoring XCHANGE!"
		XCHANGE=""
	fi
fi

if [ $# -gt 0 ]; then
	USERS=$*
else
#	USERS=`getent passwd | awk -F: '{print $1}'`
	echo "uid required!"
	exit 1
fi

[ $NETATALK_HOME ] && mac=$NETATALK_HOME
[ $SAMBA_HOME ] && pc=$SAMBA_HOME
[ $XCHANGE_HOME ] && xchange=$XCHANGE_HOME

echo "Setting up additional folders and permissions..."
for user in $USERS; do
	uid="`getent passwd \"$user\" | awk -F: '{print $3}' | head -1`"
	HOME="`getent passwd \"$user\" | awk -F: '{print $6}' | head -1`"
	if [ -z "$HOME" ]; then
		echo "User $user doesn't exist. Ignoring..."
		continue
	fi

	# Ignore non-human accounts silently
	[ "$uid" -ge "$FIRST_UID" -a "$uid" -le "$LAST_UID" ] || continue

	[ -d $HOME ] || continue
#	[ -L $HOME ] && continue

	echo -n $user

#	if [ -x /etc/local/quota.sh ]; then
#		/etc/local/quota.sh $user
#		fi
	[ $QUOTASOFT ] || QUOTASOFT="0"
	[ $QUOTAHARD ] || QUOTAHARD="0"
	for QUOTAHOME in $QUOTAHOMES; do
		if [ $NEW_QUOTA ]; then
			setquota $user $QUOTASOFT $QUOTAHARD 0 0 $QUOTAHOME
		else
			setquota $user $QUOTAHOME $QUOTASOFT $QUOTAHARD 0 0
		fi
	done

	mkdir -p $HOME/mail
	if [ "$USE_MBOX" ]; then
		touch $HOME/mail/mbox
	elif [ -f $HOME/mail/mbox -a ! -s $HOME/mail/mbox ]; then
		rm -f $HOME/mail/mbox
	fi

	if [ $NETATALK ]; then
		mkdir -p $HOME/$mac
	fi
	if [ $SAMBA ]; then
		mkdir -p $HOME/$pc
	fi

	if [ $XCHANGE ]; then
		mkdir -p $XDIRREAL/$user
	fi

	if [ $PUBLIC ]; then
		mkdir -p $HOME/public_html
	fi

	chown $user: $HOME
	chmod u=rwX,go=rX $HOME

	# Mail handling
	chown -R $user: $HOME/mail
	chmod -R u=rw,go=,u+X $HOME/mail
	if [ -f $HOME/.mailboxlist ]; then
		chown $user: $HOME/.mailboxlist
		chmod 0640 $HOME/.mailboxlist
	fi
	if [ -f $HOME/.forward ]; then
		chown $user: $HOME/.forward
		chmod 0640 $HOME/.forward
	fi
	if [ -f /var/mail/$user ]; then
		chown $user:mail /var/mail/$user
		chmod ug=rw,o= /var/mail/$user
	elif [ -f /var/spool/mail/$user ]; then
		chown $user:mail /var/spool/mail/$user
		chmod ug=rw,o= /var/spool/mail/$user
	fi

	# Mac dir permissions
	if [ -d $HOME/$mac ]; then
		chown -R $user: $HOME/$mac
		chmod -R u=rw,g=r,o=,ug+X $HOME/$mac
		rm -rf $HOME/$mac/Network\ Trash\ Folder
		mkdir $HOME/$mac/Network\ Trash\ Folder
		chown nobody: $HOME/$mac/Network\ Trash\ Folder
		chmod a= $HOME/$mac/Network\ Trash\ Folder
	fi

	# PC dir permissions
	if [ -d $HOME/$pc ]; then
		chown -R $user: $HOME/$pc
		chmod -R u=rw,g=r,o=,ug+X $HOME/$pc
	fi
	
	# Exchange dir permissions
	if [ -d $XDIRREAL/$user ]; then
		chown -R $user:users $XDIRREAL/$user
		chmod -R g=r,g+X $XDIRREAL/$user
		if [ -e "x$HOME/$xchange" ]; then
			if [ -L "x$HOME/$xchange" ]; then
				ln -sf $XDIRREAL/$user $HOME/$xchange
			else
				echo "ERROR: $HOME/$xchange exists already. Leaving it as is..."
			fi
		else
			ln -s $XDIRREAL/$user $HOME/$xchange
		fi
	fi

	# Public dir permissions
	if [ -d $HOME/public_html ]; then
		chown -R $user: $HOME/public_html
		chmod -R u+rX,go=r,go+X $HOME/public_html
		if [ $NETATALK ]; then
			rm -rf $HOME/public_html/Network\ Trash\ Folder
			mkdir $HOME/public_html/Network\ Trash\ Folder
			chown nobody: $HOME/public_html/Network\ Trash\ Folder
			chmod a= $HOME/public_html/Network\ Trash\ Folder
		fi
	fi

	# Fileshares: <home>/shares.<sharetype>/<rogroup>/<rwgroup>/<sharename>
	#   <sharetype>: Either mac or win depending on which of netatalk and samba provides r/w access to the shares
	#   <rwgroup>:   Group with write access to the share (usually the default group of the owner)
	#   <rogroup>:   Either rwgroup or secondary group with read-only access to the share
	#   owner must be member of both groups, and rwgroup members must also be members of rogroup
	find "$HOME" -mindepth 1 -maxdepth 1 -type d -print | egrep "^$HOME/shares\." | (while read thisdir; do
		sharetype="`basename \"$thisdir\" | awk -F. '{print $2}'`"
		# Define dir and file exceptions
		case "$sharetype" in
		    mac)
			dirs_world_rw_create='.AppleDB'
			dirs_group_rw_create='.AppleDesktop/Temporary Items/TheFindByContentFolder'
			dirs_group_ro_create='TheVolumeSettingsFolder'
			dirs_group_ro_update='.AppleDouble'
			files_group_ro_update=':2eDS_Store'
			dirs_no_access_purge='Network Trash Folder'
			;;
		    win)
			;;
		    *)
			continue
			;;
		esac
		exceptions="$dirs_world_rw_create/$dirs_group_rw_create/$dirs_group_ro_create/$dirs_group_ro_update/$files_group_ro_update/$dirs_no_access_purge"
		exception_dirs_create="$dirs_world_rw_create/$dirs_group_rw_create/$dirs_group_ro_create"
		chown "$user": "$thisdir"
		chmod a=rX "$thisdir"
		find "$thisdir" -mindepth 1 -maxdepth 1 -type d -print | (while read thisdir; do
			rogroup="`basename \"$thisdir\"`"
			chown "$user":"$rogroup" "$thisdir"
			chmod ug=rX,o= "$thisdir"
			find "$thisdir" -mindepth 1 -maxdepth 1 -type d -print | (while read thisdir; do
				rwgroup="`basename \"$thisdir\"`"
				chown "$user":"$rwgroup" "$thisdir"
				chmod a=rX,g+s "$thisdir"
				find "$thisdir" -mindepth 1 -maxdepth 1 -type d -print | (while read thisdir; do
					sharename="`basename \"$thisdir\"`"
					chown "$user":"$rwgroup" "$thisdir"
					chmod u=rw,go=r,a+X,g+s "$thisdir"
					ifs="$IFS"
					# Set default permissions
					find "$thisdir" -mindepth 1 -maxdepth 1 -print | (while read thisdir; do
						item="`basename \"$thisdir\"`"
						IFS="/"; for exception in $exceptions; do IFS="$ifs";
							if [ "$item" = "$exception" ]; then
								continue 2
							fi
						done
						chgrp -R "$rwgroup" "$thisdir"
						chmod -R ug=rw,o=r,a+X,g+s "$thisdir"
					done)
					# Handle exception dirs to be created if not existing
					IFS="/"; for dir in $exception_dirs_create; do IFS="$ifs";
						if [ ! -d "$thisdir/$dir" ]; then
							rm -f "$thisdir/$dir"
						fi
						if [ ! -e "$thisdir/$dir" ]; then
							mkdir "$thisdir/$dir"
						fi
						chown "$user":"$rwgroup" "$thisdir/$dir"
					done
					IFS="/"; for dir in $dirs_world_rw_create; do IFS="$ifs";
						if [ "$rogroup" = "$rwgroup" ]; then
							chmod -R ug=rw,o=r,a+X,g+s "$thisdir/$dir"
						else
							chmod -R a=rw,a+X,g+s "$thisdir/$dir"
						fi
					done
					IFS="/"; for dir in $dirs_group_rw_create; do IFS="$ifs";
						chmod -R ug=rw,o=r,a+X,g+s "$thisdir/$dir"
					done
					IFS="/"; for dir in $dirs_group_ro_create; do IFS="$ifs";
						chmod -R u=rw,go=r,a+X,g+s "$thisdir/$dir"
					done
					# Handle exception dirs to be updated if already there
					IFS="/"; for dir in $dirs_group_ro_update; do IFS="$ifs";
						if [ -e "$thisdir/$dir" ]; then
							chmod u=rw,go=r,a+X,g+s "$thisdir/$dir"
						fi
					done
					# Handle exception files to be updated if already there
					IFS="/"; for file in $files_group_ro_update; do IFS="$ifs";
						if [ -e "$thisdir/$file" ]; then
							chmod u=rw,go=r,g+s "$thisdir/$file"
						fi
					done
					# Handle exception dirs to be purged and recreated
					IFS="/"; for dir in $dirs_no_access_purge; do IFS="$ifs";
						rm -rf "$thisdir/$dir"
						mkdir -m a= "$thisdir/$dir"
						chown nobody: "$thisdir/$dir"
					done
					IFS="$ifs"
				done)
			done)
		done)
	done)

	# Deprecated share permissions
	for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/shares_win"`; do
		chgrp -R $user $dir
		chmod -R u=rw,g=rw,o=,ug+X,g+s $dir
	done
	for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/shares_mac"`; do
		chgrp -R $user $dir
		chmod -R u=rw,g=rw,o=,ug+X,g+s $dir
		rm -rf $dir/Network\ Trash\ Folder
		mkdir $dir/Network\ Trash\ Folder
		chown nobody: $dir/Network\ Trash\ Folder
		chmod a= $dir/Network\ Trash\ Folder
	done

	# Ftp shares permissions
	for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/ftp_$USER$"`; do
		chgrp -R $user $dir
		chmod -R ug=rw,o=r,a+X,g+s $dir
		rm -rf $dir/Network\ Trash\ Folder
		mkdir $dir/Network\ Trash\ Folder
		chown nobody: $dir/Network\ Trash\ Folder
		chmod a= $dir/Network\ Trash\ Folder
	done
	for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/ftp_${USER}_ro$"`; do
		chown -R $user: $dir
		chmod -R u=rw,go=r,a+X $dir
		rm -rf $dir/Network\ Trash\ Folder
		mkdir $dir/Network\ Trash\ Folder
		chown nobody: $dir/Network\ Trash\ Folder
		chmod a= $dir/Network\ Trash\ Folder
	done

	# Web shares permissions
	for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/web_"`; do
		chown -R $user: $dir
#		chmod -R u=rw,go=r,a+X $webdir
#TODO: Only cgi scripts (.cgi and .pl) should be executable
		chmod -R u+rw,go+r,a+X $dir
		# leftover from ancient times with another policy
		if [ $NETATALK ]; then
			rm -rf $dir/Network\ Trash\ Folder
		fi
	done
	
	# Web shares permissions
	for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/websites"`; do
		chown root: $dir
		chmod a=r,u+w,a+X $dir
	done
	for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/websites/"`; do
		chown -R $user: $dir
#		chmod -R u=rw,go=r,a+X $webdir
#TODO: Only cgi scripts (.cgi and .pl) should be executable
		chmod -R u+rw,go+r,a+X $dir
		# leftover from ancient times with another policy
		if [ $NETATALK ]; then
			rm -rf $dir/Network\ Trash\ Folder
		fi
	done
	for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webscripts"`; do
		chown root: $dir
		chmod a=r,u+w,a+X $dir
	done
	for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webscripts/"`; do
		chown -R $user: $dir
#		chmod -R u=rw,go=r,a+X $webdir
#TODO: Only cgi scripts (.cgi and .pl) should be executable
		chmod -R u+rw,go+r,a+X $dir
	done
	for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webdata"`; do
		chown $user: $dir
		chmod a=r,u+w,a+X $dir
	done
	for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webdata/"`; do
		chown -R $user: $dir
		chmod -R u=rw,go=,u+X $dir
	done
	for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webphpsites"`; do
		chown root: $dir
		chmod u=rw,go=r,a+X $dir
	done
	for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webphpsites/"`; do
		chown -R $user:www-data $dir
#		chmod -R ug=rw,o=r,a+X $dir
		chmod -R ug=rw,o=,ug+X $dir
	done
	for dir in `find $HOME -mindepth 1 -maxdepth 1 -type d | egrep "^$HOME/webphpdata"`; do
		chown root: $dir
		chmod a=r,u+w,a+X $dir
	done
	for dir in `find $HOME -mindepth 2 -maxdepth 2 -type d | egrep "^$HOME/webphpdata/"`; do
		chown -R $user:www-data $dir
		chmod -R ug=rw,o=,ug+X $dir
	done
	
	# Dummy user restrictions
	if [ -n "$REALUSERS_GROUPNAME" -a -n "$DUMMYSHAREDIR" -a -n "$DUMMYSHAREOWNER" -a -n "$DUMMYSHARENAME" ]; then
		[ -e $DUMMYSHAREDIR/$user ] \
			|| mkdir $DUMMYSHAREDIR/$user
		chown $DUMMYSHAREOWNER: $DUMMYSHAREDIR/$user
		chmod u=rw,go=r,a+X $DUMMYSHAREDIR/$user
		if [ -e $HOME/$DUMMYSHARENAME ]; then
			if [ -L $HOME/$DUMMYSHARENAME ]; then
				ln -sf $DUMMYSHAREDIR/$user $HOME/$DUMMYSHARENAME
				chown $user: $HOME/$DUMMYSHARENAME
			else
				echo "WARNING: $HOME/$DUMMYSHAREDIR exists already. Leaving it as is..."
			fi
		else
			ln -s $DUMMYSHAREDIR/$user $HOME/$DUMMYSHARENAME
			chown $user: $HOME/$DUMMYSHARENAME
		fi
		if [ -n "$DUMMYAPACHECFG" -a -n "$DUMMYAPACHESHAREDIR" ]; then
			if [ -f /etc/apache/include.d/$DUMMYAPACHECFG -a -x /etc/init.d/apache ]; then
				if [ -e /etc/apache/include.d/$DUMMYAPACHECFG-$user ]; then
					echo "/etc/apache/include.d/$DUMMYAPACHECFG-$user exists already. Ignoring..."
				else
					echo "# Created automatically by adduser.local
<Location /$DUMMYAPACHESHAREDIR/$user>
	<Limit GET POST>
		require user $user
	</Limit>
</Location>" \
						> /etc/apache/include.d/$DUMMYAPACHECFG-$user
					apache_reload_needed="1"
				fi
			fi
		fi
	fi

	echo "."
done

if [ $XCHANGE ]; then
	for USER in $(ls $XDIRREAL); do
		id $user >/dev/null 2>&1 || rm -rf $XDIRREAL/$user
	done
fi

if [ "$apache_reload_needed" ]; then
	apache_do_reload=""
	case runmode in
	    interactive)
		echo -n "Apache config changed. Reload Apache now (Y/n)? "
		read apache_reload
		case $apache_reload in
		    y|Y|"")
			apache_do_reload="1"
			;;
		esac
		;;
	    force)
		apache_do_reload="1"
		;;
	    *)
		echo "Apache config has changed. Remember to reload Apache...!"
		;;
	esac
	if "$apache_do_reload" ]; then
		/etc/init.d/apache force-reload
	fi
fi