#!/bin/sh

#Set "DEREF_DEBUG_CONSOLE=1" to trigger debug mode:
#1.DEREF_CONSOLE() can print debug message to console
DEREF_DEBUG_CONSOLE=1

#Set "DEREF_DEBUG_CONSOLE=1" to trigger debug mode:
#1.DEREF_LOGGER() can print debug message to syslog
DEREF_DEBUG_LOGGER=1

BATCH_DEREF_LOCK="/tmp/obj_de_ref/EXEC_LOCK"
CGI_ERROR_MSG="/tmp/cgi_error_msg"
CGI_DIALOG_MSG="/tmp/cgi_dialog_msg"

#initialize related files
echo -n >$CGI_ERROR_MSG		#-18 normal message box
echo -n >$CGI_DIALOG_MSG	#-19 dialog box


########################################################################################################################################################
#Format of an Entry:
#[table name]="[Name of category shown in msg]:[uci config]:[executed script path]@[target function in the script]:[[uci Option 1],[uci Option 2],...]"
####Note:
##1.If there are more than one referrences, add the new entry behind the previous one subsequently with a GAPPING.
##2.The "GAPPING" is ONLY used to divide each entry here, do not use it inside an entry.
##3.The character '_' in column:[Name of category shown in msg] will be replaced by a gapping when it's shown in UI message

####uci config: time_object (Time object)
ref_time_object="\
IP_Filter:ip_filter_set_rule:/etc/init.d/ip_filter_set@apply:time_objs \
IPv6_Filter:ip6_filter_set_rule:/etc/init.d/ip6_filter_set@apply:time_objs \
APP_Filter:app_filter:/etc/init.d/app_filter@apply:time_objs \
URL_Filter:url_filter:/etc/init.d/url_filter@apply:time_objs \
QQ_Filter:qq_filter:/etc/init.d/qq_filter@apply:time_obj \
Session_Limit:connlimit:/etc/init.d/connlimit@apply:time_objs \
Bandwidth_Management:bandwidth_limit:/etc/init.d/bandwidth_limit@apply:time_objs"
#PS:refered by [WAN schedule reconnect] or [schedule reboot] will still forbid deletion

####uci config: time_object (Time group)
ref_time_group="\
IP_Filter:ip_filter_set_rule:/etc/init.d/ip_filter_set@apply:time_grps \
IPv6_Filter:ip6_filter_set_rule:/etc/init.d/ip6_filter_set@apply:time_grps \
APP_Filter:app_filter:/etc/init.d/app_filter@apply:time_grps \
URL_Filter:url_filter:/etc/init.d/url_filter@apply:time_grps \
QQ_Filter:qq_filter:/etc/init.d/qq_filter@apply:time_obj \
Session_Limit:connlimit:/etc/init.d/connlimit@apply:time_grps \
Bandwidth_Management:bandwidth_limit:/etc/init.d/bandwidth_limit@apply:time_grps"
#PS:[WAN schedule reconnect] and [schedule reboot] does not incldue time group

####uci config: country_object (Country object)
ref_country_object="IP_Filter:ip_filter_set_rule:/etc/init.d/ip_filter_set@apply:src_ctry_obj,dst_ctry_obj"

####uci config: keyword_object (Keyword Object)
ref_keyword_object="URL_Filter:url_filter:/etc/init.d/url_filter@apply:whitelist,blacklist"

####uci config: dns_object (DNS object)
ref_dns_object="\
IP_Filter:ip_filter_set_rule:/etc/init.d/ip_filter_set@apply:dst_dns_obj \
WAN_Load_Balance:lb_rule:/etc/init.d/lb_rule@apply:dst_dns_obj"

####uci config: fext_object (File extention object)
ref_fext_object="URL_Filter:url_filter:/etc/init.d/url_filter@apply:fextobjects_pass,fextobjects"

####uci config: category_object (Web category object)
ref_category_object="URL_Filter:url_filter:/etc/init.d/url_filter@apply:webcategory"

####uci config: cn_webcategoryt (China web category object)
ref_cncategory_object="URL_Filter:url_filter:/etc/init.d/url_filter@apply:cn_webcategory"

####uci config: app_object (App object)
ref_app_object="APP_Filter:app_filter:/etc/init.d/app_filter@apply:appobjects"

####uci config: service_object (Service object/group)
ref_srv_group="\
IP_Filter:ip_filter_set_rule:/etc/init.d/ip_filter_set@apply:service_grp \
IPv6_Filter:ip6_filter_set_rule:/etc/init.d/ip6_filter_set@apply:service_grp \
DMZ_Host:dmz:/etc/init.d/dmz@apply:servicetype \
QoS_Rule:packet_mark_lan:/etc/init.d/packet_mark@apply:servicetype"

ref_srv_object="\
IP_Filter:ip_filter_set_rule:/etc/init.d/ip_filter_set@apply:service_obj \
IPv6_Filter:ip6_filter_set_rule:/etc/init.d/ip6_filter_set@apply:service_obj \
DMZ_Host:dmz:/etc/init.d/dmz@apply:servicetype \
QoS_Rule:packet_mark_lan:/etc/init.d/packet_mark@apply:servicetype"

####uci config: ip_object (IPv4 group)
ref_ip_group_ip4="\
IP_Filter:ip_filter_set_rule:/etc/init.d/ip_filter_set@apply:src_ip_grp,dst_ip_grp \
WAN_Load_Balance:lb_rule:/etc/init.d/lb_rule@apply:src_ip_grp,dst_ip_grp \
DMZ_Host:dmz:/etc/init.d/dmz@apply:dst_ip_grp \
Address_Mapping:addr_mapv2:/etc/init.d/addr_map@apply:src_ip_grp \
APP_Filter:app_filter:/etc/init.d/app_filter@apply:ip_grp \
URL_Filter:url_filter:/etc/init.d/url_filter@apply:ip_grp \
QQ_Filter:qq_filter:/etc/init.d/qq_filter@apply:src_group \
Web_Portal_Whitelist:general_conf:/etc/init.d/base_configuration@apply:whitelist \
QoS_Rule:packet_mark_lan:/etc/init.d/packet_mark@apply:sourceip,destip \
Session_Limit:connlimit:/etc/init.d/connlimit@apply:ip_grp \
Bandwidth_Management:bandwidth_limit:/etc/init.d/bandwidth_limit@apply:ip_grp"

####uci config: ip_object (IPv4 object)
ref_ip_object_ip4="\
IP_Filter:ip_filter_set_rule:/etc/init.d/ip_filter_set@apply:src_ip_obj,dst_ip_obj \
WAN_Load_Balance:lb_rule:/etc/init.d/lb_rule@apply:src_ip_obj,dst_ip_obj \
DMZ_Host:dmz:/etc/init.d/dmz@apply:dst_ip_obj \
Address_Mapping:addr_mapv2:/etc/init.d/addr_map@apply:src_ip_obj \
APP_Filter:app_filter:/etc/init.d/app_filter@apply:ip_obj \
URL_Filter:url_filter:/etc/init.d/url_filter@apply:ip_obj \
QQ_Filter:qq_filter:/etc/init.d/qq_filter@apply:src_group \
Web_Portal_Whitelist:general_conf:/etc/init.d/base_configuration@apply:whitelist \
QoS_Rule:packet_mark_lan:/etc/init.d/packet_mark@apply:sourceip,destip \
Session_Limit:connlimit:/etc/init.d/connlimit@apply:ip_obj \
Bandwidth_Management:bandwidth_limit:/etc/init.d/bandwidth_limit@apply:ip_obj"

####uci config: ip_object (IPv6 object)
ref_ip_object_ip6="IPv6_Filter:ip6_filter_set_rule:/etc/init.d/ip6_filter_set@apply:src_ip_obj,dst_ip_obj"

####uci config: qq_object (QQ object)
ref_qq_object="QQ_Filter:qq_filter:/etc/init.d/qq_filter@apply:qq_obj_pass,qq_obj_block"

####uci config: qq_object (QQ group)
ref_qq_group="QQ_Filter:qq_filter:/etc/init.d/qq_filter@apply:qq_obj_pass,qq_obj_block"

####uci config: appuser (User Profile)
ref_user_profile="\
IP_Filter:ip_filter_set_rule:/etc/init.d/ip_filter_set@apply:src_usr_obj,dst_usr_obj \
APP_Filter:app_filter:/etc/init.d/app_filter@apply:usr_obj \
URL_Filter:url_filter:/etc/init.d/url_filter@apply:usr_obj \
VPN_Profile:pptp_l2l_din:/etc/init.d/pptp_l2l_din@apply:username"

####uci config: appuser (User Group)
ref_user_group="\
IP_Filter:ip_filter_set_rule:/etc/init.d/ip_filter_set@apply:src_usr_grp,dst_usr_grp \
APP_Filter:app_filter:/etc/init.d/app_filter@apply:usr_grp \
URL_Filter:url_filter:/etc/init.d/url_filter@apply:usr_grp"

####uci config: ldap
ref_ldap="\
IP_Filter:ip_filter_set_rule:/etc/init.d/ip_filter_set@apply:ldap_src_grp,ldap_dst_grp \
APP_Filter:app_filter:/etc/init.d/app_filter@apply:ldap_usr_grp \
URL_Filter:url_filter:/etc/init.d/url_filter@apply:ldap_usr_grp"

########################################################################################################################################################
DEREF_LOGGER()
{
	[ "$DEREF_DEBUG_LOGGER" = "1" ] || return
	echo "logger \"[Batched-\$exec_dtime][$1]: $2\"" >>$BATCH_DEREF_FILE
}

DEREF_CONSOLE()
{
	[ "$DEREF_DEBUG_CONSOLE" = "1" ] || return
	echo "echo \"[Batched-\$exec_dtime][$1]: $2\" >/dev/console" >>$BATCH_DEREF_FILE
}

######################### BATCH FILE INIT/TREM ##########################################
#initialize dereference worksheet
BATCH_DEREF_INIT()
{
	uci_config=$1
	echo "#!/bin/sh" >$BATCH_DEREF_FILE
	chmod 755 "$BATCH_DEREF_FILE"
	echo "lock $BATCH_DEREF_LOCK" >>$BATCH_DEREF_FILE
	echo "exec_dtime=`date +%Y/%m/%d-%H:%M:%S`" >>$BATCH_DEREF_FILE
	DEREF_LOGGER "$uci_config" "LOCK BATCH:($BATCH_DEREF_FILE)"
	DEREF_CONSOLE "$uci_config" "LOCK BATCH:($BATCH_DEREF_FILE)"
	echo "exec_func_list=\"\"" >>$BATCH_DEREF_FILE
	echo "need_deref=0" >>$BATCH_DEREF_FILE
}

BATCH_DEREF_TERM()
{
	uci_config=$1
	echo "uci commit $uci_config" >>$BATCH_DEREF_FILE
	DEREF_CONSOLE "$uci_config" "Job finished, COMMIT"
	DEREF_LOGGER "$uci_config" "Job finished, COMMIT"
	#Final: release lock and remove self when job's finished
	echo "lock -u $BATCH_DEREF_LOCK" >>$BATCH_DEREF_FILE
	DEREF_CONSOLE "$uci_config" "UNLOCK BATCH:($BATCH_DEREF_FILE)"
	DEREF_LOGGER "$uci_config" "UNLOCK BATCH:($BATCH_DEREF_FILE)"
	#print something as a token of response to web
	echo "echo 0" >>$BATCH_DEREF_FILE
	echo "rm $BATCH_DEREF_FILE" >>$BATCH_DEREF_FILE
}

######################### SUB_ACTION ################################################
act_del()
{
	DEREF_CONSOLE "$uci_config" "Delete $item in config=$func_cfg | section=$mem | option=$option"
	DEREF_LOGGER "$uci_config" "Delete $item in config=$func_cfg | section=$mem | option=$option"
	echo "uci delete $func_cfg.$mem.$option=$item" >>$BATCH_DEREF_FILE
}

act_mod()
{
	DEREF_CONSOLE "$uci_config" "update $item in config=$func_cfg | section=$mem | option=$option"
	DEREF_LOGGER "$uci_config" "update $item in config=$func_cfg | section=$mem | option=$option"
	echo "uci set $func_cfg.$mem.tag=$dtime" >>$BATCH_DEREF_FILE
}


#########################################################################
#####
# This function handles following steps:
# 1.Filter all possible configs(defined at above) to get a list of refernecing
# 2.Do uci dereference by deleting item from uci option (batch file)
# 3.Setup a list for refernecing script apply (batch file)
filter_deref_param()
{
	item="$1"
	uci_config="$2"
	sub_action="$4"
	
	#Add final uci deletion in batch file
	[ "$sub_action" = "act_del" ] && echo "uci delete $uci_config.$1" >>$BATCH_DEREF_FILE
	
	for func_table in $3 ;do
		local profile_hit_flag=0
		func_name=`echo $func_table |cut -d ':' -f 1`
		func_name=`echo $func_name |tr '_'  ' '`
		func_cfg=`echo $func_table |cut -d ':' -f 2`
		func_exe=`echo $func_table |cut -d ':' -f 3`
		func_opt=`echo $func_table |cut -d ':' -f 4`
		func_opt=`echo "$func_opt" |tr ','  ' '`
		exec_func_list="$exec_func_list""$func_exe "
		for option in $func_opt ;do
			rules=`uci filter ${func_cfg} ${option} ${item}`
			if [ "$rules" ]; then
				for mem in $rules; do
					eval "$sub_action"
				done
				need_deref=1
				rules=`echo $rules |tr ' '  ','`
				[ "$profile_hit_flag" = "0" ] && {
					echo -n "<b><li>[$func_name]</b> profiles:<b>$rules</b> has an unresolved reference to the object.</li><br>" >>$CGI_DIALOG_MSG
					profile_hit_flag=1		#let message only shows once time by the same object
				}
			fi
		done
	done
	if [ "$need_deref" = "1" ] ;then
		if [ -n "$exec_func_list" ] ;then
			for cmd in $exec_func_list ;do
				cmd=`echo "$cmd" |tr '@' ' '`
				DEREF_CONSOLE "$uci_config" "$cmd"
				DEREF_LOGGER "$uci_config" "$cmd"
				echo "$cmd" >>$BATCH_DEREF_FILE
			done
		fi
		if [ "$sub_action" = "act_mod" ] ;then
			echo -n "<b>Note:<br>All references has been updated automatically, it may take a while to effect.</b><br>" >>$CGI_ERROR_MSG
		elif [ "$sub_action" = "act_del" ] ;then
			#echo -n "<b>Note:<br>Deletion is not permitted until all references are removed completely.</b><br>" >>$CGI_DIALOG_MSG
			echo -n "<b>Warn:<br>a. Press 'OK' button can resovle above references automatically.<br>b. Auto-dereference may take a while to effect.</b>" >>$CGI_DIALOG_MSG
		fi
	fi
}
