#!/usr/bin/perl
################################################################
#																					#
#  package ActinicAddressBook 											#
#																					#
#  Separated from ACTINIC package in v6								#
#																					#
#  This module contains the definition of HTML_ZCL and 			#
#  ADDRESS_BOOK classes.													#
#																					#
#	Author: Zoltan Magyar													#
#																					#
#  Copyright (c)2002 Actinic Software Ltd 							#
#																					#
################################################################
#
# Version
#
$ACTINIC_ADB::prog_name = 'ActinicAddressBook.pm';	# Program Name
$ACTINIC_ADB::prog_name = $ACTINIC_ADB::prog_name;	# remove compiler warning
$ACTINIC_ADB::prog_ver = '$Revision: 21561 $ ';		# program version
$ACTINIC_ADB::prog_ver = substr($ACTINIC_ADB::prog_ver, 11); # strip the revision information
$ACTINIC_ADB::prog_ver =~ s/ \$//;					# and the trailers

################################################################
#
# HTML_ZCL  - HTML generator.
# Extracted from HTML_ZCL.pm
# Comments and pod documentation in HTML_ZCL.pm
#
# Copyright 1999 ZCL.
# Non-terminable licence to use granted to ACTINIC Software.
#
# Written by Ryszard Zybert, 1999
#
# It may be better to use HTML_ZCL.pm in the future
#
################################################################

package HTML_ZCL;
#################################################################
#
# Generation of member functions
#
#################################################################
# 
# NOTE: the following code fragment doesn't follow the Actinic
#  coding standards.
#
#################################################################

	my @oc_tags = ('A','ADDRESS','APPLET',
						'B','BIG','BLINK','BLOCKQUOTE','BODY',
						'CENTER','CITE','CODE',
						'DD','DIV','DL','DT',
						'EM','EMBED',
						'FORM','FRAMESET',
						'H1','H2','H3','H4','H5','H6','HEAD','HTML',
						'I',
						'LI','LISTING',
						'MAP',
						'NOFRAMES','NOSCRIPT',
						'OBJECT','OL','OPTION',
						'P','PLAINTEXT','PRE',
						'S','SAMP','SCRIPT','SELECT','SMALL','SPAN','STRIKE','STRONG','STYLE','SUB','SUP',
						'TABLE','TD','TEXTAREA','TH','TITLE','TR','TT',
						'U','UL',
						'VAR',
						'XMP',
					  );
	my @s_tags = ('AREA',
					  'BASEFONT','BR',
					  'FRAME',
					  'HR',
					  'IMG','INPUT',
					  'LINK',
					  'META',
					  'PARAM',
					 );

	my $tag;
	my $code = "";
	foreach $tag (@oc_tags)
		{
		$code .= 'sub '.$tag.' {my $self=shift;my $txt = pop(@_);my $b = '.
			'"<'.$tag.'".$self->attrib(@_).">".$txt."</'.$tag.'>";return $b;'."}".
		'sub '.$tag.'_ {my $self=shift;my $b = "<'.$tag.'".$self->attrib(@_).">";return $b;'."}".
		'sub _'.$tag.' {my $self=shift;my $b = "</'.$tag.'>";return $b;'."}";
		}
	foreach $tag (@s_tags)
		{
		$code .= 'sub '.$tag.' {my $self=shift;my $b = "<'.$tag.'".$self->attrib(@_).">";return $b;'."}";
		}
	eval $code;

#################################################################
# 
# HTML_ZCL->new
# 
# Stadard constructor of HTML_ZCL class
#
#################################################################

sub new
	{
	my $proto = shift;
	my $class = ref($proto) || $proto;
	my $self = {};
	bless ($self, $class);
	$self->Set(@_);
	return $self;
	}

#################################################################
# 
# HTML_ZCL->Set
# 
#################################################################

sub Set
	{
	my $self = shift;
	my %pars = @_;
	my $k;
	foreach $k (keys %pars)
		{
		$self->{$k} = $pars{$k};
		}
	}

#################################################################
# 
# HTML_ZCL->attrib - Attribute handler for HTML tags
# 
#################################################################

sub attrib
	{
	my $self = shift;
	my %pars = @_;
	my $txt = "";
	my $k;
	foreach $k (reverse sort keys %pars )
		{
		if( $pars{$k} ne "" )
			{
			$txt .= " ".uc($k)."=\"$pars{$k}\"";
			}
		else
			{
	    		$txt .= " ".uc($k);
			}
    	}
	return $txt;
	}
	
#################################################################
# 
# HTML_ZCL->FONT - <FONT> HTML tag handler
# 
# The <FONT> tag handled separately due to the Actinic CSS themes
#
# Author: Zoltan Magyar
#
#################################################################

sub FONT
	{
	my $self = shift;
	my $sText = pop (@_);
	#
	# Get the appropriate poxy font tags
	#
	my $sOpenTag = ACTINIC::GetPhrase(-1, 1967);
	my $sCloseTag = ACTINIC::GetPhrase(-1, 1970);
	return ($sOpenTag . $sText . $sCloseTag);
	}

############################################################
#
# ADDRESS_BOOK - ACTINIC address book class
# Inherits HTML methods from HTML_ZCL
#
# Needed arguments of new() (specify by name: <name> => <value>):
#
#	$self->{Action}				= undef;			# ACTION parameter for direction=forward
#	$self->{DeliveryFormHash}	= undef;			# Hash of address form
#	$self->{FormNames}			= undef;			# Array of Form names to be handled
#	$self->{FormPrefix}			= undef;			# Prefix in InputFormHash compared to DeliveryFormHash
#	$self->{InputFormHash}		= undef;			# Hash of input form values
#
# Optional arguments:
#
#	$self->{MaxAddresses} 	= 12;									# Number of allowed addresses (keep below 15)
#	$self->{Nnam_1} 			= $self->{FormNames}->[0];		# Name of NAME element in address
#	$self->{Nnam_2} 			= $self->{FormNames}->[1];		# Name of ADDRESS1 element in address
#
# Parameters needed before Show() is invoked (may be set with  new() or Set())
#
#	$self->{OneAddressMessage} 	= undef;			# "is one address"
#	$self->{MoreAddressesMessage} = undef;			# "are %s addresses" - %s will be replaced
#	$self->{StatusMessage} 			= undef;			# "There %s in your address book." - %s will be replaced with OneAddressMessage or MoreAddressesMessage
#	$self->{MaxAddressesWarning} 	= undef;			# Warning text if maximum number of addresses reached
#	$self->{NoAddressesMessage} 	= undef;			# Info - there are no addresses
#	$self->{AddMessage} 				= undef;			# "Add to address book"
#	$self->{DeleteLabel} 			= undef;			# Label text for delete check box column
#	$self->{Sequence} 				= undef;			# Sequence number for redisplay
#
# Optional parameters used by Show() (may be set with  new() or Set())
#
#	$self->{BgColor} 			= "#ffffff";			# Table background
#	$self->{LabelBgColor} 	= "#d0d0ff";			# Delete label background
#	$self->{NameBgColor} 	= "#f0f0f0";			# Name field background
#
# Public methods:
#
#	$self->Init()												# Variable initialization
#	$self->ToForm()											# Store selected address in HTML FORM
#	$self->Show()												# Return Address Book HTML text
#	$self->Header()											# Returns text to be printed inside the HTTP header
#	$self->Set(name => value [[,name => value]...])	# Set variables (inherited from HTML_ZCL)
#	( and all HTML_ZCL methods )							# See HTML_ZCL.pm documentation
#
# Internal variables
#
#	$self->{CookieList} 		= ();				# A list of cookie indices
#	$self->{Hash} 				= {};				# hash of cookie indices
#	$self->{Table} 			= ();				# Address Book table [<address hash>,<modified flag>,<deleted flag>]
#	$self->{AddressForm}		= {};				# Address to be shown in the form
#
# Written by Ryszard Zybert, October 1999
#
############################################################

package ADDRESS_BOOK;
use vars qw(@ISA);
@ISA = qw(HTML_ZCL);

sub new
	{
	my $proto = shift;
	my $class = ref($proto) || $proto;
	my $self = $class->SUPER::new();				# dont pass arguments, we can use Set() below
	bless ($self, $class);

	$self->{MaxAddresses} 		= 9;									# Number of allowed addresses (keep below 15)
	$self->{BgColor} 				= "#ffffff";						# Table background
	$self->{LabelBgColor} 		= "#d0d0ff";						# Delete label background
	$self->{NameBgColor} 		= $$::g_pSetupBlob{FORM_BACKGROUND_COLOR};						# Name field background

	$self->Set(@_);							# Handle initial arguments

	if ( !defined($self->{Nnam_1}) ) { $self->{Nnam_1} = $self->{FormNames}->[0]; }
	if ( !defined($self->{Nnam_2}) ) { $self->{Nnam_2} = $self->{FormNames}->[1]; }

	$self->{UseThis} 		= 0;
	
	#
	# initialize ADDRESS_BOOK values from Cookies
	#
	$self->InitFromCookies();	
	
	return $self;
	}

############################################################
#
# ADDRESS_BOOK->InitFromCookies - initialize ADDRESS_BOOK 
#                                 values from Cookies
#
# Author: Senthil
#
############################################################

sub InitFromCookies
	{
	my $self = shift;
	
	$self->FromCookies();				# Get Address Book from Cookies
	
	#
	# See if address book entry was selected
	# If so get the index from ADBUSETHIS* and store it in $self->{UseThis}
	# Also parse ADBACTION and replace ACTION and SEQUENCE in Input Hash with the result
	#
	foreach (keys %{$self->{InputFormHash}} )
		{
		if( $_ =~ /^ADBUSETHIS([1-9]*$)/ )
			{
			$self->{UseThis} = $1;
			if( $self->{InputFormHash}->{ADBACTION} )
				{
				my ($a,$s) = split('&',$self->{InputFormHash}->{ADBACTION});
				my ($a1,$a2) = split('=',$a);
				my ($s1,$s2) = split('=',$s);
				$self->{InputFormHash}->{ACTION}   = $self->Decode($a2);
				$self->{InputFormHash}->{SEQUENCE} = $self->Decode($s2);
				}
			last;
			}
		}
	}
	
############################################################
#
# ADDRESS_BOOK->Init - initialize ADDRESS_BOOK
#
# Get addresses from Address Form
# If address book address requested, use it
# otherwise try to add the address from Address Form
#
############################################################

sub Init
	{
	my $self = shift;

	if( defined($self->{done}) ) { return; }			
	
	if( $self->{UseThis} > 0 ) 			# Address selected
		{
		$self->{AddressForm} = $self->{Table}[$self->{UseThis}-1][0];	# Address from Address Book
		$self->ToForm();
		}
	elsif( $self->{InputFormHash}->{ADBADD} )	# Add to address book checked
		{
		$self->FromForm();							# Extract address from form
		$self->Add($self->{AddressForm});		# New Address?
		}
	else
		{
		$self->ClearForm();
		}

	$self->{done} = 1;
	}

############################################################
#
# ADDRESS_BOOK->Show - returns address book HTML
#
############################################################

sub Show
	{
	my $self = shift;
	my @tnam;
	my $na = 0;
	my $html;
	#
	# Handle customer account buyers who can't enter new addreses
	#
	my $sDigest = $ACTINIC::B2B->Get('UserDigest');
	if($sDigest ne '')
		{
		#
		# Get the account details
		#
		my ($Status, $sMessage, $pBuyer, $pAccount) = ACTINIC::GetBuyerAndAccount($sDigest, ACTINIC::GetPath());
		if ($Status != $::SUCCESS)
			{
			ACTINIC::ReportError($sMessage, ACTINIC::GetPath());
			}
		#
		# If they can't enter new delivery address details, don't mention the
		# address book
		#
		if($pBuyer->{DeliveryAddressRule} != 2)
			{
			return('');
			}
		}
	#
	# Count the number of active addresses
	#
	foreach (@{$self->{CookieList}})
		{
		if ( $self->{Table}[$_][0] && $self->{Table}[$_][2] == 0 ) { $na++; }
		}
	#
	# Insert address book status message
	#
	$html .= $self->CountMessage($na);
	#
	# If BACK button was pressed in the credit card applet, do not show address book
	# This is because the information is missing - it would have to be extracted differently
	# This is something to do in the future
	#
	#if( $self->{InputFormHash}->{SEQUENCE} > $self->{Sequence} + 1 ) { return $html; }
	#
	# I have commented this out due to cix:actinic_catlog/bugs_reports6:1223
	# It looks like the limiting conditions doesn't exist anymore
	# 04/09/20001 - zmagyar
	#
	if( $na == 0 ) 					# No addresses stored, nothing to do
		{
		$html .= $self->INPUT(
									 TYPE => "CHECKBOX",
									 NAME => "ADBADD"
									).
									  $self->FONT(
													  $self->{AddMessage}
													 );
		$html .= $self->HR();
		return $html;
		}

	$html .= $self->TABLE_(
								  BORDER      => "1" ,
								  CELLSPACING => "1" ,
								  CELLPADDING => "0" ,
								  BGCOLOR     => $self->{NameBgColor},
								  WIDTH       => '100%',
								 ).
									$self->TR(
												 $self->TD(
															  COLSPAN => 3,
															  '&nbsp;',
															 ).
												 $self->TD(
															  ALIGN   => "CENTER",
															  $self->FONT(
																			  $self->{DeleteLabel}
																			 )
															 )
												);
	#
	# Pass HTTP parameters on - except for ADBUSETHIS, ADBACTION and the delivery address
	#
	my ($key,$value);
	while (($key, $value) = each %{$self->{InputFormHash}})
		{
		if( $key !~ /^ADBUSETHIS/ && $key !~ /^DELIVER/ && $key !~ /^ADBACTION/ )
			{
			$html .= $self->INPUT(
										 TYPE  => "HIDDEN",
										 NAME  => $key,
										 VALUE => $value
										);
			}
		}
	#
	# Construct ADBACTION - this will give us ACTION and SEQUENCE next time
	#
	my $record = 'ACTION=' . $self->Encode($self->{Action}) . '&SEQUENCE=' . $self->{Sequence};
	$html .= $self->INPUT(
								 TYPE  => "HIDDEN",
								 NAME  => "ADBACTION",
								 VALUE => $record
								);
	#
	# Sort addresses by name and first address line
	#
	my $cnt = 0;
	foreach (sort {
	   uc(${$self->{Table}[$a][0]}{$self->{Nnam_1}}.${$self->{Table}[$a][0]}{$self->{Nnam_2}})
	   cmp
	   uc(${$self->{Table}[$b][0]}{$self->{Nnam_1}}.${$self->{Table}[$b][0]}{$self->{Nnam_2}})
	} @{$self->{CookieList}} )
		{

		if ( $self->{Table}[$_][2] > 0 ) 			# Address deleted
			{ 
			next;
			}

		my $tval = $self->{Table}[$_][0];			# This is the address contents

		my $nam  = $$tval{$self->{Nnam_1}};
		my $strt = $$tval{$self->{Nnam_2}};
		
		my $bDisabled = $::FALSE;						# default to enabled
		#
		# If the location info is exist in the address book entry then
		# filter the entries using different location
		#
		if (defined $$tval{'DELIVERY_REGION_CODE'} && defined $$tval{'DELIVERY_COUNTRY_CODE'})
			{
			$bDisabled = (($$tval{'DELIVERY_REGION_CODE'}  ne $self->{LocationHash}->{'DELIVERY_REGION_CODE'}) ||
							  ($$tval{'DELIVERY_COUNTRY_CODE'} ne $self->{LocationHash}->{'DELIVERY_COUNTRY_CODE'}));
			}
		$cnt++;
		$html .= $self->TR($self->Row($_, $cnt, $nam, $strt, $bDisabled));
		}

	$html .= $self->_TABLE();
	$html .= $self->_TD();
	$html .= $self->_TR();
	$html .= $self->_TABLE();
	$html .= $self->BR().
	  $self->INPUT(
						TYPE => "CHECKBOX",
						NAME => "ADBADD"
					  ).
						 $self->FONT(
										 $self->{AddMessage}
										);

	return $html;
	}
	
############################################################
#
# ADDRESS_BOOK->Row - returns address book HTML for one row
#
# Arguments:	0 - Address Book index
#		1 - row number
#		2 - name field
#		3 - address1 field
#		4 - status (enabled/disabled)
#
############################################################

sub Row
	{
	my $self = shift;

	my $ind  = shift;
	my $cnt  = shift;
	my $nam  = shift;
	my $strt = shift;
	my $bDisabled = shift;
	
	my $sStatus = $bDisabled ? 'DISABLED' : '';

	my $html;
	my $j = $ind + 1;

	if( $strt eq '{No Street}' ) { $strt = '&nbsp;'; }

	$html = $self->TD(
							ALIGN => "RIGHT",
							$self->FONT(
											$cnt . '.&nbsp;'
										  )
						  ).
							 $self->TD(
										  BGCOLOR => $self->{NameBgColor},
										  $self->INPUT(
															STYLE => 'font-weight:bold;color:white;background:' .
															$::g_sRequiredColor . ';width: 200px;',
															WIDTH => '200',
															TYPE  => "SUBMIT",
															NAME  => "ADBUSETHIS" . "$j",
															VALUE => $nam,
															$sStatus => ''
														  )
										 ).
											$self->TD(
														 BGCOLOR => $self->{NameBgColor},
														 WIDTH   => '270',
														 $self->FONT(
																		 '&nbsp;' . $strt . '&nbsp;'
																		)
														).
														  $self->TD(
																		ALIGN => "CENTER",
																		$self->INPUT(
																						 TYPE => "CHECKBOX",
																						 NAME => "ADBDELETE" . $ind
																						)
																	  );

	return $html;
	}

############################################################
#
# ADDRESS_BOOK->CountMessage - construct Status message
#
# Arguments: Number of stored addresses
# Returns: html text with status message
#
# If there are no adresses adds an ADD checkbox only.
#
############################################################

sub CountMessage
	{
	my $self = shift;
	my $na = shift;
	my $buf;
#
# If BACK button was pressed in the credit card applet, do not show address book
# This is because the information is missing - it would have to be extracted differently
# This is something to do in the future
#
	if( $self->{InputFormHash}->{SEQUENCE} > $self->{Sequence} + 1)
		{
		if( $na < $self->{MaxAddresses} )
			{
			$buf .= $self->INPUT(
										TYPE => "CHECKBOX",
										NAME => "ADBADD"
									  ).
										 $self->FONT(
														 $self->{AddMessage}
														);
			}
		return $buf;
		}

	if( $na >= $self->{MaxAddresses} ) 	# Address Book full - give a warning
		{
		$buf .= $self->FONT(
								  $self->{MaxAddressesWarning}
								 );
		}
	if( $na > 0 )					  # Something there - open TABLE to frame it
		{
		my $adct;
		$buf .= $self->TABLE_(
									 WIDTH       => "600",
									 BORDER      => "1" ,
									 CELLSPACING => "0" ,
									 CELLPADDING => "0" ,
									);
		$buf .= $self->TR_();
		$buf .= $self->TD_();
		if( $na == 1 )				  # Construct the status message
			{
			$adct = $self->{OneAddressMessage};	# Allow some decent english
			}
		else
			{
			$adct = $self->{MoreAddressesMessage};
			$adct =~ s/\%s/$na/;
			}
		my $st = $self->{StatusMessage};
		$st =~ s/\%s/$adct/;
		$buf .= $self->FONT(
								  $st
								 );
		}
	else								  # Address Book empty - different status message and no frame
		{
		$buf .= $self->FONT(
								  $self->{NoAddressesMessage}
			);
		}
	return $buf;
	}

sub Debug
	{
	my $self = shift;
	my $buf = $self->{dbbuf};
	foreach (keys %{$self->{InputFormHash}})
		{
		$buf .= "<br>$_ = " . $self->{InputFormHash}->{$_};
		}
	return $buf;
	}
	
############################################################
#
# ADDRESS_BOOK->ToCookies - converts address book to cookies
#
############################################################

sub ToCookies
	{
	my $self = shift;
	my ($key,$value);
	foreach (@{$self->{CookieList}})
		{
		if( $self->{Table}[$_][2] == 0 && $self->{Table}[$_][1] > 0 )	# If MODIFIED and not DELETED
			{
			my $sCookie;
			while (($key, $value) = each %{$self->{Table}[$_][0]})
				{
				$sCookie .= $key . "=" . $value . ">>";
				}
			$self->{Table}[$_][0] = $self->Encode($sCookie);	# Simply put it back
			}
		}
	}
	
############################################################
#
# ADDRESS_BOOK->Add - add address to address book
#
# Arguments: Address Hash to add
#
############################################################

sub Add
	{
	my $self = shift;
	my $h = shift;

	#
	# Either name or street is needed to identify address book entry
	#
	if ( $h->{$self->{Nnam_1}} eq "" && $h->{$self->{Nnam_2}} eq "" ) { return; }
	#
	# If name or street is not required and it is absent - put a marker there
	#
	if ( $h->{$self->{Nnam_1}} eq ""  ) { $h->{$self->{Nnam_1}} = '{No Name}'; }
	if ( $h->{$self->{Nnam_2}} eq ""  ) { $h->{$self->{Nnam_2}} = "{No Street}"; }

	my $hind = $h->{$self->{Nnam_1}} . $h->{$self->{Nnam_2}};	# This identifies an address

	if( defined( $self->{Hash}{$hind} ) )								# Exists - replace data
		{
		$self->{Table}[$self->{Hash}{$hind}] = [$h,1,0];			# Set MODIFIED flag, unset DELETE flag
		}
	else
		{
		foreach (@{$self->{CookieList}})				# Try to reuse DELETED slots
			{
			if ( $self->{Table}[$_][2] != 0 )		# Deleted - reuse
				{
				$self->{Hash}{$hind} = $_;
				$self->{Table}[$_] = [$h,1,0];		# Set MODIFIED flag, unset DELETE flag
				return;
				}
			}
		my $i;
		for ( $i=0; $i<$self->{MaxAddresses}; $i++ )	# Find a free slot
			{
			if ( !defined($self->{Table}[$i][0]) || $self->{Table}[$i][2] != 0 )	# No data or deleted
				{
				$self->{Hash}{$hind} = $i;
				push @{$self->{CookieList}},$i;
				$self->{Table}[$i] = [$h,1,0];		# Set MODIFIED flag, unset DELETE flag
				return;
				}
			}
		}
	}
	
############################################################
#
# ADDRESS_BOOK->Remove - mark address as deleted
#
# Arguments: Address index
#
############################################################

sub Remove
	{
	my $self = shift;
	my $i = shift;
	$self->{Table}[$i][2] = 1;			# Set DELETED flag
	$self->{Table}[$i][0] = undef;	# Get rid of the data
	}
	
############################################################
#
# ADDRESS_BOOK->FromCookies - convert cookies to address book
# Marks deleted addresses
#
############################################################

sub FromCookies
	{
	my $self = shift;
	$self->GetCookies();

	my $i;
	foreach $i (@{$self->{CookieList}})
		{
		if ( $self->{InputFormHash}->{'ADBDELETE'.$i} )		# Remove DELETED entries
			{
			$self->Remove($i);
			}
		else							# Otherwise convert from Cookie form
			{
			if ( defined($self->{Table}[$i][0]) )
				{
				my @lst = split(">>",$self->Decode($self->{Table}[$i][0]));
				my $h = {};
				my ($key,$value);
				foreach (@lst)
					{
					($key,$value) = split "=";
					$h->{$key} = $value;
					}
				if ( !$h->{$self->{Nnam_1}} && !$h->{$self->{Nnam_2}} )	# Illegal - remove
					{
					$self->Remove($i);
					}
				else					# Put is back and set Hash entry
					{
					$self->{Table}[$i][0] = $h;
					$self->{Hash}{$h->{$self->{Nnam_1}}.$h->{$self->{Nnam_2}}} = $i;
					}
				}
			}
		}
	}
	
############################################################
#
# ADDRESS_BOOK->GetCookies - extracts ACTINIC_ADDRBOOK cookies
#
# Constructs the Address Book table and Cookie list
#
############################################################

sub GetCookies
	{
	my $self = shift;
	my ($sCookie, $sCookies);
	$sCookies = $::ENV{'HTTP_COOKIE'};				# try to retrieve the cookie
	my (@CookieList) = split(/;/, $sCookies);		# separate the various cookie variables in the list
	my ($sLabel,$sA);
	@{$self->{CookieList}} = ();
	foreach $sCookie (@CookieList)
		{
		$sCookie =~ s/^\s*//;								# strip leading white space
		if ($sCookie =~ /^ACTINIC_ADDRBOOK([0-9]*)/)	# found the address book
			{
			my $ind = $1;
			($sLabel, $sA) = split (/=/, $sCookie);	# retrieve the value
			#
			# strip any trailing or leading quotes and spaces
			#
			$sA =~ s/^\s*"?//;
			$sA =~ s/"?\s*$//;
			$self->{Table}[$ind] = [$sA,0,0];	# Flag as not modified and not deleted for now
			push @{$self->{CookieList}},$ind;	# Store index in CookieList
			}
		}
	}
	
############################################################
#
# ADDRESS_BOOK->Header - constructs HTTP header test for
#			Address Book Cookies.
#
# Returns text to be printed inside the HTTP header
#
############################################################

sub Header
	{
	my $self = shift;
	my (@expires, $day, $month, $now, $later, $before, $expiry, $expired);
	my (@days) = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
	my (@months) = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');

	$now = time;

# Two years from now

	$later = $now + 2 * 365 * 24 * 3600;
	@expires = gmtime($later);
	$day = $days[$expires[6]];
	$month = $months[$expires[4]];
	$expiry = sprintf("%s, %02d-%s-%04d %02d:%02d:%02d GMT", $day, $expires[3],
							$month, $expires[5]+1900, $expires[2], $expires[1], $expires[0]);

# Yesterday

	$before = $now - 24 * 3600;
	@expires = gmtime($before);
	$day = $days[$expires[6]];
	$month = $months[$expires[4]];
	$expired = sprintf("%s, %02d-%s-%04d %02d:%02d:%02d GMT", $day, $expires[3],
							$month, $expires[5]+1900, $expires[2], $expires[1], $expires[0]);
	my $buf;

	$self->ToCookies();					# Convert Address Book Hash to cookies

	foreach (@{$self->{CookieList}})
		{
		if ( $self->{Table}[$_][2] != 0 )		# Deleted - make it expire
			{
			$buf .= "Set-Cookie: ACTINIC_ADDRBOOK" . $_ . "=\"\"" .
			"; EXPIRES=" . $expired . "; PATH=/;\n";
			}
		elsif ( $self->{Table}[$_][1] > 0 )		# Modified - send the new value
			{
			$buf .= "Set-Cookie: ACTINIC_ADDRBOOK" . $_ . "=\"" . $self->{Table}[$_][0] . "\"" .
			"; EXPIRES=" . $expiry . "; PATH=/;\n";
			}
		}
	return $buf;
	}
	
############################################################
#
# ADDRESS_BOOK->FromForm - Get address fields from HTML form
# Extracts data from HTML form and makes it current address
#
############################################################

sub FromForm
	{
	my $self = shift;

	if( 	!$self->{InputFormHash}->{$self->{FormPrefix} . $self->{Nnam_1}} &&
		!$self->{InputFormHash}->{$self->{FormPrefix} . $self->{Nnam_2}} 	)
		{
		return;										# Illegal - forget it
		}
	#
	# Get form fields
	#
	foreach (@{$self->{FormNames}})			# Get all selected fields into Address Book
		{
		$self->{AddressForm}->{$_} = $self->{InputFormHash}->{$self->{FormPrefix} . $_};
		}
	#
	# Get location info
	#
	foreach (@{$self->{LocationInfoNames}})
		{
		$self->{AddressForm}->{$_} = $self->{InputFormHash}->{$_};
		}	
	}
	
############################################################
#
# ADDRESS_BOOK->ToForm - Store current Address Book entry into Address Form
#
############################################################

sub ToForm
	{
	my $self = shift;

	if( $self->{UseThis} <= 0 ) { return; }		# Nothing was selected
	#
	# Restore form fields
	#
	foreach (@{$self->{FormNames}})					# Put selected fields into address form
		{
		$self->{DeliveryFormHash}->{$_} = $self->{AddressForm}->{$_};
		}
	#
	# Restore location info
	#
	foreach (@{$self->{LocationInfoNames}})
		{
		if (defined $self->{AddressForm}->{$_})
			{
			$self->{LocationHash}->{$_} = $self->{AddressForm}->{$_};
			}
		}		
	#
	# Replace our 'empty' markers by nothing in the address form
	#
	if ( $self->{DeliveryFormHash}->{$self->{Nnam_1}} eq '{No Name}'  )
		{
		$self->{DeliveryFormHash}->{$self->{Nnam_1}} = "";
		}

	if ( $self->{DeliveryFormHash}->{$self->{Nnam_2}} eq '{No Street}'  )
		{
		$self->{DeliveryFormHash}->{$self->{Nnam_2}} = "";
		}
	}
	
############################################################
#
# ADDRESS_BOOK->ClearForm - Clear Address Form
#
############################################################

sub ClearForm
	{
	my $self = shift;

	foreach (keys %{$self->{DeliveryFormHash}})
		{
		$self->{DeliveryFormHash}->{$_} = "";
		}
	}
	
############################################################
#
#  ADDRESS_BOOK->Decode - decodes URL encoded strings
#  Arguments:
#      0 - class
#      1 - string to decode
#  Returns: decoded string
#
#  Ryszard Zybert  Mar 14 11:57:04 GMT 2000
#
#  Copyright (c) Actinic Software Ltd (2000)
#
############################################################

sub Decode
	{
	return ACTINIC::DecodeText($_[1],$ACTINIC::FORM_URL_ENCODED);
	}
	
############################################################
#
#  ADDRESS_BOOK->Encode - URL encode strings
#   Arguments:
#        0 - class
#        1 - string to uncode
#   Returns: encoded string
#
#  Ryszard Zybert  Mar 14 11:58:57 GMT 2000
#
#  Copyright (c) Actinic Software Ltd (2000)
#
############################################################

sub Encode
	{
	return ACTINIC::EncodeText2($_[1],$::FALSE,$::FALSE);
	}

1;
