#!/usr/bin/perl

######################################
#			             #
#	     EZDB v 3.02  ©          #
#	                             #
#			             #
#          By Stephane Barde   	     #
#        (webmaster@ezperl.com)      #
#	     January 31 2000         #
#				     #	
#     http://www.ezperl.com	     #
#				     #												 
######################################
#  ATTENTION CETTE VERSION EST MODIFIEE PAR AHAAWEB AFIN DE
#            DE CONTENIR DANS LE SCRIPT LE TAG DE FIN DE TABLEAU D AFFICHAGE DES LIGNES
#            DE MASQUER LE BOUTON FERMER CET ENREGISTREMENT
# COPYRIGHT NOTICE:
#
# Copyright 1998-2001 Stephane Barde.  All Rights Reserved.
#
# This program is being distributed as a FREEWARE. 
#
# It may be used and modified by anyone, as long as this copyright notice and the header
# above remain intact, but any usage should be registered.  (See the
# chapter XIII- for registration information.)  By using this
# program you agree to indemnify Stephane Barde from any liability.
#
# Selling the code for this program without prior written consent is
# expressly forbidden.  Obtain permission before redistributing this
# program over the Internet or in any other medium.  In all cases
# copyright and header must remain intact.
#
# Contributions are welcome and will be used exclusively to enhance
# the script (contact EZ Perl at webmaster@ezperl.com)

# I would off course appreciate to have some feedback about the
# use you are doing with this script.

# It also would be nice to make a link to the EZ Perl site:
# http://www.ezperl.com

# VERSION HISTORY:

# 3.02 1/31/01
# - Binary uploads with NT. 
# - Updated examples set.
#
# 3.01 11/17/00
# -External query bug fixed
# -<header> and <footer> parsing fixed in the line display 
# -Category Assignment right added at the group level
# -<select> form tag parsing fixed
# -HTML template at group level fixed
# -EzTree new global variables added
#
# 3.0 10/30/00
# - Bad word parsing (reject add/edit) 
# - Bulk update fixed + file_name=~s/ /_/g; 
# - Password expiration 
# - EzTree optional 
# - Password reminders 
# - header-footer replaced by a single HTML template
# - cart system 
# - crypted pwd 
# - ~date, ~group, ~group_owner. Must use _*date, _*owner... and _~date,... to display special fields 
# - Global vars interface
# - IP address login restrictions 
# -  Invalid login attempt 
# - Order by insertion date sorting fixed
# - html_line_display at group level 
# - cookie session check 
# - html_line_display with and <header> and <footer> tags
# - Field submission blocking at group level 
# - Field default value at group level 
# - Language Pack 
# - <select> form elements 
#
# 2.63 9/25/00
# - headers/footers for login, auhorize and connnected phases
#
# 2.62 9/22/00
# - Table_group_form updated within the package
# - Image upload backward compatibility
#
# 2.61 8/30/00
# - Bulk deletions
# - Reverse sorting
# - Textarea fixed in file generated from wizard
# - Record protection based on one database field
# - No match html page
# - Bulk update fixed and name_file_after scans for spaces
#
# 2.6 7/14/00
# - Version # added
#		 - Crypted session #
#		 - Multiple default accesses using session=~/^default/i
#		 - IP check optional
#		 - Script name can be changed
#		 - 'loggout' is shown instead of 'login' once logged
#		 - order_by in the url using %%%%ob=field_name
#		 - _RECORD_COUNTER_ and _KEYWORD_ parsed in the display_line files and returning
#		 the number of search results and the keywords entered.
#		 - Auto Upgrade from 2.x to 2.6 in the wizard
#		 - EzTree ©
#		 - EzTree_fields field added to tables
#		 - *date used as special field for date stamp
#		 - _CONTEXT_ parsed in the headers, footers, display and form files.
#		 - Bug fixed on the order_by routine, on textarea fields generation from the wizard
#		 - special form name is now 'ezform' (ezrdb_from => ezform for relational imports)
#
# 2.5 12/25/99
#		 - Cursors (relational display)
#		 - Direct Full Display parameter usable in the URL
#		 - _LOGIN_ and _SESSION_ usable when displaying the db form
#		 - Select form elements parsed only for column name is used in a <select> tag
#		 - File generation: named after columns, extension configurable.
# 2.1b 11/07/99
#		 - Parameters in the command line
#		   for queries with max_record_no
# 2.1 08/15/99
#		 - Static HTML output
#		 - EZ Wizards
#		 - Order By Statement
#		 - Image Upload
#		 - Headers and footers at group level
#		 - Control over the direct Full display
#		 - Text Color for Default display
#		 - Multiple Selections
#
# 2.0 03/20/99
#		 - Templates for mail notification.
#		 - Line Mode Dislay automatically recognise <tr> tags
#		   for nice table formatting
#		 - HTML file autogeneration
#		 - Cascading additions (ex: Member Account Generation)
#
# 2.0 PR1 02/18/99
#	   	 - Relational flat databases.
#		 - Display Mode configurable from the search engine
#		 - Accuracy of the error messages
#		 - Possibility to create member account
#		 - Display line mode vs. tables
#
# 1.5  01/01/99
#	 	 - First Shareware release
#		 - Setup Analyser
#		 - Javascript added to handle the problem of checkboxes
#		 - Some bug fixed (Modify vs.Full display mode).
#		 - Search revised.
#		 - Email Notification.
#		 - Viewing restictions option at group level.
#		 - GUI enhanced: menu bar to navigate between system db.
#		 - Abbility to go to the login page with table data.
#		 - Go to connect screen directly after login.
#		 - Show authorized table at connection.
#		 - Display mode configurable at group level.
#		 - Separate folder for system db
#		 - Feedback utility removed (useless with v1.3)
#		 - Pop-down menu for connection.
#		 - Indexed fields
# 1.3  12/10/98
#	   	 - Numerous bug fixed
#		 - Search engine enhanced: line mode + many options
#		 - Headers and Footers
#		 - Mandatory fields and Unique Constraint
#		 - HTML configurable at group level
#		 - Support default values for html fields
#		 - HTML fields in read only access when fisplaying a form
#		 - Aliases for table path
#		 - Log options at table level
#
# 1.21 11/06/98
#	   	 - Search page by page updated
#		 - Search result sorted in alphabetical order
#
# 1.2  10/28/98  
#		 - sub display_feedback
#		 - decrease size of error message
#		 - enhanced search engine: added the following functions:
#		   =,=~,=^,!=,!~,!^ plus case sensitivity
#		 - Auditing function implemented
#		 - Exit after error message
#
# 1.1  10/01/98  New User Interface + numerous bug fixed
#
# 1.0  09/11/98  FIRST RELEASE

$|=1;



require 5.004;

eval {
require "ezdb_setup.pl";
require "ez_$language.pl";
require "ezdb_lib.pl";
require "ezhtml.pl";
require "ezwizard.pl";

};

if ($@) {print $@} #{ &display_error_message(&get_msg(0).": $@"); }

&read_form;


#############################################################

if ($ENV{'QUERY_STRING'} eq "setup") {$setup_on?&setup:&display_error_message(&get_msg(6))}

##   extension is in format:
##   $script_name?table_name+context+phase&user_group
##


($internal,$external,$search_parameters)=split/%%/, $ENV{'QUERY_STRING'};

($from,$to)=split/~/, $external;

($access,$session,$page,$words)=split/\&/, $internal;

$words=~ s/\+/ /g;

($table,$context,$phase,$key,$select)=split/\+/, $access;


if (($external ne "")&&($external !~ /^cart_id/)) {&handle_cookie; }



##############################################################
##		 The main script			    ##
##############################################################


if ($context eq "password") 
{
	if ($phase eq 'entry') {&display_html('password.html');&display_output;exit}
	elsif ($phase eq 'update') 
	{
		&password_update;
		if ($password_updated) {&display_error_message(&get_msg(72))}
		else {&display_error_message(&get_msg(71))}
	}
	elsif ($phase eq 'reminder') {&display_html('password_reminder.html');&display_output;exit }
	elsif ($phase eq 'send_reminder') 
	{
		&password_reminder;
		if ($password_sent) {&display_error_message(&get_msg(70))}
		else {&display_error_message(&get_msg(71))}
	}
}


&get_setup;
$ok=&security_check;
my $message;

# start page

if ((($session eq "login") && ($table eq "connect")) || (($session eq "") && ($table eq "")))
{$message=&get_msg(1)}

# If we call the wizard, we create a faked table

if ($context eq "ezwizard") {$real_table=$table;$table="."}

# if we are asked to attempt a new connection

if ($table eq "") {$message.=&get_msg(2)}
elsif ($table eq "connected") {
	$display_connected=1;
	$table=$in{'table'};
	
	# if the table does not exist
	if (! -e $in{'table'}) {&get_group_setup;&html_menu;&display_error_message(&get_msg(3));}

	&check_acces_right_to_db;
	&security_check;
	}

&get_group_setup;

# if we are asked to authorize a new user session

if ($session eq "authorize")
	{$session=&check_valid_user;
	if ($session eq "0") {$session="login";$message=&get_msg(4);}
	else {
		unless ($phase ne '') {$message=&get_msg(5)} 
		if ($table ne "") 
		{
			$hide_menu=1;
			undef $message;
			&check_acces_right_to_db;
			&security_check;
			&get_group_setup;
			$display_connected=1 unless $phase;
		}
		else {$force_connect=1}
		}
	}


# Display the menu if requested

unless ($hide_menu) {&html_menu;}

if ($print_back_internal_link) {$content.=$back_internal_link}

# Show connection result if necessary

if ((($table eq "connect")&&($session ne "login"))||($force_connect)) {&connect_db;}
elsif ($display_connected) {&display_html('user_connected.html')}

# Display error message if any

if ($message ne "") {&display_error_message($message);}

# Display login screen 

if (($session eq "login")&&($table ne "connect")
	|| ($context eq "login")&&($table ne "connect") ) {&display_html('login.html')}


############################################################
# If we are asked to access a user defined table 	   
#							
# The phase can be entry -> retrieve -> display -> process
# The context can be add, modify, search, rollback or delete
#
###########################################################


if (($context eq 'add')||($context eq 'modify')) {&check_submited_values}
	
unless (($table eq "")||($table eq "connect")) {

if ($user_logged eq "admin")
{
		
if ($context eq "global_variables") 
{
	if ($phase eq 'display') {&display_global_variables;exit}
	elsif ($phase eq 'process') 
	{
		&display_message(&get_msg(82));
		&process_global_variables;
		exit
	}
}

	
if ($context eq "ezwizard") {
	$wizard=1;
	if ($phase eq "step1") {&db_builder_form}
	elsif ($phase eq "step2") {&create_db}
	elsif ($phase eq "step3") {&build_form}
	elsif ($phase eq "step4") {&generate_html}
	else {&display_html('admin_menu.html')}
	}

elsif ($context eq "html_generate") {
	if ($phase eq "build") {&build_form}
	elsif ($phase eq "generate") {&generate_html}
	else {&entry_form}
}

elsif ($context eq "db_builder") {
	if ($phase eq "build") {&create_db}
	elsif ($phase eq "update") {&update_db}
	else {&db_builder_form}
}

elsif ($context eq "bulk_update") {
	if ($table_alias eq 'eztree') {&generate_eztree}
	else { &bulk_update_html}
}

elsif ($context eq "upgrade") {
	if ($phase eq 'done') {&upgrade}
	else { &upgrade_form}
}
}

if ($context eq 'selection') 
{
	if ($phase eq 'display') {&view_selection}
	elsif ($phase eq 'clear') {&clear_selection}
}

elsif ($phase eq "display") {
	if ($context eq "add") {
		if ($security[1]) {
		&display_html_form_for_add;
		}
		else { &display_error_message("$error_message{add}")}
		}

	elsif ($context eq "modify") {
		&generate_populated_form;}

	else {
		if ($select eq 'select') {&add_to_selection; &display_message(&get_msg(78))}
		
		&display_record;
				
		if ($context eq "delete") {
		&show_button("$script_name?$table_alias+$context+process+$key&$session",&get_msg(9));} 
		
		if ($context eq "search") {
		unless ($no_close_record) {&show_button("javascript:history.back();",&get_msg(7));} }
		
		
		} #end else
	}
	
elsif ($phase =~ /rollback/) {&rollback; if ($notify_rollback ne "") {&send_mail("$notify_rollback");}}

elsif ($phase eq "process") {

	if ($context eq "add") 
	{
	&check_mandatory;
	&check_duplicate;
	if ($bad_words) {&parse_bad_data}
	$key=&add_to_database(%in);
	
	
	if ($notify_add ne "") {&send_mail("$notify_add");}
	
	&display_message(&get_msg(10));
	
	&display_record;
	
	&add_external;
	
	}

	if ($context eq "delete") 
	{&delete_record;
	if ($notify_delete ne "") {&send_mail("$notify_delete");} }

	if ($context eq "modify") 
	{&modify_record;
	&display_record;
	if ($notify_modify ne "") {&send_mail("$notify_modify");}}

	} # end process

elsif (($phase eq "entry") && ( 
	(($context eq "modify") && ($security[2]))
	||(($context eq "delete") && ($security[3]))
	||(($context eq "search")) && ($security[0]))
	 ) 
	{ &display_html('ask_for_keyword.html') }


elsif (($phase eq "entry") && ($context eq "audit"))
{
	if ($user_group ne "admin_group") {&display_error_message(&get_msg(11))}
	else 
	{
		&display_html('audit_menu.html')
		&display_html('ask_for_keyword.html')
	} 
}
	
elsif (($phase eq "retrieve") && ($context eq "audit") && ($user_group eq "admin_group"))
	{&display_result_for_key;}
	
elsif (($phase =~ /(audit|deleted)_record/) && ($context eq "audit") && ($user_group eq "admin_group"))
	{&audit_table;}
	

elsif ((($context eq "modify") && !($security[2])) 
	|| (($context eq "delete") && !($security[3]))	
	|| (($context eq "search") && !($security[0])))
	{ &display_error_message($error_message{"$context"})}

	
elsif (($phase eq "retrieve") && (($context eq "modify")||($context eq "delete")||($context eq "search"))) {
	&display_result_for_key;}
	
elsif (($context eq 'delete')&&($phase eq 'bulk_delete')) {&bulk_deletion}	

} # end unless


&display_output;
exit(0);

###################################################
###################################################
##		SUBROUTINES    	  		 ##
###################################################
###################################################



#################################################
#		Read_Form			#
#################################################

sub read_form{

if ($ENV{'CONTENT_TYPE'}=~m|^multipart/form-data|)
{	
	use CGI;
	$form = new CGI;
	my $params = $form->Vars;
	%in;

	foreach $key ($form->param()) 
	{
		if (($key =~ /^file_/)||($key =~ /^image/))
		{
			if ($form->param($key) =~ /([^\/\\]+)$/)
			{
				$in{"$key"}=$1;
				$in{"$key"} =~ s/^\.+//;
				$key_handle=$key.'_handle';
		  		$in{"$key_handle"}= $form->param($key);
			}
  			else {$in{"$key"}=$form->param($key)}	  	
		}	
		else
		{
			@temp = split("\0",$params->{$key});
			if (@temp > 1)  {$in{"$key"}=join(', ',@temp)}
			else {$in{"$key"}=$form->param($key)}
		}
	}
}

else 
{
	read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
	# Split the name-value pairs
	@pairs = split(/&/, $buffer);
	foreach $pair (@pairs) 
	{
		local($name, $value) = split(/=/, $pair);
		$value =~ tr/+/ /;
		$name =~ tr/+/ /;
		$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
		$value =~ s/<!--(.|\n)*-->//g;
		
		if ($in{$name} && $value) {$in{$name}.=", ".$value} 
		else {$in{$name} = $value}
	}


} # end else

# just in case...
$ENV{'QUERY_STRING'}=~ s/<!--(.|\n)*-->//g;


}


#################################################
#	   get_no_of_column			#
#################################################

sub get_no_of_column{

open(DB,"<$_[0]");
flock(DB,1);
my @lines=<DB>;
close(DB);

my @temp=split /\Q$separator/, $lines[0];

return @temp;
}


#################################################
#	get_indexes_for_columns			#
#################################################

sub get_indexes_for_columns{

open(DB,"<$_[0]");
flock(DB,1);
my @lines=<DB>;
close(DB);

chomp $lines[0];
my @temp=split /\Q$separator/, $lines[0];

my @result;

foreach $field_to_display (@fields_displayed_for_result)
{
my $i=0;
foreach $cols (@temp) 
{$cols=~s/\W//g;

if (lc($cols) eq lc($field_to_display)) {push(@result,$i);}
$i++;
}

}
 return @result;
}

#################################################
#		display_html_form_for_add	#
#################################################
#  this is used to display the html form

sub display_html_form_for_add {

open(HTML, "<$html_form_path") || &display_error_message(&get_msg(12));
flock(HTML,1);
my @html = <HTML>;
close(HTML);

my $href="$script_name?$table_alias+add+process&$session";

my $global_line=join('',@html);
$global_line=~ s/!_/_/g;
$global_line=~ s/value=\"(_R_|_C_)/value=\"/g;
$global_line=~ s/value=\"\_\w+\s?(.+)?"/value=\"$1"/g;
$global_line=~ s/value=\"(.+)\s+(_R_|_C_|_\w+)/value=\"$1/g;
$global_line=~ s/_\w+\s?<\/textarea/<\/textarea/g;
$global_line=~ s/_CONTEXT_/$href/g;
$global_line=~ s/_M_\w+?://g;
$global_line=~ s/_M_//g;
$global_line=~ s/_L_\w+?://g;
$global_line=~ s/_L_//g;
$global_line=~ s/value="\w+?:(\w+)"/value="$1"/g;
$global_line=~ s/_R_//g;
$global_line=~ s/_C_//g;
$global_line=~ s/\|\|index:_(\w+)//g;
$global_line=~ s/name="%%(.+?)"/onClick="document.ezform.action+='%%$1'"/g;
$global_line=~ s/_SESSION_/$session/g;
$global_line=~s/_LOGIN_/$user_logged/g;
$global_line=~ s/_CONTEXT_/$context/g;
$global_line=~ s/_MENU_/$system_menu/;
$global_line=~ s/\s_\w+(\W)/ $1/g;

$content.=$global_line;

} # end subroutine;



#################################################
#		Check_mandatory			#
#################################################

sub check_mandatory {
	
my $missing;

foreach $field (@mandatory)
{
chomp $field;
if ($in{"$field"} eq "") {
	if ($missing eq "") {$missing=&get_msg(13);$missing.=$field}
	else {$missing.=", $field"}
	}
}

if ($missing ne "") {&display_error_message($missing)}

}


#################################################
#		return_lines			#
#################################################

sub return_lines {

open(DB,"<$_[0]");
flock(DB,1);
my @lines=<DB>;
close(DB);
	
return @lines;
}



#################################################
#		get_index			#
#################################################

sub get_index {

my @temp=split /\Q$separator/, $_[0];

my $i=0;
my %indexes;

for (@temp)
{
$indexes{"$_"}=$i;
$i++;
}

return %indexes;

}






#################################################
#		Check_duplicate			#
#################################################

sub check_duplicate {
	
my @lines=&return_lines("$table");
my %indexes=&get_index($lines[0]);

my %failed;

for (@unique) {$is_unique{"$_"}=1;}

foreach $line (@lines)
{
my @temp=split /\Q$separator/, $line;

	foreach $constraint (@unique)
	{
		my $ok=0;
		my @constraint_element=split/\+/, $constraint;
		my $count=@constraint_element;

		foreach $field (@constraint_element)
		{
		if ($in{"$field"} eq $temp[$indexes{"$field"}]) {$ok++}	
		}
		
		if ($ok == $count) {$is_unique{"$constraint"}=0};
	
	}
	
}

my $error_message="";

for (keys(%is_unique))
{
if ($is_unique{"$_"}==0) {my $msg=&get_msg(14);$error_message.=$msg.$_;}
}

if ($error_message ne "") {&display_error_message("$error_message")}
}


#################################################
#		get_indexed_field_list		#
#################################################

sub get_indexed_field_list {
	
open(IND, "<$system_file_path/index") || &display_error_message(&get_msg(15));
flock(IND,1);
@index_line=<IND>;
close(IND);

for (@index_line)
{
my @temp=split (/\|/);
if ($temp[1] eq $table_alias) {push (@indexed_field, $temp[2])}
}


}



#################################################
#	Add_To_Database				#
#################################################

sub add_to_database {

&load_default_values;

for (keys(%in)) {if ((/^image/)&&($in{"$_"} ne '')) {&upload_file("$_")} }

for (keys(%in)) {if ((/^file_/)&&($in{"$_"} ne '')&&($_ !~ /_handle$/)) {&upload_file("$_")} }

if ($table_alias eq 'user_data')  {$in{'password'}=crypt($in{'password'},'ez')}

$val=time();
my $pkey=$val;

my ($column_line,$rec)=&get_column_n_data($key);
my @columns=split /\Q$separator/, $column_line;

&get_indexed_field_list;

for ($i=1;$i<$no_of_column;$i++)
{
	my $line=$in{"$columns[$i]"};

	for ($columns[$i])
	{
		/^\*date$/ and do {$line=scalar(localtime(time))};
		/^~date$/ and do {$line=scalar(localtime(time))};
		/^\*group_owner$/ and do {$line=$user_group};
		/^~group_owner$/ and do {$line=$user_group};
		/^\*owner$/ and do {$line=$user_logged};
		/^~owner$/ and do {$line=$user_logged};
	}

	if (grep{$_ eq $columns[$i]} @indexed_field)
	{
		open(IND, ">$system_file_path/index") || &display_error_message(&get_msg(15));
		flock(IND,2);
		for (@index_line)
		{
			my @temp=split (/\|/);
			if ($temp[1] eq $table_alias) {chomp $temp[3];$line=$temp[3]++; print IND join('|',@temp),"\n";$in{"$columns[$i]"}=$line}
			else {print IND "$_";}
		}
		close(IND);
	}
	
	$line=~ s/.\n/<br>/g;
	$val.="$separator"."$line";
}


open(TABLE, ">>$table") || &display_error_message(&get_msg(16));
flock(TABLE,2);
print TABLE "$val\n";
close(TABLE);


$val.="\n";
if (($enable_log==1)&&($log_add==1)){ &update_log("Add");}

$in{'pkey'}=$pkey;
return $pkey;


} # end subroutine;



#################################################
#		Add_external			#
#################################################

sub add_external {

# if there is something to add to another table, we call add_external:

open(ADD, "<$system_file_path/add_external") || &display_error_message(&get_msg(17));
flock(ADD,1);
@lines=<ADD>;
close(ADD);

shift @lines;
%in_int=%in;
undef %in;
$internal_table=$table_alias;

for (@lines)
{
my @temp=split(/\|/);

if ($temp[1] eq $internal_table) {
	chomp $temp[3];
	my @tab=split /<br>/, $temp[3];
	
	for (@tab)
	{
		if ($_ eq "") {next}
		my ($ref_int,$ref_ext)=split(/->/);
		if ($ref_ext eq "") {next}
		if ($ref_int =~ /\((.+)\)/) {$in{"$ref_ext"}=$1;}
		else {$in{"$ref_ext"}=$in_int{"$ref_int"};}
		
	}
	$table=$temp[2];
	$context='external_add';
	&get_setup;
	$key='';
	&check_duplicate;
	&add_to_database;
}

undef %in;

} #end for


}


#################################################
#		send_mail			#
#################################################

sub send_mail {

my @notify_tab=split /<br>/, $_[0];

my $verb;
if ($context eq "add") {$verb="added"}
elsif ($context eq "modify") {$verb="modified"}
elsif ($context eq "delete") {$verb="deleted"}
elsif ($context eq "rollback") {$verb="rollbacked"}

my $to;
my $body="Hi\n\nAn Item has been $verb in the $table_alias database\n\n";
my $default_subject="Item $verb to the $table_alias database";

for (@notify_tab)
{
my ($condition,$send_to,$show,$subject)=split(/->/);
unless ($subject) {$subject=$default_subject}
my @show_items= split /\+/, $show;
my $ok=0;
my $template_flag=0;

$send_to=~s/\((.+?)\)/$in{"$1"}/g;

if ($show =~ /^\(Template:(.+)?\)/) 
{ 
	my $template=$1;
  $template=~ s/^\s//;
  open(TEMPL,"<./mail_templates/$template");
  flock(TEMPL,1);
  my @template_lines =<TEMPL>;
  close(TEMPL);
  $body=join('',@template_lines);
  $template_flag=1;
}


if ($condition eq "*") {$ok=1;}
else {
  $ok=1;
  
  my @all_conditions=split /\+/, $condition;
  for (@all_conditions)
  { 
  	
    if (/(\w+)(=|!=)(.+)/) 
     { 
     	my $left_op=$1;
     	if ($left_op eq "_LOGIN_"){$left_op=~ s/_LOGIN_/$user_logged/;}
     	elsif($left_op eq "_GROUP_") {$left_op=~ s/_GROUP_/$user_group/;}
     	else { $left_op=$in{"$1"}; }
      
     	my $op=$2; 
      
     	if ($op eq "=") {$op="eq"}
     	if ($op eq "!=") {$op="ne"}

     	unless (eval "$left_op $op $3") {$ok=0; last;}  
     }
     else {$ok=0; last;}  
   }
}

if ($ok) 
{$to.=$send_to.","; 

if ($template_flag) {$body=~ s/%_(\w+)_%/$in{"$1"}/g;}
else {
	for (@show_items) 
	{/(.+):(.+)/;
	my $left=$1;
	$left=~ s/[^\w\$\'\{\}\s\t]//g;
	my $alias=eval($left);
	unless (eval($left)) {$alias=$left}
	$body.="$alias: ".$in{"$2"}."\n";
	} 
$body.="\n\n$mail_signature";
} #end else

$to=~ s/,$//;

if ($to ne "") {
open(MAIL,"| $mail_routine_path -t -n -oi") || &display_error_message(&get_msg(18));
print MAIL "To: $to\n";
print MAIL "From: $mail_from\n";
print MAIL "Subject: $subject\n\n";
print MAIL "$body";

close(MAIL); }
}

}



}


#################################################
#	  	display_record			#
#################################################

sub display_record {

my ($column_line,$record_line) = &get_column_n_data($key);

# if we are asked to display an old record for auditing:
if ($in{'old_record'} ne "") {$record_line=$in{'old_record'}; }
#-->

chomp $column_line;
chomp $record_line;
@column=split /\Q$separator/, $column_line;

@record=split /\Q$separator/, $record_line;

#$column[$#column]=~s/\W//g;

$j=0;
for (@column)
{
$rec{"$_"}=$record[$j];
$in{"$_"}=$record[$j];
$j++;
}

if (($password_field ne '')&&($context eq 'search')) {&check_password}

sub bylength {length $a <=> length $b;}
@column=reverse sort bylength @column;

open(HTML, "<$html_display_path") || &display_error_message(&get_msg(19));
flock(HTML,1);
my @html = <HTML>;
close(HTML);

my $global_line=join('',@html);

while ($global_line =~ /<cursor value="(.+?)(=|=\~|\!|=\^|\!\~|\!\^)(.+?):(.+?)>(.+?)">((.|\n)+?)<\/cursor>/)
{ 	

	my $link_field=$1; 
	my $op=$2;
	my $fkey=$3;
	
	my $ftable=$4;
	$_=$5; 
	@ffields=split(/,/);
	my $cursor_html=$6; 
	$cursor_html=~ s/<cursor_header>((.|\n)+?)<\/cursor_header>//;
	my $cursor_html_header=$1;
	$cursor_html=~ s/<cursor_footer>((.|\n)+?)<\/cursor_footer>//;
	my $cursor_html_footer=$1;
	my $cursor_html_output;
	
	open(DB,"<$ftable");
	flock(DB,1);
	local @lines=<DB>;
	close(DB);
	$keyword[0]=$fkey.$op.$rec{"$link_field"}; 
	my $no_of_col=@fields_displayed_for_result;
	@tab=split /\Q$separator/, $lines[0];
	my $i=0;
	foreach $field_name (@tab) {chomp $field_name; $column_index{"$field_name"}=$i;$i++;}

	$col_name=shift(@lines); 
	
	$fquery=1; 
	&keyword_processing;
	
	my $j=0; 
	for (@{$fres{$ffields[0]}})
	{
		my $cursor_line_html=$cursor_html;
		$cursor_line_html=~s/_%(.+?)%/${$fres{$1}}[$j]/g;
		$cursor_html_output.=$cursor_line_html; 
		$j++;
	}
	if ($cursor_html_output eq '') {undef $cursor_html_header;undef $cursor_html_footer;}
	
	$global_line =~ s/<cursor value="(.+?)(\W+?)(.+?):(.+?)>(.+?)">((.|\n)+?)<\/cursor>/$cursor_html_header $cursor_html_output $cursor_html_footer/;
}



$i=0;
for (@column)
{
	if ((/^image/)&&($rec{"$column[$i]"} eq ''))
	{$global_line=~ s/<img src="_$column[$i]"(.+?)>//g}
	
	if ($column[$i] ne "") 
	{
		my $text="_$column[$i]";
		$text=~s/\*/\\\*/;
		$global_line=~ s/(\W)$text(\W)/$1$rec{"$column[$i]"}$2/g;
	}
 
	if (($column[$i] eq $name_file_after)&&($context eq 'delete')) 
	{
		$old_static_file_name=$rec{"$column[$i]"};
		$old_static_file_name=~s/ /_/g
	}
	
	$i++
}

$global_line =~ s/<form(.+?)_DETAIL_(.+?)<\/form>//;

$_=$global_line;

if (/_MENU_/) { &system_menu; $global_line=~ s/_MENU_/$system_menu/;}

$global_line=~ s/_SESSION_/$session/g;
$global_line=~ s/_TABLE_/$table/g;
$global_line=~ s/_LOGIN_/$user_logged/g;
$global_line=~ s/_CONTEXT_/$context/g;


# removing link to add to selection:
if ($display_selection) {$global_line=~s/<a href=".+?\+select&\w+?".+?<\/a>//sgi}


while ($global_line =~ /href="%%(.+?)~(.+?):(.+?)"/)
{
	my $val="'".$rec{"$1"}."'"; $val=~s/\s/\+/g; 
  	if ($val eq "''") {$global_line =~s/<a(.+?)?href="%%(.+?)<\/a>//;}
  	else {$global_line=~ s/href="%%(.+?)~(.+?):(.+?)"/href="$script_name?$2+search+retrieve&$session&1-1&$3=$val"/; }
}


if (($global_line =~ /_CLOSE_/)&&($context ne 'add'))
{ 
	my $close="<form method=post action=\"javascript:history.back();\"><input type=submit value=\"CLOSE RECORD\"></form>";
	$global_line =~ s/_CLOSE_/$close/;
	$no_close_record=1;
}
else {$global_line=~ s/_CLOSE_//}


$content.=$global_line;


if (($html_output_dir ne "")&&(($context eq "add")||($context eq "modify")))
{
	if (! -e $html_output_dir) {&display_error_message("The Output Directory $html_output_dir doesn't exist");}
	else {
		my $filename=$rec{$name_file_after};
		$filename=~s/ /_/g;
		
		unlink "$html_output_dir/$old_static_file_name.$files_extension";
		
		open(HTML,">$html_output_dir/$filename.$files_extension")||&display_error_message(&get_msg(20));
		flock(HTML,2);
		print HTML $global_line;
		close(HTML);
		my $msg1=&get_msg(21);
		my $msg2=&get_msg(22);
		$content.= qq!
		<br><br><b><font face="Verdana, Arial, Helvetica, sans-serif" size="2">
		$msg1
		<a href=\"$html_output_url/$key.html\">
		$msg2
		</a></font>
		!;
	}
			
}


#added in v2.6 for categorization: work for admin_group only.
if ( ($context eq 'add') 
	&& ($table_alias !~ /^(tables|user_data|add_external|index|table_group|user_rights)$/)
	&& ($allow_eztree)
	&& ($eztree_on) )
	{&assign}



} # end subroutine

#################################################
#	  		Assign			#
#################################################

sub assign {
my $msg=&get_msg(23);
$content.= qq!
<br><br>
<table bgcolor="white" border=0><tr><td>
<a href="javascript:var w=window.open('./eztree.cgi?&assign=$table_alias:$key','','width=500,height=350,scrollbars=yes,resizable=yes')">
<font face="Verdana, Arial, Helvetica, sans-serif" size="2">$msg</font></a>
</td></tr></table>
!;
}

#################################################
#	  	Generate_Populated_Form		#
#################################################

sub generate_populated_form {

my $access_cookie;
if ($key < 0) {$key=-1*$key; $access_cookie=1;}
 
my ($column_line,$record_line) = &get_column_n_data($key);

$record_line=~ s/<br>/\n/g;

chomp $column_line; chomp $record_line;
my @column=split /\Q$separator/, $column_line;
my @record=split /\Q$separator/, $record_line;

$j=0;
for (@column)
{
$record[$j]=~ s/</&lt;/g;
$record[$j]=~ s/>/&gt;/g;
$record[$j]=~ s/"/&quot;/g;

if ($access_cookie) { $rec{"$_"}=$in{"$_"} }
else { $rec{"$_"}=$record[$j]; }
$j++;
}




open(HTML, "<$html_form_path") || &display_error_message(&get_msg(12));
flock(HTML,1);
my @html = <HTML>;
close(HTML);

my $global_line=join('',@html);

if ($next_context ne "") {$url_context=$next_context} else {$url_context="modify"}

my $href="$script_name?$table_alias+$url_context+process+$key&$session";
$global_line=~ s/((\w|\s)+)\|\|//g;
$global_line=~ s/index:_(\w+)/_$1/g;
$global_line=~ s/[^\.]selected>/>/gi;
$global_line=~ s/[^\.]checked>/>/gi;
$global_line=~ s/"Submit"/"Modify Record"/g;
$global_line=~ s/\_CONTEXT\_"/$href"/;
$global_line=~s/_SESSION_/$session/g;
$global_line=~s/_LOGIN_/$user_logged/g;
$global_line=~ s/_CONTEXT_/$context/g;
$global_line=~ s/name="%%(.+?)"/onClick="document.ezform.action+='%%$1'"/g;

$column[$#column]=~s/\W//g;
sub bylength {length $a <=> length $b;}
@column=reverse sort bylength @column;

for ($i=0;$i<$no_of_column;$i++)
{
my $ref="_".$column[$i];
my $ref_list="$column[$i]";
$value=$rec{"$column[$i]"};
$ref=~s/\*/\\\*/;

$_=$global_line;

if ($global_line =~ /<select name="$ref_list"/) 
{
	my @val=split /, /, $value;
	for (@val) 
	{ 
		$global_line=~ s/>_M_$ref_list:$_/ selected>$_/;
		$global_line=~ s/value="$ref_list:$_"/value="$_" selected/;
	}
	
	$global_line=~ s/value="$ref_list:$value"/value="$value" selected/;
	$global_line=~ s/>_L_$ref_list:$value/ selected>$value/;
	

	$global_line=~ s/_L_$ref_list://g;
	$global_line=~ s/_M_$ref_list://g;
	$global_line=~ s/"$ref_list:/"/g;

}

$global_line=~ s/\Qname=\"$ref_list\" value=\"_R_$value\"/name=\"$ref_list\" value=\"$value\" checked/;
$global_line=~ s/\Qname=\"$ref_list\" value="_C_$value\"/name="$ref_list\" value=\"$value\" checked/;


if ( (/$ref/)&&($ref ne "_")) 
{ 
	$global_line=~ s/<(.+)?!$ref(.+)?>/$value/;	
	$global_line=~ s/value="$ref"/value="$value"/;
	$global_line=~ s/value="$ref\s?([^"]+)"/value="$value"/;
	$global_line=~ s/>((\s|\[\|\])+)?$ref/>$value/;
	$global_line=~ s/(\W)$ref(\W)/$1$value$2/;
}


}

$global_line=~ s/_M_//g;
$global_line=~ s/_L_//g;
$global_line=~ s/_R_//g;
$global_line=~ s/_C_//g;
$global_line=~ s/_SESSION_/$session/g;

$_=$global_line;
if (/_MENU_/) { &system_menu; $global_line=~ s/_MENU_/$system_menu/;}

$content.= $global_line;
if ($eztree_on && ($table_alias !~ /^(tables|user_data|add_external|index|table_group|user_rights)$/)) {&assign}


} # end subroutine


#################################################
#		 get_column_n_data		#
#################################################
# return the reference line and the record line for the key entered

sub get_column_n_data {

my $keyword=$_[0];

open(TABLE, "<$table") || &display_error_message(&get_msg(16));
flock(TABLE,1);
my @lines = <TABLE>;
close(TABLE);


my $column= shift(@lines);
chomp $column;

for (@lines)
{
if (/^$keyword\D/) {$record=$_;last}
}

chomp $return;

return ($column,$record);
}



#################################################
#	Display_Result_For_Key			#
#################################################

sub display_result_for_key {
	
if ($page eq "") {$page=1; $range=$in{'max_record_no'}} else {($page,$range)=split /-/, $page}
if ($words ne "") {$in{'keyword'}=$words;$in{'keyword'}=~s/\+/ /g; } else {$words=$in{'keyword'}; $words=~s/ /\+/g;}
	
$in{'keyword'}=~s/^(\s)+//;	
$words=~s/^(\s)+//;	

if ($search_parameters ne "") 
{
	$_=$search_parameters;
	/ob=(\w+)/;
	#unless ($1 ne 'Yes') {$in{'order_by'}=$1;} /()/;
	$in{'order_by'}=$1; /()/;
	/dm=(Line|Full|Default|)/;
	$display_mode=$1;/()/;
	/cs=(Yes|No)/;
	$in{'case_sensitive'}=$1; /()/;
	/em=(Yes|No)/;
	$in{'exact_match'}=$1;/()/;
	/dfd=(Yes|No)/; 
	if ($1 eq 'Yes') {$direct_full_display='Yes';} /()/;
}

# check for default value from the tables db
if ($in{'order_by'} eq "") { $in{'order_by'}=$order_by }
# for compatibility with version < 2.1
if ($in{'order_by'} eq "") { $in{'order_by'}=$in{'order_by_date'} }
#We force the sorting by date of insertion if selected
if ($in{'order_by_date'} ne '') { undef $in{'order_by'} }

	
if ($cookie_key eq "") {$cookie_key=$key}

unless ( grep{$_ eq "case_sensitive"} keys(%in) ) {$in{'case_sensitive'}="No";}
unless ( (grep{$_ eq "max_record_no"} keys(%in))|| ($range ne "") ) {$in{'max_record_no'}='*';}
unless ( grep{$_ eq "exact_match"} keys(%in) ) {$in{'exact_match'}="No";}
unless ( grep{$_ eq "order_by"} keys(%in) ) {$in{'order_by'}="No";}
unless ( grep{$_ eq "keyword"} keys(%in) ) {$in{'keyword'}='*';}

if ($in{'display_mode'} ne "") { $display_mode=$in{'display_mode'} }

	
local $display;
if ($context eq "audit") {$display="audit_record"}
else {$display="display";}


open(TABLE, "<$table") || &display_error_message(&get_msg(16));
flock(TABLE,1);
local @lines = <TABLE>;
close(TABLE);


local $list_all=$in{'keyword'};

if ($restrictions ne "") 
{
	$restrictions =~ s/_LOGIN_/\'$user_logged\'/;
	$restrictions =~ s/_GROUP_/\'$user_group\'/;

	my @temp=split /\+/, $restrictions;
	
	foreach $condition (@temp)
	{
	$in{'keyword'}="restrict:$condition ".$in{'keyword'};
	$in{'keyword'}=~ s/\*$//;
	}

	if ($list_all eq "*") {$restriction_no=0;} else {$restriction_no=1;}
}

@keyword=split /\s+/, $in{'keyword'};

my $stop=@keyword;
my $r=0;
for ($k=0;$k<$stop;$k++)
{
	$_=$keyword[$r];
	if (/'$/) {$keyword[$r]=~s/'//g;next}	
	if (/(.+)?'((\w|\s)+)/) {$keyword[$r+1]=$keyword[$r]." ".$keyword[$r+1];splice(@keyword,$r,1);$r--;}
	$r++;
}

for (@keyword) { if (/(.+)?'((\w|\s)+)'/) {$keyword[$r]=$1.$2}	}


my $no_of_col=@fields_displayed_for_result;

if ($no_of_col==0) 
{
	$no_of_col=1;
	$_=$lines[0];
	/\w+\|(\w+)\|.+/;
	$fields_displayed_for_result[0]=$1;
	$color_for_search_result[0]="ffffff";
	$indexes_displayed_for_result[0]=1;
}

my $j=0;
my @color_for_text;
for (@color_for_search_result)
{ 
	my ($cell_color,$text_color)= split /\//;
	if ($cell_color eq "") {$cell_color="ffffff"}
	if ($text_color eq "") {$text_color="000000"}
	$color_for_search_result[$j]=$cell_color;
	$color_for_text[$j]=$text_color;
	$j++
}

local @tab=split /\Q$separator/, $lines[0];
my $i=0;
foreach $field_name (@tab) {chomp $field_name; $column_index{"$field_name"}=$i;$i++;}

$col_name=shift(@lines);

unless ($no_keyword_processing) {&keyword_processing}

local @sort_result;
foreach $result_line (keys %result) 
{
	my $value=$result{"$result_line"}."\:\:".$result_line; 
	push(@sort_result,$value)
}

$count_result=@sort_result;


if ($in{'order_by'} eq "Yes") {@sort_result=reverse sort @sort_result}
elsif ($order_by ne '') {&result_tab_sorting}

if ($sort_result[0] eq "")   # NO RESULT FOUND
{
	if ($no_match_html) 
	{
		open(HTML,"<$no_match_html")||&display_message(&get_msg(25));
		flock(1,HTML);
		my @html_lines=<HTML>;
		close(HTML);
		for (@html_lines) {$content.=$_}
	}
	else 
	{
		if ($display_selection) {&display_message(&get_msg(77))}
		else {&display_message(&get_msg(24))}
	}
}
else { # PRINTING SEARCH RESULT HEADERS
	if ( ( ($display_mode eq "Default") && (($count_result>1)||($direct_full_display eq "No")) ) 
		|| ($context eq "audit") ) 
	{
		# DISPLAY MODE FOR MORE THAN 1 RESULT OR 1 RESULT WITH NO DEFAULT FULL DISPLAY
		
		if ($display_selection) {&display_message(&get_msg(73))}
		else {&display_message(&get_msg(26))}
	
		if (($bulk_delete eq 'Yes')&&($context eq 'delete')) 
		{$content.= qq! <form method=post action="$script_name?$table_alias+delete+bulk_delete&$session"> !}
	
		$content.= qq!
		<center>
		<table border=1 cellspacing=0 cellpadding=0>
		<tr>
		!;

		for ($i=0;$i<$no_of_col;$i++) 
		{
			$content.= qq!
			<td bgcolor="#$color_for_search_result[$i]">
			<b>
			<font face="Verdana, Arial, Helvetica, sans-serif" size="2" color="#$color_for_text[$i]">
			$fields_label{"$fields_displayed_for_result[$i]"}</b>
			</font>
			</td>
			!;
		}

		if ($show_percent) {$content.= "<td width=7>Keywords Found</td>"}
	
		$content.= qq!
		<td bgcolor="#$color_for_search_result[$#color_for_search_result]">&nbsp;</td></tr>
		!;
	
	} # end if mode = Default

	else 
	{
		# LINE MODE (for 1 or more results found)
		
		if ($display_mode eq "Line") {$html_mode_path=$line_mode_html_path} 
		else {$html_mode_path=$html_display_path}
	
		open(HTML,"<$html_mode_path")||&display_error_message(&get_msg(19));
		flock(HTML,1);
		@html_line=<HTML>;
		close(HTML);
	
		
		$html_lines=join('',@html_line);
		
		if ($display_mode eq "Line")
		{
			my $tags=0;
			if ($html_lines =~ /<header>(.+)<\/header>/si) 
			{
				$content.=$1;
				$html_lines =~ s/<header>(.+)<\/header>//si;
				$tags++
			}
			if ($html_lines =~ /<footer>(.+)<\/footer>/si) 
			{
				$line_footer=$1;
				$html_lines =~ s/<footer>(.+)<\/footer>//si;
				$tags++
			}
			if ($tags) {$html_content=$html_lines}
		}
		
			
		
	}	


	my $k=0;

	if ($in{'max_record_no'} eq "\*") { $page=1; $range=@sort_result }

	for ($a=$range*($page-1);$a<$page*$range;$a++)
	{
		my @temp=split /::/, $sort_result[$a];
		my @fields= split /\Q$separator/, $temp[1];

		my $percentage=int(10000*$temp[0]/$no_of_keyword)/100;
		$k++;

		my $external_url;
		if ($external ne "")
		{ 
			if ($external !~ /^cart_id/) {$external_url="%%external_query~$cookie_key"}
  			else {$external_url=$external}
		}

		my $action="$script_name?$table_alias+$context+$display+$fields[0]&$session".$external_url;

		unless ( ($percentage==0) || (($percentage<100)&&($in{'exact_match'} eq "Yes")) )
		{
  			if ((($display_mode eq "Default")
  				&&(($count_result>1)||($direct_full_display eq "No")))
  				||($context eq "audit")) 
  			{
				# DISPLAY MODE FOR MORE THAN 1 RESULT OR 1 RESULT WITH NO DEFAULT FULL DISPLAY 
				
				$content.= "<tr>";

				for ($i=0;$i<$no_of_col;$i++) 
				{
					$content.= qq!
					<td bgcolor="#$color_for_search_result[$i]" valign=top>
					<font face="Verdana, Arial, Helvetica, sans-serif" size="2" color="#$color_for_text[$i]">
					$fields[$indexes_displayed_for_result[$i]]</font>
					</td>
					!;
				}

				if ($show_percent eq "Yes") { $content.= "<td valign=top>$percentage %</td>"}

				my $delete_checkbox;
				if (($bulk_delete eq 'Yes')&&($context eq 'delete')) 
				{
					$delete_box=qq! <input type=checkbox name="delete_$fields[0]" value=1>!;
					$content.= qq!
					<td valign=top bgcolor="#003399">
					<a method=post href="$action"> <font face="Verdana, Arial, Helvetica, sans-serif" size="2" style="text-decoration:none" color=white>?</font></a> $delete_box</td</tr>
					!;
				}
				else 
				{
					$content.= qq!
					<td valign=top bgcolor="#$color_for_search_result[$#color_for_search_result]">
					<form name="form$i" method=post action="$action">
					<input type=submit size=5 value=" ? ">$delete_box</td></form></tr>
					!;
				}
	
  			} # end if mode = Default
  		
  		elsif ( (($display_mode eq "Default")||($display_mode eq "Line"))
  			&& ($count_result==1) 
  			&& ($context ne "audit")
  			&& ($direct_full_display eq "Yes") )
			
		{
			# DISPLAYING 1 RESULT ONLY WITH DIRECT FULL DISPLAY
			
			$key=$fields[0];
    			if (($context eq "modify")&&($external eq "")) {&generate_populated_form}
			else 
			{
				if ($context eq "delete") 
				{
					&display_record;
					&show_button("$script_name?$table_alias+$context+process+$key&$session","DELETE RECORD")
				} 
		
				if (($context eq "search")||(($context eq "modify")&&($external ne ""))) 
				{
					if ($back_internal_link =~ /\+-1/) {$back_internal_link=~ s/\+-1&(.+)%%(.+?)"/\+$key&$1%%back_internal:$table~$cookie_key"/ }
					else {$back_internal_link=~ s/\+(\d+?)?&(.+?)%%(.+?)"/\+$key&$2%%back_internal:$table~$cookie_key"/}
		
					$content.= $back_internal_link;
					&display_record;	
		
					unless ($no_close_record) {&show_button("javascript:history.back();",&get_msg(7))} }
				}
  			}
	
  		else 
  		{ 
  			#!! Cursor processing do not work if result==1 and direct full display
  	
  			my $pkey=$fields[0];
  			$key=$fields[0];
			my ($column_line,$record_line) = &get_column_n_data($pkey);
			chomp $column_line;
			chomp $record_line;
			@column=split /\Q$separator/, $column_line;
	
	
			@record=split /\Q$separator/, $record_line;
			#$column[$#column]=~s/\W//g;
			
			$global_line=$html_content||join('',@html_line);

			
			$global_line=~ s/_DETAIL_/$action/g;
			$global_line=~ s/_PERCENTAGE_/$percentage %/g;
			$global_line=~ s/_MENU_//g;
			$global_line=~ s/_SESSION_/$session/g;


			for ($j=0;$j<@column;$j++) { $rec{"$column[$j]"}=$record[$j] }	
	
			sub bylength {length $a <=> length $b;}
			@column=reverse sort bylength @column;

			for (@column)
			{
				my $text="_$_";
				$text=~s/\*/\\\*/;
				if ($_ ne "") {$global_line=~ s/$text(\W)/$rec{$_}$1/g;}
			}
			
			$global_line =~ s/<cursor value="(.+?)(\W+?)(.+?):(.+?)>(.+?)">((.|\n)+?)<\/cursor>/$cursor_html_header $cursor_html_output $cursor_html_footer/;

			if ($global_line =~ /_CLOSE_/)
			{ 
				my $msg=&get_msg(7);
				my $close="<form method=post action=\"javascript:history.back();\"><input type=submit value=\"$msg\"></form>";
				$global_line =~ s/_CLOSE_/$close/;
				$no_close_record=1;
			}

			# removing link to add to selection:
			if ($display_selection) {$global_line=~s/<a href=".+?\+select&\w+?".+?<\/a>//sgi}
			
			$content.= $global_line;
			  	  	
		}

	} #end of unless

} # end for each record


} # end else of if no matches

if ((($display_mode eq "Default")&&(($count_result>1)||($direct_full_display eq "No")))||($context eq "audit")) {$content.= "</table></center>";}
$content.= $line_footer;

my $no_of_record=@sort_result;
my $page_prev=$page-1;
my $page_next=$page+1;
$words=~s/ /\+/g;
my $href_prev="<a href=\"$script_name?$table_alias+$context+$phase+$cookie_key&$session&$page_prev-$range&$words%%$external%%dm=$display_mode+cs=$in{'case_sensitive'}+em=$in{'exact_match'}+ob=$in{'order_by'}+dfd=$direct_full_display\">&lt;&lt;</a>&nbsp;";
if ($page==1) {$href_prev=""}
my $href_next="<a href=\"$script_name?$table_alias+$context+$phase+$cookie_key&$session&$page_next-$range&$words%%$external%%dm=$display_mode+cs=$in{'case_sensitive'}+em=$in{'exact_match'}+ob=$in{'order_by'}+dfd=$direct_full_display\">&gt;&gt;</a>&nbsp;";
if ($page*$range>=$no_of_record) {$href_next=""}

	
if (($bulk_delete eq 'Yes')&&($context eq 'delete')) { $content.= qq!<br><center><input type=submit value="Bulk Delete"> </form></center>!;}


if ($in{'max_record_no'} ne "*") 
{
	$content.= qq!
	</table>
	<center>$href_prev &nbsp; <b>Page $page</b> &nbsp; $href_next</center>
	!;
}


} # end of subroutine




#################################################
#		result_tab_sorting		#
#################################################

sub result_tab_sorting {

my (%sort_hash,@sort_index, @invert_sort_index,$i);

my @order_by;

if (($in{'order_by'} ne "")&&($in{'order_by'} ne "Yes"))
{
	$in{'order_by'}=~s/, /,/g;
	$in{'order_by'}=~s/,/--/g;
	@order_by=split /--/, $in{'order_by'};
}

$i=0;
for (@order_by) 
{
	if ($column_index{$_} eq '') {&display_error_message(&get_msg(27))}

	$sort_index[$i]=$column_index{$_}; 
	$i++
}

chomp $col_name;
foreach $field (split /\Q$separator/, $col_name) 
{
$_=$col_name;

if (($field ne "pkey")&&(! grep {$_ eq $field} @order_by)) { $sort_index[$i]=$column_index{$field};$i++;}
}

$i=0;
for (@sort_index) {$invert_sort_index{$sort_index[$i]}=$i; $i++}
	
for (@sort_result)
{
my @temp_colon=split(/::/);
chomp $temp_colon[1];
my @temp_pipe=split /\Q$separator/, $temp_colon[1];


# Here, we sort the data depending on the order_by clause
my @tab; my $tab_index=0;
for (@order_by) { push (@tab,$temp_pipe[$column_index{$_}]); }
for (@order_by) { splice (@temp_pipe,$column_index{$_},1) }

my $primary=shift (@temp_pipe);
push(@tab,@temp_pipe);

push @{ $sort_hash{"$temp_colon[0]"} } , join($separator,@tab).$separator.$primary;
} # end for @sort_result

my @clean_result;

foreach $percent (reverse (keys(%sort_hash)))
{
@{$sort_hash{"$percent"}}=sort @{$sort_hash{"$percent"}};


for (@{$sort_hash{"$percent"}}) 
{
	my @temp=split(/\Q$separator/);
	my @tab;
	for ($j=0;$j<$#temp;$j++) { $tab[$sort_index[$j]-1]=$temp[$j]}
	my $val=$percent."::".$temp[$#temp].$separator.join($separator,@tab);

	push(@clean_result, $val);
}

}

@sort_result=@clean_result;
if ($reverse_sort) {@sort_result=reverse @sort_result}
}



#################################################
#		 keyword_processing		#
#################################################

sub keyword_processing {

$no_of_keyword=@keyword-$restriction_no;
if ($in{'case_sensitive'} !~ /yes/i) {$case="i"}

$i=0;
LINE: foreach $line (@lines)
{
chomp $line;
	foreach $words (@keyword)
	{
		my $restriction;
		my $word=$words;
		$word=~s/\*/\\\*/;

		$_=$line;
		
	@temp=split (/\Q$separator/); 
	
	if ($word =~ /^restrict:/) { $word=~s/^restrict://;$restriction=1;}

	if (($list_all eq "\*")&&($restriction !=1)) { $result{"$_"}=1 ;}
	elsif ( $word =~ /(\*)?(\w+)(=|=~|==|<|>|<>|<=|>=|=\^|!=|!~|!\^)((\w|\s|\.|,|;|:|\?|\!|\$|%|=|\+|\/|\\|\&|\@|\#|\`|\(|\)|-)+)/ )
	{
		my $column_name=$1.$2;
		my $operator=$3; 
		my $data=$4; 

		my $field_no=$column_index{"$column_name"}; 
		
		# if we have restriction we jump to the next line if the data doesn't match the restriction
		if ($restriction == 1) 
			{ if ($temp[$field_no] ne $data) {next LINE;};
			  if ($list_all eq "*") {$result{"$_"}++}
			  next }

		if (! exists $column_index{"$column_name"}) {&display_error_message("The field $column_name was not found in the $table database"); exit(0);}
		
		if ($operator eq "=") {$operator=~s/=/=~/; $data="\/\^".$data."\$\/$case";}
		elsif ($operator eq "!=") {$operator=~s/!=/ne/; $data="\"$data\"";}
		elsif ($operator eq "=~") {$data="\/$data\/$case";}
		elsif ($operator eq "=^") {$operator="=~"; $data="\/\^$data\/$case";}
		elsif ($operator eq "!~") {$data="\/$data\/$case";}
		elsif ($operator eq "!\^") {$operator="!~"; $data="\/\^$data\/$case";}
		elsif ($operator eq "<>") {$operator="!=";}
					
		if (($operator eq "==") || ($operator eq "<=") || ($operator eq ">=") || ($operator eq "<>") || ($operator eq ">") || ($operator eq "<") )
			{ $compare_to= $temp[$field_no];}
			else { $compare_to= "'$temp[$field_no]'";}
		
    if (eval "$compare_to $operator $data") { 
    	
    			if ($fquery) 
    			{
    			for (@ffields)
    			{my $ffield_no=$column_index{"$_"};
    			push (@{$fres{$_}},$temp[$ffield_no])
    			}
    			}
			
			if ($result{"$_"} eq "") {$result{"$_"}=1} else {$result{"$_"}++}
			}
		
		elsif ($in{'exact_match'} eq "Yes") { delete $result{"$_"}; next LINE }
		
		next;
	
	}

	elsif ($case eq "i") {
		if (/$word/i) { if ($result{"$_"} eq "") {$result{"$_"}=1} else {$result{"$_"}++} }
		elsif ($in{'exact_match'} eq "Yes") { delete $result{"$_"}; next LINE }
		}
	elsif ($case ne "i") { 
		if  (/$word/) { if ($result{"$_"} eq "") {$result{"$_"}=1} else {$result{"$_"}++} }
		elsif ($in{'exact_match'} eq "Yes") { delete $result{"$_"}; next LINE }
		}
	
	} #end @words

$i++;
} #end for @keyword


}



#################################################
#		 Delete_Record			#
#################################################

sub delete_record {


open(TABLE, "<$table") || &display_error_message(&get_msg(16));
flock(TABLE,1);
my @lines = <TABLE>;
close(TABLE);



open(TABLE, ">$table") || &display_error_message(&get_msg(28));
flock(TABLE,2);
for (@lines)
{
if (/^$key/) {$val=$_} else {print TABLE "$_";}
}

close(TABLE);


if ($eztree_fields)
{
open(TREE, "<./my_db/eztree.csv") || &display_error_message(&get_msg(29));
flock(TREE,1);
my @tree_lines = <TREE>;
close(TREE);

open(TREE, ">./my_db/eztree.csv") || &display_error_message(&get_msg(30));
flock(TREE,2);
for (@tree_lines)
{
unless (/\d+?\|$key\|$table_alias/) {print TREE "$_";}
}

close(TREE);
} # end unless


if (($enable_log==1)&&($log_delete==1)){ &update_log("Delete");}

if (defined $html_output_dir) {unlink "$html_output_dir/$in{'delete_file'}.$files_extension" || &display_error_message(&get_msg(31))}
			
&display_error_message(&get_msg(80));

} # end subroutine


#################################################
#		 Modify_Record			#
#################################################

sub modify_record {

open(TABLE, "<$table") || &display_error_message(&get_msg(16));
flock(TABLE,1);
my @lines = <TABLE>;
close(TABLE);


my ($column_line,$record_line)=&get_column_n_data($key);
chomp $column_line;
chomp $record_line;
my @columns=split /\Q$separator/, $column_line;
my @rec=split /\Q$separator/, $record_line;


$val="$key";
my @in_keys=keys(%in);

open(TABLE, ">$table") || &display_error_message(&get_msg(28));
flock(TABLE,2);

foreach $line (@lines)
{
chomp $line;
$_=$line;
if (/^$key\D/) 
	{ 
	for ($i=1;$i<$no_of_column;$i++)
		{
			#if ($columns[$i] eq "\~date") {$rec[$i]=scalar(localtime(time))}
			for ($columns[$i])
			{
				/^~date$/ and do {$rec[$i]=scalar(localtime(time))};
				/^~group_owner$/ and do {$rec[$i]=$user_group};
				/^~owner$/ and do {$rec[$i]=$user_logged};
			}
			
			# in case we should have a static output changing name:
			if (($name_file_after)&&($columns[$i] eq $name_file_after)) {$old_static_file_name=$rec[$i];$old_static_file_name=~s/ /_/g}
			
			$in{"$columns[$i]"}=~ s/\r\n/<br>/g;
			if (($columns[$i] =~ /^(image.+)/) || ($columns[$i] =~ /^(file_.+)/))
			{
				my $file=$1;
				if ($in{$file} eq "") {$val.=$separator.$rec[$i];} 
				else 
				{ 
					&upload_file($file); 
					$val.=$separator.$in{$file}
				} 
			}
			elsif (grep {$_ eq $columns[$i]} @in_keys) {$val.="$separator".$in{"$columns[$i]"}}
			else {$val.="$separator".$rec[$i]}
		}
	print TABLE "$val\n";
	} 
	
else {print TABLE "$line\n";}

}

close(TABLE);

# eztree addition:

if ($eztree_fields)
{
open(TREE, "<./my_db/eztree.csv") || &display_error_message(&get_msg(29));
flock(TREE,1);
my @tree_lines = <TREE>;
close(TREE);

my @tree_fields=split /--/, $eztree_fields;
for ($i=0;$i<@tree_fields;$i++) { $tree_fields[$i]=$in{"$tree_fields[$i]"} }


open(TREE, ">./my_db/eztree.csv") || &display_error_message(&get_msg(30));
flock(TREE,2);
foreach $line (@tree_lines)
{
if ($line =~ /^\d+?\|$key\|$table_alias\|/) 
	{ 
	chomp $line;
	my @temp=split /\|/, $line;
	print TREE "$temp[0]\|$temp[1]\|$temp[2]\|$temp[3]\|".join('|',@tree_fields)."\n";
	} 
	
else {print TREE "$line";}
}

close(TREE);
} # end unless


&display_message(&get_msg(32));

$val.="\n";
if (($enable_log==1)&&($log_modify==1)){ &update_log("Modify");}



} # end subroutine



#################################################
#	   security_check			#
#################################################

sub security_check {

if ($session eq "") 
{
	$user_group="default"; 
	$user_logged="default";
	return
}
	
open(DB,"<$system_file_path/user_session");
flock(DB,1);
my @lines=<DB>;
close(DB);

my $okflag=0;

for (@lines) 
{
	chomp;
	my @fields=split(/\|/);

	my $valid_ip=0;
	if ( (! $enable_ip_check) || (($enable_ip_check)&&($ENV{'REMOTE_ADDR'} eq $fields[4])) ) {$valid_ip=1}

	if (($fields[0] eq $session)&&($valid_ip))
	{
		if ($fields[3]+$session_max_duration < time) {$message=&get_msg(33)}
		if ($use_cookie_session) 
		{
			$_=$ENV{'HTTP_COOKIE'};
			/session=(.+);*/;
			my $second_key=$1;
			if ($second_key && ($second_key ne $fields[5])) {&display_error_message(&get_msg(85))}
		}
		$user_group=$fields[1];
		$user_logged=$fields[2];
		$okflag=1;
		last
	}
}

if (($user_group eq "")&&($session =~ /^default/i)) {$user_group=$session}
elsif ($user_group eq "") {$user_group="default"}

if ($user_logged eq "") 
	{ if ($in{'login'} ne "") {$user_logged=$in{'login'}}
	  else {$user_logged=$user_group} 
	}

return $okflag;

}


#################################################
#		  html_menu			#
#################################################

sub html_menu {

my $msg1=&get_msg(34);
my $msg2=&get_msg(35);
my $msg3=&get_msg(36);
my $msg4=&get_msg(37);
my $msg5=&get_msg(38);
my $msg6=&get_msg(39);
my $msg7=&get_msg(40);
my $msg8=&get_msg(41);

$menu.= qq!
<div align="center">

  <table border="1" CELLPADDING=0 CELLSPACING=0 bgcolor="#003399">
    <tr> 
!;

if (($show_add)&&($table ne "connect"))
{
	$menu.= qq!
      <td width="60"> 
        <div align="center" valign=center><a href="$script_name?$table_alias+add+display&$session"><font face="Verdana, Arial, Helvetica, sans-serif" size="2" style="text-decoration:none" color=white>$msg1</a></font></div>
      </td>
      !;
}

if (($show_view) &&($table ne "connect"))
{
	$menu.= qq!
      <td width="60"> 
        <div align="center" valign=center><a href="$script_name?$table_alias+search+entry&$session"><font face="Verdana, Arial, Helvetica, sans-serif" size="2" style="text-decoration:none" color=white>$msg2</font></a></div>
      </td>
      !;
}

if (($show_delete)&&($table ne "connect")) 
{
	$menu.= qq!
            <td width="60"> 
        <div align="center" valign=center><a href="$script_name?$table_alias+delete+entry&$session"><font face="Verdana, Arial, Helvetica, sans-serif" size="2" style="text-decoration:none" color=white>$msg3</font></a></div>
      </td>
      !;
}

if (($show_modify)&&($table ne "connect")) 
{
	$menu.= qq!
      <td width="60"> 
        <div align="center" valign=center><a href="$script_name?$table_alias+modify+entry&$session"><font face="Verdana, Arial, Helvetica, sans-serif" size="2" style="text-decoration:none" color=white>$msg4</font></a></div>
      </td>
      !;
}

if (($show_login) || ($table eq "connected")||($table eq "") || ($table eq "connect"))
{
	my $login_message=&get_msg(43);
	if ( 	($session eq 'login') || 
		($ENV{'query_string'} eq '') || 
		($session eq 'connect') || 
		( ($table eq "connect") && (($session eq '')||($session =~ /default/i)) ) 
	    ) {$login_message=&get_msg(42)}
	
	$menu.= qq!
      <td width="60"> 
        <div align="center" valign=center><a href="$script_name?&login%%$session"><font face="Verdana, Arial, Helvetica, sans-serif" size="2" style="text-decoration:none" color=white>$login_message</font></a></div>
      </td>
      !;
}

if (($show_connect) ||($table eq "connect"))
{
	my $w_session;
	if ($session ne "login") {$w_session=$session};
	$menu.= qq!
      <td width="60"> 
        <div align="center" valign=center><a href="$script_name?connect&$w_session"><font face="Verdana, Arial, Helvetica, sans-serif" size="2" style="text-decoration:none" color=white>$msg5</font></a></div>
      </td>
      !;
}

if (($user_group eq "admin_group") && ($table ne "")&& ($table ne "connect") && ($enable_log ==1))
{
	$menu.= qq!
      <td width="60"> 
       <div align="center" valign=center><a href="$script_name?$table_alias+audit+entry&$session"><font face="Verdana, Arial, Helvetica, sans-serif" size="2" style="text-decoration:none" color=white>$msg6</font></a></div>
      </td>
      !;
}

if (($user_logged eq "admin"))
{
	$menu.= qq!
      <td width="60"> 
        <div align="center" valign=center><a href="$script_name?$table_alias+ezwizard+entry&$session"><font face="Verdana, Arial, Helvetica, sans-serif" size="2" style="text-decoration:none" color=white>$msg7</font></a></div>
      </td>
      !;
}
# AHAAWEB MODIFICATION LIENS DU MENU
$menu.= qq!
<td width=60> 
        <div align="center" valign=center><a href="javascript:var w=window.open('http://www.maisondusportlalouviere.be/jogging/ahaaweb.html','','width=600,height=600,scrollbars,resizeable=yes')" border=0><font face="Verdana, Arial, Helvetica, sans-serif" size="2" style="text-decoration:none" color=white>$msg8</font></a></div>
      </td>
<td width=160> 
        <div align="center" valign=center><a href="http://www.maisondusportlalouviere.be/jogging/ahaaweb.html" border=0><font face="Verdana, Arial, Helvetica, sans-serif" size="2" style="text-decoration:none" color=white>EZ Perl / EZDB $version</font></a></div>
      </td>
    </tr>
  </table>
</div><br><br>
!;


}


#################################################
#		  connect_db			#
#################################################

sub connect_db {

my $msg1=&get_msg(44);
my $msg2=&get_msg(45);
my $msg3=&get_msg(46);
my $msg4=&get_msg(47);

$content.= qq!

<form method="post" action="$script_name?connected&$session" name="">
<br><br><center>
  <table border="1" cellpading=0 cellspacing=0>
    <tr bgcolor="#003399"> 
      <td><font face="Verdana, Arial, Helvetica, sans-serif" size="2"><b><font color="#FFFFFF">$msg1</font></b></font></td>
    </tr>
    <tr> 
      <td bgcolor="#e1e1e1"><font face="Verdana, Arial, Helvetica, sans-serif" size="2">$msg2:
        <select name="table">
        !;


my @lines;
if ($user_logged eq "default") {

open(DB,"<$system_file_path/table_group") || &display_error_message(&get_msg(48));
flock(DB,1);
@lines=<DB>;
close(DB);
	
}	
else { 
       
open(DB,"<$system_file_path/user_rights") || &display_error_message(&get_msg(49));
flock(DB,1);
@lines=<DB>;
close(DB);

}

my @res;

for (@lines)
{
my @temp=split(/\|/);
if (($user_logged =~ /^default/i)&&($temp[2] =~ /^default/i)) {push (@res, $temp[1])}
elsif ($temp[1] eq $user_logged) {push (@res, $temp[2])}
}

for (sort @res) {$content.= "<option>$_\n"; }
      
unless ($res[0] ne "") {$content.= "<option>$msg3\n";}    
        
$content.= qq!        
        </select></font>
      </td>
    </tr>
    <tr> 
      <td bgcolor="#003399"> 
        <div align="center">
         <input type="submit" name="submit" value="$msg4">
        </div>
      </td>
    </tr>
  </table>
</form>
!;

}


#################################################
#		check_valid_user		#
#################################################

sub check_valid_user {


open(TABLE, "<$system_file_path/user_data") || &display_error_message(&get_msg(50));
flock(TABLE,1);
my @lines = <TABLE>;
my $first_line=shift(@lines);
close(TABLE);

$no_exit=1;

my $user_session=0;
my $log_invalid_attempt=0;

for (@lines) 
{
	chomp;
	my @temp=split(/\|/);
	if ($in{'login'} eq $temp[1])
	{
		if (($max_invalid_attempt > 0)&&($temp[4] >= $max_invalid_attempt))
		{ 
			$no_exit=0;
			&display_error_message(get_msg(68)) 
		}
		elsif ( (($temp[0] + $password_expiration * 86400) < time ) && ($password_expiration) )
		{ 
			$no_exit=1;
			&display_error_message(get_msg(79));
			&display_html('password.html');
			&display_output; 
			exit 
		}
		elsif (crypt($in{'password'},'ez') eq $temp[2])
		{
			$temp[6]=~s/\./\\\./g;
			if ($temp[6] && ($ENV{'REMOTE_ADDR'} !~ /$temp[6]/))
			{
				&display_error_message(get_msg(84));
				&display_output; 
				exit
			}
			$user_session=&encrypt(time.$$);
			if ($use_cookie_session)
			{
				$second_key=&encrypt($user_session);
				&write_session_cookie;
			}
			
			open(SESSION, ">>$system_file_path/user_session") || &display_error_message(&get_msg(51));
			flock(SESSION,2);
			print SESSION "$user_session\|default\|$temp[1]\|".time."\|$ENV{'REMOTE_ADDR'}\|".$second_key."\n";
			close(SESSION);
		}
		elsif (($max_invalid_attempt > 0)&&(crypt($in{'password'},'ez') ne $temp[2]))
		{
			$log_invalid_attempt=1;
		}
		last
	}
	

} #end for


# Login invalid attempt if necessary
if ($log_invalid_attempt)
{
	open(TABLE, ">$system_file_path/user_data") || &display_error_message(&get_msg(50));
	flock(TABLE,2);
	print TABLE $first_line;
	for (@lines)
	{
		chomp;
		my @temp=split(/\|/);
		if ($in{'login'} eq $temp[1]) {$temp[4]=($temp[4]?$temp[4]+1:1); print TABLE join('|',@temp)."\n"}
		else {print TABLE $_,"\n"}
	}
	close(TABLE);
}

# cleaning process:


open(SESSION, "<$system_file_path/user_session") || &display_error_message(&get_msg(51));
flock(SESSION,1);
@session_lines=<SESSION>;
close(SESSION);

open(SESSION, ">$system_file_path/user_session") || &display_error_message(&get_msg(51));
flock(SESSION,2);
print SESSION $session_lines[0];
shift (@session_lines);

for (@session_lines) {
chomp;
my @temp=split(/\|/);
my $valid_ip=0;
if ( (! $enable_ip_check) || (($enable_ip_check)&&($ENV{'REMOTE_ADDR'} eq $temp[4])) ) {$valid_ip=1}
my $hour=time;
unless ( ($temp[3]+$session_max_duration < $hour) ||
	(($session eq 'authorize')&&($temp[0] eq $from)&&($valid_ip)) )  {print SESSION "$_\n";}
}
close(SESSION);


#end of cleaning

return $user_session;
}


#################################################
#	 check_acces_right_to_db		#
#################################################

sub check_acces_right_to_db {

open(TABLE, "<$system_file_path/user_rights") || &display_error_message(&get_msg(49));
flock(TABLE,1);
my @lines = <TABLE>;
close(TABLE);

shift(@lines);

open(SESSION, "<$system_file_path/user_session") || &display_error_message(&get_msg(51));
flock(SESSION,1);
my @session_line = <SESSION>;
close(SESSION);



## User_session cleaning process

my $user_id;
open(SESSION, ">$system_file_path/user_session") || &display_error_message(&get_msg(51));
flock(SESSION,2);
for (@session_line) {
chomp;
my @temp=split(/\|/);

if ($temp[0] eq $session) 
	{
	$user_id=$temp[2];
	print SESSION "$temp[0]\|default\|$temp[2]\|$temp[3]\|$temp[4]\|$temp[5]\n";}
else 	{print SESSION "$_\n";}

}

close(SESSION);

## -> end of cleaning

if ($user_id ne "") {

for (@lines) {

chomp;
my @temp=split(/\|/);
$temp[3]=~s/\W//g;

if (($user_id eq $temp[1]) && ($table_alias eq $temp[2]))
{
  open(SESSION, ">$system_file_path/user_session") || &display_error_message(&get_msg(51));
  flock(SESSION,2);
	for (@session_line)
	{ 
	chomp;
	my @temp_tab=split(/\|/);

	if ($temp_tab[0] eq $session) 
	{print SESSION "$temp_tab[0]\|$temp[3]\|$temp_tab[2]\|$temp_tab[3]\|$temp_tab[4]\|$temp_tab[5]\n";}
	else {print SESSION "$_\n";}
	}
  close(SESSION);
  
  last;
}

} #end for

} # end if user_in not null

else {$session="default";}



}


#################################################
#	 display_error_message			#
#################################################

sub display_error_message {

$content.= qq!
<div align="center">
  <table border="1" cellpadding=0 cellspacing=0 width="300">
    <tr>
      <td bgcolor="#990033"> 
        <div align="center"><font face="Verdana, Arial, Helvetica, sans-serif" color="#FFFFFF" size="2"><b>$_[0]</b></font></div>
      </td>
    </tr>
  </table>
</div>
!;

unless (($no_exit)||($session eq "login")) {&display_output; exit}
}

#################################################
#	 display_message			#
#################################################

sub display_message {
# not exit for this routine
$content.= qq!
<div align="center">
  <table border="1"  CELLPADDING=0 CELLSPACING=0 width="300">
    <tr>
      <td bgcolor="#cecece"> 
        <div align="center"><font face="Verdana, Arial, Helvetica, sans-serif" color="#003366" size="2"><b>$_[0]</b></font></div>
      </td>
    </tr>
  </table>
</div>
<br>
!;

}



############################################
############################################


#################################################
#		  get_setup			#
#################################################

sub get_setup {



open(DB,"<$system_file_path/tables")|| &display_error_message(&get_msg(52));
flock(TABLE,1);
my @tables_lines=<DB>;
close(DB);

shift(@tables_lines);

foreach $line (@tables_lines)
{
chomp $line;
my @temp=split/\|/, $line;

my $compare_to;
if ($table eq "connected") {$compare_to=$in{'table'}}
else {$compare_to=$table}
	
@table_alias_tab=split /--/,$temp[1];

if ((($table_alias_tab[0] eq $compare_to)||($table_alias_tab[1] eq $compare_to)) && ($table ne ""))
{ 

if ($table_alias_tab[1] eq "") {$table_alias_tab[1]=$table_alias_tab[0]}

if ($table eq "connected") {  $table_alias=$table_alias_tab[0]; $in{'table'}=$table_alias_tab[1] }
else {$table_alias=$table_alias_tab[0]; $table=$table_alias_tab[1]; }


$html_form_path=$temp[2];
$html_display_path=$temp[3];

@fields_displayed_for_result=split /--/,$temp[4];

my $j=0;
for (@fields_displayed_for_result)
{my ($label,$field_name)= split(/:/);
if ($field_name eq "") {$field_name=$label}
$fields_displayed_for_result[$j]=$field_name;
$fields_label{"$field_name"}=$label;
$j++;
} #end for



@color_for_search_result=split /--/, $temp[5];

if ($temp[6] eq "pipe") {$separator='|';} else {$separator=$temp[6];};

$display_mode=$temp[7];

@mandatory=split /--/, $temp[8];
@unique=split /--/, $temp[9];
$line_mode_html_path=$temp[10];

$enable_log=$temp[11];
$log_add=$temp[12];
$log_delete=$temp[13];
$log_modify=$temp[14];
$log_rollback=$temp[15];
chomp $temp[16];
@temp_template=split /<br>/, $temp[16];

$notify_add=$temp[17];
$notify_modify=$temp[18];
$notify_delete=$temp[19];
$notify_rollback=$temp[20];

$show_percent=$temp[21];
$html_output_dir=$temp[22];
$html_output_url=$temp[23];

$target_dir=$temp[24];
$target_dir_url=$temp[25];
$max_image_size=$temp[26];

$order_by=$temp[27]; 
if ($order_by=~ s/reverse //) {$reverse_sort=1}
$direct_full_display=$temp[28];
$files_extension=$temp[29];
$name_file_after=$temp[30];

$eztree_fields=$temp[31];

$password_field=$temp[32];

$no_match_html=$temp[33];

$bulk_delete=$temp[34];

$bad_words=$temp[35];

} # end if

} # end for

#if ($session eq 'authorize') {$context='authorize'}
if ($session eq 'login') {$context='login'}
if ($table eq 'connected') {$context='connected'}

for (@temp_template)
{
my @temp=split(/--/);

if ((($temp[0] eq $context)||($temp[0] eq "*")) && (($temp[1] eq $phase)||($temp[1] eq "*")))
  { $html_template=$temp[2]} 
}

@indexes_displayed_for_result=&get_indexes_for_columns($table);

$no_of_column=&get_no_of_column($table);

}

#################################################
#	  get_group_setup			#
#################################################

sub get_group_setup {

$show_view=0;
$show_add=0;
$show_modify=0;
$show_delete=0;
$show_login=1;
$show_connect=1;


unless (! -e $table) {

open(DB,"<$system_file_path/table_group")|| &display_error_message(&get_msg(48));
flock(DB,1);
my @table_group_lines=<DB>;
close(DB);

shift(@table_group_lines);

for (@table_group_lines)
{
my @temp=split(/\|/);
chomp $temp[$#temp];

if ((($temp[1] eq $table_alias)||($temp[1] eq $table)) && ($temp[2] eq $user_group))
{ @security=($temp[3],$temp[4],$temp[5],$temp[6]);
if (($temp[7] eq "1") || ($temp[8] eq "1") || ($temp[9] eq "1") || ($temp[10] eq "1") || ($temp[11] eq "1") || ($temp[12] eq "1"))
{$hide_menu=0}
else {$hide_menu=1}

$show_view=$temp[7];
$show_add=$temp[8];
$show_modify=$temp[9];
$show_delete=$temp[10];
$show_login=$temp[11];
$show_connect=$temp[12];

chomp $temp[17];

if ($temp[13] =~ /--/)
{
my @tab=split /--/, $temp[13];
if ((($tab[0] eq $context)||($tab[0] eq "*")) && (($tab[1] eq $phase)||($tab[1] eq "*")))
  { {$html_display_path=$tab[2]} } 
}
elsif (($temp[13] ne "Default")&&($temp[13] ne "")&&($temp[13] ne "\n")&&($temp[13] =~ /\//)) {$html_display_path=$temp[13]}

if ($temp[14] =~ /--/)
{
my @tab=split /--/, $temp[14];
if ((($tab[0] eq $context)||($tab[0] eq "*")) && (($tab[1] eq $phase)||($tab[1] eq "*")))
  { {$html_form_path=$tab[2]} } 
}
elsif (($temp[14] ne "Default")&&($temp[14] ne "")&&($temp[14] ne "\n")&&($temp[14] =~ /\//)) {$html_form_path=$temp[14]}

if ($temp[15] ne "") {$display_mode=$temp[15]}

my @restrictions=split /;/, $temp[16];
for (@restrictions) { if (/$context:(.+)/) {$restrictions=$1}}
if (($restrictions eq '')&&($temp[16] ne '')) {$restrictions=$temp[16]}

if (($temp[17] ne "Default")&&($temp[17] ne "")&&($temp[17] ne "\n")) 
{@temp_template=split /<br>/, $temp[17]}

for (@temp_template)
{
	my @temp=split(/--/);

	if ((($temp[0] eq $context)||($temp[0] eq "*")) && (($temp[1] eq $phase)||($temp[1] eq "*")))
  	{ $html_template=$temp[2]} 
}
if ($temp[17] eq " ") {undef $header_path; undef $footer_path;}

if ($temp[18]) {$direct_full_display=$temp[18]}

if ($temp[19]) {@authorized_fields=split /--/, $temp[19]}

if ($temp[20]) {@default_values=split /--/, $temp[20]}

if ($temp[21]) {$line_mode_html_path=$temp[21]}

if ($temp[22]) {$allow_eztree=$temp[22]}

last;
}

}

} #end unless


if (($context eq "search") and ($security[0]!=1)) {$message=&get_msg(53)}
if (($context eq "add") and ($security[1]!=1)) {$message=&get_msg(54)}
if (($context eq "modify") and ($security[2]!=1) and (! $modify_from_cookie)) {$message=&get_msg(55)}
if (($context eq "delete") and ($security[3]!=1)) {$message=&get_msg(56)}

}



#################################################
#		  update_log			#
#################################################

sub update_log {

my $log_file="./log_files/".$table_alias.".log";

my $clean=0;

if (!(-e $log_file)) {open(LOG,">$log_file");flock(LOG,2); print LOG "pkey%%date%%user%%group%%action%%record\n";} 
else {$clean=1; open(LOG,">>$log_file");flock(LOG,2);}

@time_tab=localtime(time);

print LOG time."%%$time_tab[3]/$time_tab[4]/$time_tab[5] $time_tab[2]:$time_tab[1]%%$user_logged%%$user_group%%$_[0]%%$val";

close(LOG);



if ($clean) 
{
# cleaning process:

open(LOG, "<$log_file") || &display_error_message(&get_msg(57));
flock(LOG,1);
@log_lines=<LOG>;
close(LOG);
open(LOG, ">$log_file") || &display_error_message(&get_msg(58));
flock(LOG,2);
print LOG $log_lines[0];
shift (@log_lines);

my $the_time=time;

for (@log_lines) {
chomp;
my @temp=split(/%%/);
unless ($temp[0]+$log_archiving_duration < $the_time) {print LOG "$_\n";}

}
close(LOG);


#end of cleaning}

}

}



#################################################
#		audit_table			#
#################################################

sub audit_table {

my $log_table="./log_files/$table_alias.log";

open(LOG,"<$log_table") || &display_error_message(&get_msg(57));
flock(LOG,1);
my @lines=<LOG>;
close(LOG);


shift(@lines);

$content.= qq!
<center>
<table border=1>
<tr><td bgcolor="#8CC894"><b>Date</b></td>
<td bgcolor="#8CC894"><b>User</b></td>
<td bgcolor="#8CC894"><b>Group</b></td>
<td bgcolor="#8CC894"><b>Action</b></td>
<td bgcolor="#D0B548"><b>View Old<br>Record</b></td>
<td bgcolor="#D0B548"><b>Rollback<br>Changes</b></td></tr>
!;

my %audit;
my $any_record_deleted=0;

foreach $line (reverse(@lines))
{

my @temp=split/%%/, $line;
chomp $temp[5];

$_=$temp[5];

/(\d+?)\|.+/;

$temp_pkey=$1;

if ($phase eq "audit_record") {if ($key == $temp_pkey) {push @{ $audit{"$temp_pkey"} },$line;};$any_record_deleted=1;}
else {
      if (($temp[4] eq "Delete")&&($audit{"$temp_pkey"}[0] eq "")) {$any_record_deleted=1;}
      push @{ $audit{"$temp_pkey"} },$line; 
      }

}

my $count=%audit;

if ($count == 0) {&display_error_message(&get_msg(59))}
elsif ($any_record_deleted)
{

for (keys(%audit))
{
my $deleted;

if ($phase eq "deleted_record") {
$deleted="_deleted";
if ($audit{"$_"}[0] !~ /%%Delete%%/ ) {next;}

}

$content.= qq!
<tr><td colspan=6 bgcolor="#91BFC4">Record No $_</td></tr>
!;

for (@{$audit{"$_"}})
{	
my @temp=split(/%%/);	

$_=$temp[5];

/(\d+)\|.+/;
my $temp_pkey=$1;

chomp $temp[5];

$content.= qq!
<tr><td bgcolor="#8CC894">$temp[1]</td><td>$temp[2]</td><td>$temp[3]</td><td>$temp[4]</td>
<form action="$script_name?$table_alias+search+display+$temp_pkey&$session" method=post>
<input type=hidden name=old_record value="$temp[5]">
<td align=middle><input type=submit value=View></td></form>
<form action="$script_name?$table_alias+audit+rollback$deleted+$temp_pkey&$session" method=post>
<input type=hidden name=old_record value="$temp[5]">
<td valign=middle><input type=submit value=Rollback></td></form></tr>
!;
}

}
$content.= "</table>";

} #end if any_record_deleted

else {&display_error_message(&get_msg(60))}



}




#################################################
#		rollback			#
#################################################

sub rollback {

if ($phase eq "rollback_deleted") {
	open(DB,">>$table") || &display_error_message(&get_msg(16));
	flock(DB,2);
	print DB "$in{'old_record'}\n";
	close(DB);
}

else {	
	
open(DB,"<$table") || &display_error_message(&get_msg(16));
flock(DB,1);
my @lines=<DB>;
close(DB);

open(DB,">$table") || &display_error_message(&get_msg(16));
flock(DB,2);

for (@lines)
{
my @temp=split(/\|/);

if ($temp[0] eq $key) { print DB $in{'old_record'},"\n";}
else { print DB "$_";}
}

close(DB);
}


&display_message("Rollback Done");


$context="search";
$phase="display";
&display_record;

$content.= qq!
<center>
<form>
<input type=button value="CLOSE RECORD" onClick="document.location.href='$script_name?$table_alias+audit+entry&$session'">
<form><br><br><br>
</center>
!;

$val=$in{'old_record'}."\n";
if (($enable_log==1)&&($log_rollback==1)){ &update_log("Rollback"); }

}




#################################################
#		 show_button			#
#################################################

sub show_button {
my $delete_file;
if ($old_static_file_name) {$delete_file="<input type=hidden name=delete_file value=\"$old_static_file_name\">"}

$content.= qq!
<center>
<form method=post action="$_[0]">
<input type=submit value="$_[1]">
$delete_file
</form><br>
</center>
!;

}



#################################################
#		upload_file			#
#################################################


sub upload_file {
	
my $bytes_read;
my $buffer;

$image_file=$in{$_[0]};
$in{$_[0]}=$target_dir_url."/".$in{$_[0]};
$handle=$_[0].'_handle';
$file_handle=$in{$handle};

if (($target_dir eq '')||(! -e $target_dir)) {&display_message(&get_msg(61))}

open(OUTFILE, ">$target_dir/$image_file")||&display_message(&get_msg(62));
flock(OUTFILE,2);
binmode OUTFILE;
while ($bytes = read($file_handle,$buffer,1024)) 
{
	$bytes_read += $bytes;
	print OUTFILE $buffer;
}
close(OUTFILE);        

if ($bytes_read > $max_image_size) 
{
	unlink "$target_dir/$image_file";
	&display_error_message(&get_msg(63));
}

$in{$_[0]}=$image_file;

}


#################################################
#		Encryption Routine		#
#################################################

sub encrypt {
	
# This is a one way encryption enforcing the session id	
	
my @chars = (0..9,a..z,A..Z,'-','_');
my $salt;
for (rand 2) {$salt.=$chars[rand 64]}
return crypt($_[0], $salt);		
					
}


			
#################################################
#		check_password			#
#################################################

sub check_password {
	
if ($in{'ezdb_password_for_record_access'} eq '') {
my $form= qq!
<form method=post action="ezdb.cgi?$ENV{QUERY_STRING}">
<font size=1>You must provide a password to view this record:</font>
<input type=password name=ezdb_password_for_record_access size=10>
<input type=submit value=submit>
</form>
!;		
&display_error_message("$form");
}
else {
# checking password:
if ($in{"$password_field"} ne $in{'ezdb_password_for_record_access'}) {&display_error_message(&get_msg(64))}
}

					
}			

#################################################
#		bulk_deletion			#
#################################################

sub bulk_deletion
{

my @delete_records;
foreach $name (keys %in)
{
	if (($in{$name})&&($name =~ /^delete_(\d+)$/)) { push(@delete_records,$1) }
}

open(TABLE, "<$table") || &display_error_message(&get_msg(16));
flock(TABLE,1);
my @lines = <TABLE>;
close(TABLE);

my $fields=shift(@lines);
my @columns=split /\Q$separator/, $fields;
my @static_delete;

my $name_file_after_index=0;
for (@columns) 
{
	if ($_ eq $name_file_after) {last}
	else {$name_file_after_index++}
}




open(TABLE, ">$table") || &display_error_message(&get_msg(64));
flock(TABLE,2);
print TABLE $fields;
foreach $line (@lines)
{
if (grep {$line =~ /^$_\D/} @delete_records) 
{
my @temp=split /\Q$separator/, $line;
my $filename=$temp[$name_file_after_index];
$filename=~s/ /_/g;
push(@static_delete,$filename)
}
else {print TABLE $line;}
}

close(TABLE);

for (@static_delete) {unlink "$html_output_dir/$_.$files_extension"}

&display_error_message(&get_msg(65));

}


#################################################
#		parse_bad_data			#
#################################################

sub parse_bad_data
{
my ($temp_fields,$temp_words)=split /:/, $bad_words;

my @fields=split /--/, $temp_fields;
my @words=split /,/, $temp_words;

foreach $field (@fields)
{
	if (grep {$in{$field} =~ /$_/} @words) {&display_error_message(&get_msg(66))} 
}



}



#################################################
#		  Display_html			#
#################################################

sub display_html
{
	my $file=$generic_html_file_path.'/'.$language.'_'.$_[0];
	open(HTML,"<$file") || &display_error_message(&get_msg(69));
	flock(HTML,1);
	while (<HTML>)
	{
		if ($_[0] eq 'ask_for_keyword.html')
		{$_=~s/value="$display_mode"/value="$display_mode" checked/}
		$_=~s/_LOGIN_ACTION_/$script_name?$table_alias&authorize%%$from/g;
		$_=~s/_AUDIT_ACTION_/$script_name?$table_alias+audit+deleted_record&$session/g;
		$_=~s/_SEARCH_ACTION_/$script_name?$table_alias+$context+retrieve&$session/g;
		$_=~s/_TABLE_/$table_alias/g;
		$content.=$_;
	}
	
	close(HTML);
	
	
}




#################################################
#	 	password_reminder		#
#################################################

sub password_reminder
{
open(DB,"<$system_file_path/user_data")|| print &get_msg(50);
flock(DB,1);
my @lines=<DB>;
close(DB);

open(DB,">$system_file_path/user_data")|| print &get_msg(50);
flock(DB,2);

for (@lines)
{
	chomp;
	my @temp=split(/\|/);
	if (($temp[1] eq $in{'login'}) && ($temp[5] eq $in{'email'}))
	{
		my @chars = (0..9,a..z,A..Z,'-','_');
		my $password;
		for ($i=0;$i<8;$i++) {$password.=$chars[rand 64]}
		
		$temp[0]=time;
		$temp[4]=0;
		$temp[2]=crypt($password,'ez');
		print DB join('|',@temp),"\n";
		
		open(MAIL,"| $mail_routine_path -t -n -oi") || &display_error_message(&get_msg(18));
		print MAIL "To: $temp[5]\n";
		print MAIL "From: $mail_from\n";
		print MAIL "Subject: Your EZDB Password\n\n";
		print MAIL qq!
		Hi,
		
		Your EZDB login is: $temp[1]
		Your EZDB password is: $password
		
		$mail_signature
		!;
		close(MAIL);
		$password_sent=1;
		
	}
	else {print DB $_,"\n"}
	
}

close(DB);

}

#################################################
#	 	password_update			#
#################################################

sub password_update
{
open(DB,"<$system_file_path/user_data")|| print &get_msg(50);
flock(DB,1);
my @lines=<DB>;
close(DB);

open(DB,">$system_file_path/user_data")|| print &get_msg(50);
flock(DB,2);

for (@lines)
{
	chomp;
	my @temp=split(/\|/);
	if (($temp[1] eq $in{'login'}) && ($temp[2] eq crypt($in{'old_password'},'ez')) && ($in{'old_password'} ne $in{'password'}))
	{
		$temp[0]=time;
		$temp[4]=0;
		$temp[2]=crypt($in{'password'},'ez');
		print DB join('|',@temp),"\n";
		$password_updated=1;
		
	}
	else {print DB $_,"\n"}
	
}

close(DB);

}


#################################################
#	 	add_to_selection		#
#################################################

sub add_to_selection
{
$_=$ENV{'HTTP_COOKIE'};
/selection=([\w:\|]*);*/;
my $selection=$1;

$display_selection=1;

# already selected?
if ($selection =~ /$table_alias:$key/) {return}

if ($selection) {$selection.='|'.$table_alias.':'.$key}
else {$selection=$table_alias.':'.$key}

print "Content-Type: text/html\n";
print "Set-Cookie: selection=$selection; path=/; expires=Monday, 01-Jan-2010 00:00:00 GMT\n";	



}

#################################################
#	 	view_selection			#
#################################################

sub view_selection
{
$_=$ENV{'HTTP_COOKIE'};
/selection=(.+);*/;
my $selection=$1;
my @selected_record;
my @temp=split /\|/, $selection;
for (@temp) { if (/$table_alias:(\d+)/) {push(@selected_record,$1)} }

open(DB,"<$table") || &display_error_message(&get_msg(16));
flock(DB,1);
my @lines=<DB>;
close(DB);

foreach $line (@lines)
{
	chomp $line;
	if (grep {$line =~ /^$_\D/} @selected_record) 
	{ if ($result{"$line"} eq "") {$result{"$line"}=1} else {$result{"$line"}++} }
}	

$no_of_keyword=1;
$no_keyword_processing=1;
$display_selection=1;
$context='search';
if ($select eq 'full') {$display_mode='Full'}
&display_result_for_key;


unless ($select eq 'full')
{
my $msg1=&get_msg(75);
my $msg2=&get_msg(76);

$content.=qq!
<br><br>
<font face="Verdana, Arial, Helvetica, sans-serif" size="2">
<a href="$script_name?$table_alias+selection+clear&$session">$msg1</a>
<br>
<a href="$script_name?$table_alias+selection+display++full&$session">$msg2</a>
!;
}

}

#################################################
#	 	clear_selection			#
#################################################

sub clear_selection
{
print "Content-Type: text/html\n";
print "Set-Cookie: selection=; path=/; expires=Monday, 01-Jan-2010 00:00:00 GMT\n";	

&display_error_message(&get_msg(74));
}


#################################################
#	 	check_submited_values		#
#################################################

sub check_submited_values
{
@authorized_fields || return;

open(DB,"<$table") || &display_error_message(&get_msg(16));
flock(DB,1);
my $fields=<DB>;
close(DB);

my @temp=split /\Q$separator/, $fields;

foreach $data (keys %in)
{
	if ( (!(grep {$_ eq $data} @authorized_fields)) && (grep {$_ eq $data} @temp) ) {&display_error_message(&get_msg(81))}
}


}


#################################################
#	 	load_default_values		#
#################################################

sub load_default_values
{
@default_values || return;

for (@default_values)
{
	my ($field,$value)=split(/=/);
	$in{$field}=$value
}

}


#################################################
#	 	write_session_cookie		#
#################################################

sub write_session_cookie
{
print "Content-Type: text/html\n";
print "Set-Cookie: session=$second_key; path=/; expires=Monday, 01-Jan-2010 00:00:00 GMT\n";	
}

#################################################
#	 	cookie_session			#
#################################################

sub cookie_session
{
$_=$ENV{'HTTP_COOKIE'};
/session=(.+);*/;
}

