# Copyright (C) 2005 FishGrove Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# 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 program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
# $Id: ApplicationManager.pm,v 1.16 2006/03/07 14:39:10 slash5234 Exp $

package Affelio::Managing::ApplicationManager;
{
    use strict;
    use lib("../../../extlib");    
    use Error qw(:try);
    use DBI;
    use Jcode;
    use lib("../../../lib/");
    use Affelio::misc::CGIError;
    use Affelio::misc::Encoding qw(db_encode db_decode);
    use Affelio::misc::Debug qw(debug_print);
    use Affelio::exception::DBException;
    use Affelio::exception::InvalidInputException;

    #######################################################################
    #Constructor
    #######################################################################
    sub new{
	my $class = shift;
	my $af = shift;
	my %apps=();

	debug_print("ApplicationManager::new: start.");
	my $self = {af => $af,
		    apps => %apps
		    };

	bless $self, $class;

	#########################
	#Load applications
	load_applications($self);

	debug_print("ApplicationManager::new: end.");
	return $self;
    }

    ######################################################################
    #rename_title
    ######################################################################
    sub rename_title{
	my $self = shift;
	my $af = $self->{af};
	my $appid = shift;
	my $title = shift;

	#############################
	#DB access
	#############################
	my $query = "update $af->{site__dbtbl_prefix}_CORE_apps set install_title = '$title' WHERE appid = $appid";
	
	my $sth;
	eval{
	    $sth = $af->getDB->prepare($query);
	    $sth->execute();
	};
	if($@){
	    throw Affelio::exception::DBException($af->getDB->errstr);
	}
	debug_print("ApplicationManager::rename_title: DB access done.");
	
	#############################
	#loadl_application
	#############################
	$af->getAM->load_applications();
	
	debug_print("ApplicationManager::rename_title: end.");
	
    }


    ######################################################################
    #uninstall_app
    ######################################################################
    sub uninstall_app{
	my $self = shift;
	my $af = $self->{af};
	my $app_id = shift;
	my $install_name = shift;

	#############################
	#DB access
	#############################
	my $query = "delete from $af->{site__dbtbl_prefix}_CORE_apps where appid = $app_id";
	my $sth;
	eval{
	    $sth = $af->getDB->prepare($query);
	    $sth->execute();
	};
	if($@){
	    throw Affelio::exception::DBException($af->getDB->errstr);
	}
	debug_print("ApplicationManager::uninstall_app: DB access done.");
	
	#############################
	#case: AFE2
	#  .htaccess operation
	#############################
	debug_print("ApplicationManager::uninstall_app to AFE2? [$self->{site__farm_mode}]");
	if($af->{site__farm_mode} eq "AFE2"){
	    debug_print("ApplicationManager::uninstall_app to AFE2...");
	    $af->{farm_con}->uninstall_app(Username => $af->{site__username},
					   InstallName => $install_name);
	}

	#############################
	#loadl_application
	#############################
	$af->getAM->load_applications();
	
	debug_print("ApplicationManager::uninstall_app: end.");
    }

    
    ######################################################################
    #install_app
    ######################################################################
    sub install_app{
	my $self = shift;
	my $af = $self->{af};
	my $app_dir = shift;
	my $app_dir_abs = shift;
	my $app_region = shift;
	my $install_name = shift;
	my $install_title = shift;

	debug_print("ApplicationManager::install_app start.");

	#############################
	#Read .cfg file
	#############################
	my $cfg = Config::Tiny->new();
	my $cfg_path = "";
	$cfg_path = "$app_dir_abs/AF_app.cfg";
	$cfg = Config::Tiny->read($cfg_path);

	if(!$cfg){
	    throw Affelio::exception::InvalidInputException("Could not open $app_dir_abs/AF_app.cfg");
	}
	debug_print("ApplicationManager::install_app opened config file");

	#############################
	#prep data
	#############################
	#install_name
	#install_title
	my $app_URI = $cfg->{application}->{app_URI};
	my $app_name = $cfg->{application}->{app_name};
	my $app_version = $cfg->{application}->{app_version};
	my $app_desc = $cfg->{application}->{app_desc};
	my $app_author = $cfg->{application}->{app_author};
	my $guest_index = $cfg->{application}->{guest_index};
	my $owner_index = $cfg->{application}->{owner_index};
	my $action_types = $cfg->{application}->{action_types};
	my $action_types_desc = $cfg->{application}->{action_types_desc};

	debug_print("ApplicationManager::install_app data prep done.");

	#############################
	#DB access: check the same install_name
	#############################
	my $query0 = "select * from $af->{site__dbtbl_prefix}_CORE_apps where install_name = '$install_name'";
	my $sth0;
	eval{
	    $sth0 = $af->getDB->prepare($query0);
	    $sth0->execute();
	};
	if($@){
	    throw Affelio::exception::DBException($af->getDB->errstr);
	}
	my @array0= $sth0->fetchrow_array;
	if(@array0){
	    throw Affelio::exception::InvalidInputException("Duplicated name");
	}
	debug_print("ApplicationManager::install_app DB check done.");


	#############################
	#DB access
	#############################
	my $query = "insert into $af->{site__dbtbl_prefix}_CORE_apps(install_name, install_title, app_URI, app_name, app_version, app_desc, app_author, guest_index, owner_index, action_types, action_types_desc) values (?,?,?,?,?,?,?,?,?,?,?)";
	
	my $sth;
	eval{
	    $sth = $af->getDB->prepare($query);
	    $sth->execute($install_name, $install_title,
			  $app_URI, $app_name, $app_version,
			  $app_desc, $app_author,
			  $guest_index, $owner_index,
			  $action_types, $action_types_desc);
	};
	if($@){
	    throw Affelio::exception::DBException($af->getDB->errstr);
	}

	debug_print("ApplicationManager::install_app DB access done.");

	#############################
	#loadl_application
	#############################
	$af->getAM->load_applications();

	#############################
	#case: AFE2
	#  .htaccess operation
	#############################
	debug_print("ApplicationManager::install_app to AFE2? [$self->{site__farm_mode}]");
	if($af->{site__farm_mode} eq "AFE2"){
	    debug_print("ApplicationManager::install_app to AFE2...");
	    $af->{farm_con}->install_app(Username => $af->{site__username},
					 AppDir => $app_dir,
					 AppDirAbs => $app_dir_abs,
					 AppRegion => $app_region,
					 InstallName => $install_name);
	}

	#############################
	#prep userdata/ directory
	#############################
	$af->getAM->prepare_app_userdata_dir($install_name);

	#############################
	#prep app_perm_table
	#############################
	$af->getAM->prepare_app_perm_table($install_name);

	debug_print("ApplicationManager::intsall_app prep app table done.");
	debug_print("ApplicationManager::install_app end.");
    }


    ######################################################################
    #prepare_app_userdata_dir
    ######################################################################
    sub prepare_app_userdata_dir{
	my $self = shift;
	my $af = $self->{af};
	my $install_name = shift;

	############################
	#create userdata directory as needed
	############################
	if(-e "$af->{site__user_dir}/appdata/$install_name"){
	}else{
	    if (-d "$af->{site__user_dir}/appdata/"){
		if (-w "$af->{site__user_dir}/appdata/"){
		    my $ret =
			mkdir("$af->{site__user_dir}/appdata/$install_name", 0777);
		    if(!$ret){
			throw Affelio::exception::IOException("Cannot make userdata/appdata/$install_name!");
		    }
		}else{
		    throw Affelio::exception::IOException("Cannot make userdata/appdata/ is NOT writable!");
		}
	    }else{
		my $ret =
		    mkdir("$af->{site__user_dir}/appdata/", 0777);
		if(!$ret){
		    throw Affelio::exception::IOException("Cannot make userdata/appdata/!");
		}
		$ret =
		    mkdir("$af->{site__user_dir}/appdata/$install_name", 0777);
		if(!$ret){
		    throw Affelio::exception::IOException("Cannot make userdata/appdata/$install_name!");
		}
	    }
	}
    }


    ######################################################################
    #load_applications
    ######################################################################
    sub load_applications{
	my $self = shift;
	my $af = $self->{af};

	debug_print("ApplicationManager::load_apps: start.");

	$self->{apps} = ();

	##############################
	#Access apps DB
	##############################
	my $query = "select appid, install_name, install_title, app_URI, app_name, app_version, app_desc, app_author, guest_index, owner_index, action_types, action_types_desc FROM $af->{site__dbtbl_prefix}_CORE_apps";
	my $sth;
	eval{
	    $sth = $af->getDB->prepare($query);
	    $sth->execute;
	};
	if($@){
	    throw Affelio::exception::DBException($af->getDB->errstr);
	}

	debug_print("ApplicationManager::load_apps: Access Apps DB done.");

	##################################
	#For each application in DB...
	##################################
	my @row = ();
	while(my ($t_appid, $t_inst_name, $t_inst_title, $t_app_URI,
		  $t_app_name, $t_app_version, $t_app_desc, $t_app_author, 
		  $t_guest_index, $t_owner_index,
		  $t_action_types, $t_action_types_desc) 
	      = $sth->fetchrow_array){

	    ##################################
	    #Add two default actions
	    ##################################
	    my @this_app_action_types =();
	    @this_app_action_types =split(',\s', $t_action_types);
	    unshift(@this_app_action_types, "DF_access");
	    unshift(@this_app_action_types, "DF_visibility");

	    my @this_app_action_types_desc =();
	    @this_app_action_types_desc =split(',', $t_action_types_desc);
	    unshift(@this_app_action_types_desc, '<AF_M text="DF_access">');
	    unshift(@this_app_action_types_desc, '<AF_M text="DF_visibility">');

	    ##################################
	    #Store into Affelio's hash
	    ##################################
	    $self->{apps}->{$t_inst_name}
	    = {'app_id' => $t_appid,
	       'app_URI' => $t_app_URI,
	       'app_name' => $t_app_name,
	       'app_desc' => $t_app_desc,
	       'app_version' => $t_app_version,
	       'app_author' => $t_app_author,
	       'guest_index' => $t_guest_index,
	       'owner_index' => $t_owner_index,
	       #
	       'action_types' => \@this_app_action_types,
	       'action_types_desc' => \@this_app_action_types_desc,
	       #
	       'install_name' => $t_inst_name,
	       'install_title' => $t_inst_title
	       };

	    debug_print("ApplicationManager::load:"); 
	    debug_print("\tapp_id=$self->{apps}->{$t_inst_name}->{app_id}\n");
	    debug_print("\tapp_URI=$self->{apps}->{$t_inst_name}->{app_URI}\n");
	    debug_print("\tapp_name=$self->{apps}->{$t_inst_name}->{app_name}\n");
	    debug_print("\tapp_version=$self->{apps}->{$t_inst_name}->{app_version}\n");
	    debug_print("\tinst_name=$self->{apps}->{$t_inst_name}->{install_name}\n");
	    debug_print("\tinst_title=$self->{apps}->{$t_inst_name}->{install_title}\n");
	}#while

	debug_print("ApplicationManager::load_apps: end.");
    }


    ########################################################################
    #get_permission
    ########################################################################
    sub get_permission{         #return SQL_result
	my $self = shift;
	my $af = $self->{af};
	my $type = shift;               #arg(1) IN char* type
	my $id = shift;                 #arg(2) IN char* target_id
	my $app_name =shift;            #arg(3) application install_name

	debug_print("AppMan::get_permission type[$type] id[$id]");

	my $query = "select * FROM $af->{site__dbtbl_prefix}_" . $app_name 
	    ."_permission where type = '$type' and target_id = '$id'";
	debug_print("AppMan::get_permission end: q=[$query]");

	my $sth;
	eval{
	    $sth = $af->getDB->prepare($query);
	    $sth->execute;
	};
	if($@){
	    throw Affelio::exception::DBException($af->getDB->errstr);
	}

	debug_print("AppMan::get_permission end.");
	return($sth);
    }

    #####################################################################
    #get_summed_app_perm
    #####################################################################
    sub get_summed_app_perm{
	my $self = shift;               
	my $af = $self->{af};
	my $visitor_id = shift;         #arg(1) visitor_ID  
	my $visitor_mode = shift;       #arg(2) visitor_mode
	my $app_name =shift;            #arg(3) application install_name
	my $action_type =shift;         #arg(4) action_type

	my @ret_list=();

	debug_print("AppManager::get_summed_app_perm: start.");
	debug_print("AppManager::get_summed_app_perm: visitor_id  = $visitor_id");
	debug_print("AppManager::get_summed_app_perm: visitor_mode= $visitor_mode");
	debug_print("AppManager::get_summed_app_perm: app_name    = $app_name");
	debug_print("AppManager::get_summed_app_perm: action_type = $action_type");

	if($visitor_mode eq "f2" || $visitor_mode eq "pb"){
	    ####################
	    # f2 or PB
	    ####################

	    my $query = "select $action_type from $af->{site__dbtbl_prefix}_" . $app_name 
		."_permission where type = 'f' and target_id = '$visitor_mode'";

	    debug_print("AppManager::get_summed_app_perm: q=[$query]");
	    
	    my $sth = $af->getDB()->prepare($query) or 
		throw Affelio::exception::DBException("cannot insert");
	    $sth->execute() or 
		throw Affelio::exception::DBException("cannot insert");

	    my @row = $sth->fetchrow_array;

	    debug_print("AppManager::get_summed_app_perm: end [$row[0]]");
	    return($row[0]);

	}elsif($visitor_mode eq "self"){

	    return(1);

	}else{
	    ####################
	    # f1
	    ####################
	    #We will make 
	    #  perm(f1) OR Vx(perm(G))

	    #################
	    #(1) as a friend
	    my $query = "select $action_type from $af->{site__dbtbl_prefix}_" . $app_name 
		."_permission where type = 'f' and target_id = '$visitor_mode'";
	    my $sth = $af->getDB()->prepare($query) or 
		throw Affelio::exception::DBException("cannot insert");
	    $sth->execute() or 
		throw Affelio::exception::DBException("cannot insert");
	    my @row = $sth->fetchrow_array;
	    if($row[0] == 1){
		return(1);
	    }

	    #################
	    #(2) as a member of each group

	    #Get the visitor's UID
	    my ($t_uid, $t_afid, $t_nickname, $t_time,
		$t_pass, $t_intro, $t_pid, $t_lastupdated, $t_f2list) 
		= $af->getFM->get_friend_by_afid($visitor_id);

	    #Get the visitor's groups
	    my $SQL_result = $af->getGM->get_groups_by_uid($t_uid);

	    #For each group...
	    my @g_data=();
	    my $flag=0;
	    while(@g_data = $SQL_result->fetchrow_array) {	    
		my $gid = $g_data[0];

		my $query = "select $action_type from $af->{site__dbtbl_prefix}_" . $app_name 
		    ."_permission where type = 'g' and target_id = '$gid'";
		my $sth = $af->getDB()->prepare($query) or 
		    throw Affelio::exception::DBException("cannot insert");
		$sth->execute() or 
		    throw Affelio::exception::DBException("cannot insert");
		my @row = $sth->fetchrow_array;

		if($row[0] ==1){
		    $flag=1;
		}
	    }

	    return($flag);

	}

    }

    ######################################################################
    #get_all_permission
    ######################################################################
    sub get_all_permission{
	my $self = shift;
	my $app_name = shift;          #arg(1) app install_name

	debug_print("AppMan::get_all_premission: start");
	my $af = $self->{af};

	##############################
	#retrieve all permission records from DB
	my $query = "SELECT * FROM $af->{site__dbtbl_prefix}_" . $app_name . '_permission';
	my $sth;
	eval{
	    $sth = $af->getDB()->prepare($query);
	    $sth->execute;
	};
	if($@){
	    throw Affelio::exception::DBException($af->getDB()->errstr);
	}

	debug_print("AppMan::get_all_premission: end");
	return($sth);
    }

    ######################################################################
    #prepare_app_perm_table     Check Appliation Permission Table 
    ######################################################################
    sub prepare_app_perm_table{
	my $self = shift;
	my $af = $self->{af};
	my $caller = shift;   #application install name

	#Does my application's permission table already exist?
	my $my_table_name = "$af->{site__dbtbl_prefix}_" . $caller . "_permission"; 
	debug_print("AppManager::check_table: table = [".$my_table_name."]");

	my $query = "SELECT * FROM " . $my_table_name;
	eval{
	    my $sth = $af->getDB->prepare($query);
	    my @dummy = $sth->execute();
	};
	if($@){
	    debug_print("AppManager::check_table: [$@]");
	
            #############################################
	    #Table of this application does not exist!
	    #Thus, we will make the table

	    my $create_table_SQL="CREATE TABLE $my_table_name (pid INTEGER, type TEXT, target_id  TEXT, ";
	    my $new_rec_SQL="insert into $my_table_name(pid, type, target_id,";

	    my $num_action_types 
		= @{ $self->{apps}->{$caller}->{action_types} };

	    my $i;
	    for($i=0; $i < $num_action_types; $i++){
		$create_table_SQL .= 
		    ${ $self->{apps}->{$caller}->{action_types} }[$i];
		$create_table_SQL .= " INTEGER,"; 

		$new_rec_SQL .= 
		    ${ $self->{apps}->{$caller}->{action_types} }[$i];
		$new_rec_SQL .= ","; 
	    } 
	    chop($create_table_SQL);   #Delete "," at the end.
	    $create_table_SQL .= ") ";
	    chop($new_rec_SQL);   #Delete "," at the end.
	    $new_rec_SQL .= ")";

	    debug_print("AppManager::check_table: create_SQL = [". $create_table_SQL. "]");

	    my $sth = $af->getDB()->prepare($create_table_SQL) or 
		throw Affelio::exception::DBException("cannot create table");
	    $sth->execute() or 
		throw Affelio::exception::DBException("cannot create table");

	    debug_print("AppManager::check_table: created the table!");

	    #############################################
	    #Synchronized the table
	    # Find all records from AFuser_CORE_permission and
	    # prepare 0-filled records into my table
	    my $CORE_perm_tbl = $af->getPERM->get_all_permission();
	    while( my($pid, $type, $target, $dummy) = $CORE_perm_tbl->fetchrow_array ){

		my $SQL = $new_rec_SQL . " values ('$pid','$type','$target',";
		$SQL .= "1,1,";
		for($i=2; $i < $num_action_types; $i++){
		    $SQL .= "0,";
		}
		chop($SQL);
		$SQL .= ")";
		
		debug_print("AppManager::check_table: insert_SQL = [".$SQL."]");
		my $sth = $af->getDB()->prepare($SQL) or 
		    throw Affelio::exception::DBException("cannot insert");
		$sth->execute() or 
		    throw Affelio::exception::DBException("cannot insert");

	    }


	}
	debug_print("AppManager::check_table: end.");
    }

    ######################################################################
    #update_permission
    ######################################################################
    sub update_permission{
	my $self = shift;
	my $af = $self->{af};

	my $app_name = shift;          #arg(1)
	my $gid = shift;               #arg(2)
	my $pid = shift;               #arg(3)
	my $hash_ref= shift;           #arg(4)

	############################
	#check permission existence
	############################
	my $query = "SELECT count(*) FROM $af->{site__dbtbl_prefix}_"
	    . $app_name . '_permission where pid =' . $pid;
	my $sth;
	eval{
	    $sth = $af->getDB->prepare($query);
	    $sth->execute();
	};
	if($@){
	    throw Affelio::exception::DBException($af->getDB->errstr);
	}
	my @row = $sth->fetchrow_array;
	my $retval= $row[0];

	############################
	#INSERT or UPDATE?
	############################
	if($retval == 0){
	    debug_print("AppManager::update_permission record does not exist");
	    debug_print("AppManager::update_permission We will make it.");
	    $query = "insert into $af->{site__dbtbl_prefix}_" . $app_name . "_permission(";
	    my $total_col="pid, type, target_id,";
	    my $total_val="$pid, 'g', $gid,";
	    while (my ($action_type, $value) = each(%{$hash_ref}) ) {
		$total_col .= "$action_type,";
		$total_val .= "$value,";
	    }
	    chop($total_col);
	    chop($total_val);
	    $query = $query . $total_col . ") values (" . $total_val . ")";
	}else{
	    $query = "update $af->{site__dbtbl_prefix}_" . $app_name . "_permission set ";
	    while (my ($action_type, $value) = each(%{$hash_ref}) ) {
		$query .= "$action_type=$value,";
	    }
	    chop($query);
	    $query .= " where pid=$pid";
	}
	debug_print("AppManager::update_permission q=[$query]");

	#access DB
	my $sth;
	eval{
	    $sth = $af->getDB()->prepare($query);
	    $sth->execute;
	};
	if($@){
	    throw Affelio::exception::DBException($af->getDB()->errstr);
	}

	#debug_print("AppManager::update_permission end.");
    }

    ######################################################################
    #get_unregistered_apps
    ######################################################################
    sub get_unregistered_apps{
	my $self = shift;
	my $af = $self->{af};
	my $array_ref= shift;           #arg(1) array reference

	my @app_topdirs=();
	my $app_topdir="";
	my $app_dir="";

	###########################################
	#Collect directories to explore
	if ($af->{site__farm_mode} eq "AFE2"){
	    #AFE2 mode
	    @app_topdirs = $af->{farm_con}->get_app_topdirs();
	}else{
	    #Standalone
	    push (@app_topdirs, "$af->{top_dir}/apps");
	}
	debug_print("AppManager::get_unreg_apps: [@app_topdirs]");

	###########################################
	#For each top directories...
	foreach $app_topdir (@app_topdirs) {
	    opendir(DIR, $app_topdir);

	    while (defined($app_dir = readdir(DIR))) {
		if( ($app_dir ne '.') 
		    && ($app_dir ne '..') 
		    && ($app_dir ne 'index.html') 
		    && ($app_dir ne 'sampleapp') 
		    && ($app_dir ne 'CVS')
		    ){

		    my $app_dir_abs
			= "$app_topdir/$app_dir";

		    ##################################
		    #For each found application directory
		    ##################################
 		    debug_print("AppManager::get_unreg_apps: [$app_dir]");

		    if( (!defined($af->getAM->{apps}->{$app_dir}))
			|| ($af->{site__farm_mode} eq "AFE2")
			){
			
			#Read AF_app.cfg file of install-ready applications.
			#In case of AFE2:  
			#    All apps. in affelio/apps/ dir. is always ready for install.
			#In case of Stand-alone and AFE:
			#    Only apps which is not registered as "installed" are ready.
			
			##################################
			#Open AF_app.cfg file
			##################################
			my $cfg = Config::Tiny->new();
			$cfg = Config::Tiny->read("$app_dir_abs/AF_app.cfg");
			if(!$cfg){ next; }

			#app_dir: directory this application exists
			#install_dir: destination directory
			#   Standalone case: install_dir = app_dir
			#   AFE2 case: install_dir = user-specified.
			#app_name: Application name
			#app_version: Application version
			#disabled_flag: if "install_dir" can be changed
			#               by user.
			my $app_URI = $cfg->{application}->{app_URI};
			my $app_name = $cfg->{application}->{app_name};
			my $app_version = $cfg->{application}->{app_version};
			my $app_desc = $cfg->{application}->{app_desc};
			my $guest_index = $cfg->{application}->{guest_index};
			my $owner_index = $cfg->{application}->{owner_index};
			
			if( (!$app_URI) || (!$app_name) || (!$app_version)
			    || (!$guest_index) || (!$owner_index)){
			    next;
			}
			
			##################################
			#Open AF_app.cfg file
			##################################
			my $operate_URL
			    ="admin.cgi?mode=config_apps&action=install_app";
			
			##################################
			#Flag : if install_dir can ben changed
			##################################
			my $disabled_flag;
			my $install_dir;
			if($af->{site__farm_mode} eq "AFE2"){
			    $install_dir = "";
			    $disabled_flag="";
			}else{
			    $install_dir = $app_dir;
			    $disabled_flag=" readonly";
			}

			my $app_region;
			$app_dir_abs =~ /([A-Za-z]*)Farm\/apps\/([A-Za-z]*)\//;
			$app_region = "$1Farm/apps/$2";

			##################################
			#Push into output_ref
			##################################
			push(@$array_ref,
			     {app_dir => $app_dir,
			      app_dir_abs => $app_dir_abs,
			      app_region => $app_region,
			      app_name => $app_name,
			      app_version => $app_version,
			      install_dir => $install_dir,
			      disabled_flag => $disabled_flag,
			      opURL => $operate_URL
			      } );

			debug_print("AppManager::get_unreg_apps: [$app_dir] [$app_dir_abs] [$app_region]");
			
		    } #if
		    
		}
	    } #while

	    close(DIR);

	}#foreach

    }

}
1;
