#!/bin/bash

# permtool (no options)
#
# Version 0.1
#
# Menu based tool to change permissions and ownership of directories and their 
# contents recursively, according to your configuration specified in the script
# header. You MUST CONFIGURE this script in the CONFIG section below !
# 
# First of all, you will be shown a complete overview of your configuration.
# While you're reading, the script already assembles a list of files which 
# would be changed, according to your configuration. But yet it does NO 
# modification at all.
# After the assembly has finished, you will be prompted to hit any key, to see
# now a menu like this:
# ------------------------------------------------------------------------
## Enter the exact key for the task you want to perform:
##
##  D .......  Show the list of directories that will be processed 
##  A .......  Modify access permissions (matching old ownership)
##  O .......  Modify ownership (not regarding access permissions)
##  L .......  Show the logfile
##
## Any other key will exit without any action.
# ------------------------------------------------------------------------
# Note: Modifying the access permissions will match against the ownership,
# while modifying the owner does not match the access permissions; therefore 
# consider to perform the access permissions task first, and modify ownership 
# later.
# The script generates unique logfiles by including the full date in the name,
# so it should be possible to back-trace any (configuration) mischief.
#
# WARNING ! This script is beta, there may be bugs. NO WARRANTY !
#
# TODO:
# (1) Needs more testing with filenames with special chars like blanks
#     Debugging: Look for the 'XXX:' marker.
#
# (C) This script is GPL version 2 or higher.

# ====================== CONFIG BEGIN ===========================

# Space seperated list of directories that will be searched recursively
# Absolute pathes, with no trailing '/' (like "/home/user/Works" ).
# A top dir will be proceeded itself, too.
top_dirs="/var/cache/wwwoffle"

# Space seperated list of directories that will be exluded (pruned).
# Subdirs will be excluded, too. Use bash '\' to break too long lines. 
prune_dirs="/var/cache/wwwoffle/html \
/var/cache/wwwoffle/monitor \
/var/cache/wwwoffle/local"

# Only files and directories matching these attributes will be modified:
old_owner=daemon
old_group=daemon
old_file_perm=644	# 644 = rw- r-- r-- 
old_dir_perm=755	# 755 = rwx r-x r-x

# The new settings of the matching files and directories
new_owner=proxy
new_group=proxy
new_file_perm=644	# 640 = rw- rw- r--
new_dir_perm=755	# 770 = rwx rwx --- 
			# 775 = rwx rwx r-x
# Logfile
log=/tmp/permtool_log
# automatically append unique date to logfile name:
log="$log-`date +%y.%m.%d__%H.%M.%S`"

# Temproary files
proceedlist=/tmp/permtool_proceedlist
# XXX DEBUG: comment out for debugging:
# prunelist=/tmp/permtool_prunelist

# Make proper
unalias chown chmod rm 2>/dev/null
echo "" > $log
rm -f $proceedlist; touch $proceedlist 
# XXX DEBUG: comment out for debugging:
# rm -f $prunelist; touch $prunelist 

# ===================== CONFIG END ================================

# ------------------  functions
function config_header ()
{
clear
cat << EOF
-----------------------------------------------------------------------
Directories to search recursively:
$top_dirs

Directories excluded from processing: 
$prune_dirs

old owner:			$old_owner
old group:     			$old_group
octal file permissions:      	$old_file_perm
octal directory permissions: 	$old_dir_perm

new owner:     			$new_owner
new group:     			$new_group
octal file permissions:      	$new_file_perm
octal directory permissions: 	$new_dir_perm

logfile: 			$log
-------------------------------------------------------------------------

EOF
}

function print_form ()	# print_form <prefix-string> <directory>
			# clean output of ownership or access permissions
{
case $1 in
 -owner) echo "DIR: $2  old=$old_owner:$old_group  new=$new_owner:$new_group";;
 -perm) echo "DIR: $2 old=$old_dir_perm  new=$new_dir_perm";;
esac
}


# ========== MAIN

clear 

# ---------- Check configuration

config_header

echo -n "This tool changes permissions and ownership of directories and their contents
recursively, according to your configuration specified in the script header.
You will be offered a menu after the preparations have finished. Note:
Because modifying the access permissions will match against the ownership,
consider to perform this task first, and modify ownership later.

Preparing file list. This may take a while -- please wait..."

# ---------- Preparing file lists

for dir in $top_dirs; do
  # XXX: Need sed for dir names like "Local\ Folders"  =|
  find $dir -type d | sed s/'\\'/'\\\\'/g \
  | ( while read dirname; do
    flag=ok
    for prunedir in $prune_dirs; do
	if ( echo "$dirname" | grep -q "^$prunedir" ); 
	then flag="prune"; break; fi
    done
    case $flag in
        ok) echo "$dirname" >> $proceedlist;;
        prune) ;; # XXX: DEBUG: echo "$dirname" >> $prunelist;;
    esac
  done )

done

echo -e "done.\n"
read -p "Hit any key to continue." -n1 a

# ---------- Menu

flag=loop

while [ $flag = "loop" ]; do

config_header
cat << EOF 
Enter the exact key for the task you want to perform:

  D .......  Show the list of directories that will be processed 
  A .......  Modify access permissions (matching old ownership)
  O .......  Modify ownership (not regarding access permissions)
  L .......  Show the logfile 

Any other key will exit without any action.

EOF

unset choice; read -n1 -p "Enter a key: " choice; clear

case $choice in

    d|D) cat $proceedlist | sort | less;;

    l|L) less $log;;

    A) 	echo "===== MODIFYING ACESS PERMISSIONS BEGIN (`date`) =====" | tee -a $log

	# XXX: again, sed for 'Local\ Folders' like names:
	cat $proceedlist | sed s/'\\'/'\\\\'/g | ( while read dir; do

	# chmod directory itself
	if [ ! -z "`find "$dir" -type d -maxdepth 0 -perm $old_dir_perm \
	-user $old_owner -group $old_group;`" ];
	 then print_form -perm "$dir"  | tee -a $log;
	 chmod $new_dir_perm "$dir" | tee -a $log
	fi

	# chwon directories' file content one (= the same) level deep
	find "$dir" -maxdepth 1 -type f -perm $old_file_perm \
	-user $old_owner -group $old_group \
	-exec chmod -c "$new_file_perm" {} \; | tee -a $log
	
	done )

	echo "===== MODIFYING ACESS PERMISSIONS END (`date`) =====" | tee -a $log
	read -p "------------------------------ Done. -------------------------------" a

	;;

    O)  echo "========== MODIFYING OWNERSHIP BEGIN (`date`) ==========" | tee -a $log
	
	# XXX: again, sed for 'Local\ Folders' like names:
	cat $proceedlist | sed s/'\\'/'\\\\'/g | ( while read dir; do

	# chown directory itself
	if [ ! -z "`find "$dir" -maxdepth 0 -user $old_owner -group $old_group;`" ];
	 then print_form -owner "$dir"  | tee -a $log;
	 chown --preserve-root $new_owner:$new_group "$dir" | tee -a $log
	fi

	# chwon directories' file content one (= the same) level deep
	find "$dir" -maxdepth 1 -type f -user $old_owner -group $old_group \
	-exec chown -c "$new_owner:$new_group" {} \; | tee -a $log
	
	done )
	echo "========== MODIFYING OWNERSHIP END (`date`) ==========" | tee -a $log
	read -p "------------------------------ Done. -------------------------------" a
	;;
    

	*) flag="exit";;

esac;

done


# ---------- Finish

echo -e "\nBye.\n"; 
exit 0
