#!/usr/bin/perl
################################################################
#																					#
#  package ACTINIC_PXML - ACTINIC specific parser					#
#																					#
#  Separated from ACTINIC package in v6								#
#																					#
#  This module contains the ACTINIC_PXML object description.	#
#  This object is the Actinic specific event driven extension	#
#	of the core PXML object.												#
#	The basic member functions are inherited form the parent 	#
# 	PXML object. The below described functions are the event		#
#	(XML tag) handler functions.											#
#																					#
#	Each event hadler is called twice for each XML tag (open		#
#	and end tag). These calls can be identified by the tag name.#
#	Each event handler receives the following arguments:			#
#  	$sTag 			- tag name											#
#  	$sInsideText 	- reference to text between start and end #
#     $ParameterHash - hash of parameters,							#
#     $sId 				- current tag prefix,							#
#     $sFullTag 		- full text of current tag;					#
#																					#
#	Author: Zoltan Magyar													#
#																					#
#  Copyright (c)2002 Actinic Software Ltd 							#
#																					#
################################################################

package ACTINIC_PXML;
push (@INC, "cgi-bin");
<Actinic:Variable Name="IncludePathAdjustment"/>

require <Actinic:Variable Name="PXMLPackage"/>;
#
# Version
#
$ACTINIC_PXML::prog_name = 'ACTINIC_PXML.pm';	# Program Name
$ACTINIC_PXML::prog_name = $ACTINIC_PXML::prog_name;	# remove compiler warning
$ACTINIC_PXML::prog_ver = '$Revision: 21018 $ ';		# program version
$ACTINIC_PXML::prog_ver = substr($ACTINIC_PXML::prog_ver, 11); # strip the revision information
$ACTINIC_PXML::prog_ver =~ s/ \$//;					# and the trailers

#use constant Version => "1.0, (PXML: " . PXML->Version . ")";

############################################################
#
#  ACTINIC_PXML->new() - constructor for ACTINIC_PXML class
#
#  A very standard constructor. Derives itself from PXML and
#	set up the event handler functions.
#	See object header and PXML.pm for more details.
#
#  Author:	Ryszard Zybert  Dec  1 18:15:36 GMT 1999
#
#  Copyright (c) Actinic Software Ltd 1999
#
############################################################

use vars qw(@ISA);
@ISA = qw(PXML);											# inheritance

sub new
	{
	my $Proto = shift;
	my $Class = ref($Proto) || $Proto;
	my $self  = $Class->SUPER::new();				# dont pass arguments, we can use Set()

	bless ($self, $Class);
	#
	# Set up event handler functions
	#
	$self->Set(
				  ID						=>	'Actinic:',													# default prefix
				  XMLERROR				=> "<br>" . ACTINIC::GetPhrase(-1, 1972, $::g_sRequiredColor) . "<b>". ACTINIC::GetPhrase(-1, 218) . "</b>" . ACTINIC::GetPhrase(-1, 1970) . "<br>",
				  MAINFRAME				=>	sub { $self->MainFrameTagHandler(@_)		},		# handle url of main frame
				  PRICES					=> sub { $self->PriceTagHandler(@_)				},		# price tag
				  PRICE_EXPLANATION	=> sub { $self->ExplanationTagHandler(@_)		},		# price explanation tag				  
				  VAR						=> sub { $self->VarTagHandler(@_)				},		# var tag
				  SECTION				=> sub { $self->SectionTagHandler(@_)			},		# section tag
				  ADDRESSES				=> sub { $self->AddressTagHandler(@_)			},		# addresses tag
				  UNREG					=> sub { $self->UnregTagHandler(@_)				},		# unregistered user tag
				  IGNORE					=> sub { $self->IgnoreTagHandler(@_)			},		# IGNORE tag (deletes text)
				  REMOVE					=> sub { $self->RemoveTagHandler(@_)			},		# Remove tag (deletes text if its parameter not defined)
				  NOTINB2B				=> sub { $self->NotInB2BTagHandler(@_)			},		# NOTINB2B tag (deletes text)
				  BASEHREF				=> sub { $self->BaseHrefTagHandler(@_)			},		# BASEHREF tag
				  DEFAULT				=> sub { $self->DefaultTagHandler(@_)			},		# unknown tags here
				  XMLTEMPLATE			=> sub { $self->XMLTemplateTagHandler(@_)		},		# XML template tag handler
				  CARTERROR				=> sub { $self->CartErrorTagHandler(@_)		}, 	# Cart error placeholder
				  RETAIL_ONLY_SEARCH => sub { $self->RetailOnlySearchTagHandler(@_)},
				  LOCATION						=> sub { $self->LocationTagHandler(@_)					},	# LOCATION tags
				  EXTRAFOOTERTEXT				=> sub { $self->ExtraFooterTagHandler(@_)				},	# EXTRAFOOTERTEXT tags
				  EXTRACARTTEXT				=> sub { $self->ExtraCartTagHandler(@_)				},	# EXTRACARTTEXT tags
				  EXTRACARTBASEPLUSPERTEXT	=> sub { $self->ExtraCartBasePlusPerTagHandler(@_)	},	# EXTRACARTBASEPLUSPERTEXT tags
				  EXTRASHIPPINGTEXT			=> sub { $self->ExtraShippingTagHandler(@_)			},	# EXTRASHIPPINGTEXT tags
				  BASEPLUSPERRATEWARNING	=> sub { $self->BasePlusPerInfoTagHandler(@_)		},	# BASEPLUSPERRATEWARNING tags
				  DEFAULTTAXZONEMESSAGE		=> sub { $self->DefaultTaxZoneMessageTagHandler(@_)},	# DEFAULTTAXZONEMESSAGE tags
				  SHOWFORPRICESCHEDULE		=> sub { $self->ShowForPriceScheduleTagHandler(@_)	},		# ShowForPriceSchedule tags
				  COOKIECHECK					=> sub { $self->AddCookieCheck(@_)						}, # Cookie checking code placeholder
				 );
	$self->Set(@_);
	return $self;
	}

############################################################
#
#  ExplanationTagHandler - process the price explanation tag
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Zoltan Magyar  Feb  22 23:22 GMT 2001
#
#  Copyright (c) Actinic Software Ltd (2001)
#
############################################################

sub ExplanationTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;

	if( $sTag =~ /^\// )									# If End tag
		{
		return "";
		}

	if( $Self->{CurrentSectionBlob} )				# If section blob set				
		{
		my @Response;
		
			@Response = ACTINIC::GetProduct($ParameterHash->{PROD_REF}, $Self->{CurrentSectionBlob},
								ACTINIC::GetPath());			# get this product object		
		my ($Status, $Message, $pProduct) = @Response;
		if ($Status != $::SUCCESS)
			{
			return "";
			}													# If any problem, forget it

		if (defined $$pProduct{PRICES})
			{
			#
			# Need to work out which prices to show
			#
			my ($bShowRetailPrices, $bShowCustomerPrices, $nAccountSchedule) = ACTINIC::DeterminePricesToShow();
			my $sComments;
			if ($nAccountSchedule == -1)
				{
				$nAccountSchedule = $ActinicOrder::RETAILID;
				}
			#
			# Look up the apropriate product or component comment
			#
			if (defined $ParameterHash->{COMPONENTID} &&
				 $ParameterHash->{COMPONENTID} != -1)
				{
				my $nComponentID = $ParameterHash->{COMPONENTID};
				#
				# Check that associated product pricing is used or not
				# and select the appropriate message
				#
				if ($pProduct->{COMPONENTS}[$nComponentID][$::CBIDX_ASSOCPRODPRICE] == 1)	# if associated product prices are used
					{
					#
					# Get the message from associated product hash
					#
					my $Assoc = $pProduct->{COMPONENTS}[$nComponentID][$::CBIDX_PERMUTATIONS][0][$::PBIDX_ASSOCIATEDPROD];
					#
					# Check if the associated product blob is defined
					# It is not defined when the associated product is out of stock
					# or the permutation is invalid. The [3][0][1] item contains
					# '+' or '-' strings in these cases (IOW no explanation hash).
					#
					if (ref $Assoc eq 'HASH')
						{
						$sComments = $$Assoc{PRICE_COMMENTS}->{$nAccountSchedule};
						}
					}
				elsif (defined $pProduct->{COMPONENTS}[$nComponentID][$::CBIDX_EXPLANATION] &&
					 ref($pProduct->{COMPONENTS}[$nComponentID][$::CBIDX_EXPLANATION]) eq 'HASH')
					{
					$sComments = $pProduct->{COMPONENTS}[$nComponentID][$::CBIDX_EXPLANATION]->{$nAccountSchedule};
					}
				}
			else
				{
				$sComments = $pProduct->{'PRICE_COMMENTS'}->{$nAccountSchedule};
				}
			if ($sComments ne '')
				{
				$$sInsideText = ACTINIC::GetPhrase(-1, 2296). $sComments . ACTINIC::GetPhrase(-1, 2297);	# wrap non empty text with BLOCKQUOTES
				}
			}
		}
	return "";
	}

############################################################
#
#  RetailOnlySearchTagHandler - process the search tag
#
#  Note: <Actinic:Actinic:RETAIL_ONLY_SEARCH/> acts globally
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
############################################################

sub RetailOnlySearchTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;

	my $sDigest = $ACTINIC::B2B->Get('UserDigest');	# get the user identifying digest
	if ($sTag !~ /^\//)									# If not End tag
		{
		if ($sDigest)										# If there is a user remove tags and text
			{
			if (ref($sInsideText))
				{
				$$sInsideText = "";
				}
			}
		}
	else														# here on the second call (the end tag)
		{
		return ('');										# on the second pass, return nothing to prevent duplicate entries
		}
	#
	# If the buyer exists and does not see retail prices, note that the search is retail prices only
	#
	my $sRetailMessage = ACTINIC::GetPhrase(-1, 357);

	if ($sDigest)											# see which price schedule they use
		{
		my ($Status, $sMessage, $pBuyer) = ACTINIC::GetBuyer($sDigest, ACTINIC::GetPath()); # look up the buyer
		if ($Status == $::SUCCESS)
			{
			my $pAccount;
			($Status, $sMessage, $pAccount) = ACTINIC::GetCustomerAccount($pBuyer->{AccountID}, ACTINIC::GetPath()); # find the account information
			if ($Status == $::SUCCESS)
				{
				if ($pAccount->{PriceSchedule} == $ActinicOrder::RETAILID) # if we can confirm that this buyer is using the retail schedule
					{
					$sRetailMessage = '';				# the message is unnecessary
					}
				}
			}
		}

	return ($sRetailMessage);
	}

############################################################
#
#  AddressTagHandler - callback for addresses
#  Replaces <Actinic:ADDRESSES/> tag by address table
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Ryszard Zybert  Jan  3 16:44:37 GMT 2000
#
#  Copyright (c) Actinic Software Ltd (2000)
#
############################################################

sub AddressTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;
	my $sDigest = $ACTINIC::B2B->Get('UserDigest');

	if( $sTag =~ /^\// )									# Ignore end-tags
		{
		return "";
		}

	my ($Status, $sMessage, $pBuyer, $pAccount) = ACTINIC::GetBuyerAndAccount($sDigest, ACTINIC::GetPath());
	if ($Status != $::SUCCESS)
		{
		if ($Status != $::NOTFOUND)
			{
			ACTINIC::ReportError($sMessage, ACTINIC::GetPath());	# if the error is not the missing digest the error should be reported
			}
		return("");
		}
	#
	# Get the lists of valid addresses
	#
	my ($pAddress, $plistValidAddresses, $plistValidInvoiceAddresses, $plistValidDeliveryAddresses);
	($Status, $sMessage, $plistValidInvoiceAddresses, $plistValidDeliveryAddresses) =
		ACTINIC::GetCustomerAddressLists($pBuyer, $pAccount);
	if ($Status != $::SUCCESS)
		{
		return("");
		}

	my ($sType,$sSelect,$nRule,$sChecked);
	if ($ParameterHash->{TYPE} =~ /^INVOICE/)		# Invoice address
		{
		$plistValidAddresses = $plistValidInvoiceAddresses;
		if ($pAccount->{InvoiceAddressRule} == 1)	# The Customer rule overrides buyer rule
			{
			$nRule = 0;
			$sSelect = $pAccount->{InvoiceAddress};# Default (or fixed) address
			($Status, $sMessage, $pAddress) = ACTINIC::GetCustomerAddress($$pBuyer{AccountID}, $sSelect, ACTINIC::GetPath());
			if ($Status != $::SUCCESS)
				{
				ACTINIC::CloseCustomerAddressIndex(); # The customer index is left open for multiple access, so clean it up here
				return("");
				}
			}
		else
			{
			$nRule   = $pBuyer->{InvoiceAddressRule};	# Address rule for this user
			$sSelect = $pBuyer->{InvoiceAddressID};   # Default (or fixed) address
			if($nRule == 0 || ($nRule == 1 && $#$plistValidAddresses == 0))
				{
				$nRule = 0;
				$pAddress = $plistValidAddresses->[0];
				$sSelect  = $pAddress->{ID};
				}
			}
		}
	elsif( $ParameterHash->{TYPE} =~ /^DELIVERY/ )	# Delivery address
		{
		$plistValidAddresses = $plistValidDeliveryAddresses;
		$nRule   = $pBuyer->{DeliveryAddressRule};	# Address rule for this user
		if($nRule == 0)
			{
			$sSelect  = $pBuyer->{DeliveryAddressID};
			($Status, $sMessage, $pAddress) = ACTINIC::GetCustomerAddress($$pBuyer{AccountID}, $sSelect, ACTINIC::GetPath());
			if ($Status != $::SUCCESS)
				{
				ACTINIC::CloseCustomerAddressIndex(); # The customer index is left open for multiple access, so clean it up here
				return ("");
				}
			}
		elsif($nRule == 1 && $#$plistValidAddresses == 0)
			{
			$nRule = 0;
			$pAddress = $plistValidAddresses->[0];
			$sSelect  = $pAddress->{ID};
			}
		else
			{
			$sSelect = $pBuyer->{DeliveryAddressID};	# Default (or fixed) address
			}
		}
	if( $ParameterHash->{TYPE} =~ /FORM$/ )		# Address form
		{
		if( $nRule != 2 )									# Only shown for Rule 2
			{
			$$sInsideText = "";
			}
		ACTINIC::CloseCustomerAddressIndex();		# The customer index is left open for multiple access, so clean it up here
		return "";
		}

	ACTINIC::CloseCustomerAddressIndex();			# The customer index is left open for multiple access, so clean it up here

	#
	# Format 'mini templates'.
	# Table title and address format depend on $nRule, there must be one for each rule
	#
	my $sTableFormat   	= $Self->{Variables}->{ADDRESS_TABLE};
	my $sTitle         	= $Self->{Variables}->{'ADDRESS_TITLE' . $nRule};
	my $sTitle_1        	= $Self->{Variables}->{'ADDRESS_TITLE1' . $nRule};
	my $sForm				= '<TD>' . $Self->{Variables}->{'ADDRESS_FORM' . $nRule} . '</TD>';
	#
	# Number of columns only matters if it results in more than one row
	# Otherwise existing addresses will expand to fill the table
	#
	my $nColumns         = $Self->{Variables}->{ADDRESS_COLUMNS} || 1;		# Number of columns - default to 1

	if( !$sForm or !$sTableFormat )
		{
		return "";
		} 														# No formats - we cannot do that

	my $sAddressText = "";

	if( $nRule == 0 )										# Rule 0 - fixed address
		{
		$sAddressText .= '<TR><TD>';					# Just a single cell
		$sAddressText .= sprintf($sForm,
										 $sSelect,						# Address ID
										 $pAddress->{Name},			# Address text follows
										 $pAddress->{Line1},
										 $pAddress->{Line2},
										 $pAddress->{Line3},
										 $pAddress->{Line4},
										 $pAddress->{PostCode},
										 ACTINIC::GetCountryName($pAddress->{CountryCode}));
		$sAddressText .= '</TD></TR>';
		}
	else														# Rule 1 - select from list
		{														# Rule 2 - select or fill form
		$sTitle = sprintf($sTitle,ACTINIC::GetPhrase(-1, 302));	# Insert title from prompts
		if( $nRule == 2 )														# Insert text for address form
			{
			if( $ParameterHash->{TYPE} =~ /^INVOICE/ )
				{
				$sTitle_1 = sprintf($sTitle_1,ACTINIC::GetPhrase(-1, 303,ACTINIC::GetPhrase(-1, 304)));
				}
			else
				{
				$sTitle_1 = sprintf($sTitle_1,ACTINIC::GetPhrase(-1, 303,ACTINIC::GetPhrase(-1, 305)));
				}
			}
		my $nCount = 0;
		my $nRowCount = 0;
		my $sCh;

		foreach $pAddress (@$plistValidAddresses)
			{
			if( $nCount % $nColumns == 0 )
				{
				$sAddressText .= '<TR VALIGN="TOP">';	# New row
				}
			if( $pAddress->{ID} eq $sSelect and $nRule == 1 )	# For Rule 1 check default address
				{
				$sCh = ' CHECKED';
				}
			else
				{
				$sCh = '';
				}

			$sAddressText .= sprintf($sForm,
											 ACTINIC::GetPhrase(-1, 301),
											 $pAddress->{ID},				# Address ID (for RADIO button)
											 $sCh,							# Optional 'CHECKED'
											 $pAddress->{Name},			# Address text follows
											 $pAddress->{Line1},
											 $pAddress->{Line2},
											 $pAddress->{Line3},
											 $pAddress->{Line4},
											 $pAddress->{PostCode},
											 ACTINIC::GetCountryName($pAddress->{CountryCode}));

			$nCount++;										# Count cells
			if( $nCount % $nColumns == 0 )			# Full row
				{
				$sAddressText .= '</TR>';				# Close row
				$nRowCount++;								# Count rows
				}
			}

		while( $nCount % $nColumns != 0 )			# Close table row if not closed
			{
			if( $nRowCount > 0 ) { $sAddressText .= '<TD>&nbsp;</TD>' }	# If more than one row - add empty cells
			$nCount++;
			if( $nCount % $nColumns == 0 )
				{
				$sAddressText .= '</TR>';
				last;
				}
			}
				}
	$sAddressText =~ s/<br>[,\s]*/<br>/gi;			# Remove leading commas
	$sAddressText =~ s/[,\s]*<br>/<br>/gi;			# Remove trailing commas
	$sAddressText =~ s/(<br>)+/<br>/gi;				# Remove blank lines
	return sprintf($sTableFormat,
						$sTitle,
						$$::g_pSetupBlob{FORM_EMPHASIS_COLOR}, 	# Border
						$$::g_pSetupBlob{FORM_BACKGROUND_COLOR}, 	# Background
						$sAddressText,
						$sTitle_1);

	return "";
	}


############################################################
#
#  sub VarTagHandler - callback for variables
#  Sets variables
#  There should be NAME and VALUE parameters
#  $Self->{Variables}->{name} is set to value
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Ryszard Zybert  Dec  7 20:58:25 GMT 1999
#
#  Copyright (c) Actinic Software Ltd (1999)
#
############################################################

sub VarTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;

	if( $sTag !~ /^\// )
		{
		$Self->{Variables}->{$ParameterHash->{NAME}} = $ParameterHash->{VALUE};
		}
	return "";
	}

############################################################
#
#  sub CartErrorTagHandler - cart error tag handler
#
#  If any error message is set for the actual product reference
#  (in the ProdRef parameter) then replace the tag to the
#  error message.
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Zoltan Magyar, 5/14/2003
#
#  Copyright (c) Actinic Software Ltd 2003
#
############################################################

sub CartErrorTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;

	if( $sTag =~ /^\// )
		{
		return "";
		}
	#
	# Check if we have error message stored for the actual product reference
	#
	my $sErrorValue = $ACTINIC::B2B->GetXML("CartError_" . $ParameterHash->{ProdRef});
	if (defined $sErrorValue)
		{
		return $sErrorValue;
		}

	return "";
	}

############################################################
#
#  sub DefaultTagHandler - callback for unknown tags
#  Looks up the tag in the B2B XML Tags hash
#  If found - replaces the tag by it
#  (meaning the whole <Actinic:$sTag....> sequence)
#  If not doesn't -leaves everything untouched
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Ryszard Zybert  Dec  7 20:58:25 GMT 1999
#
#  Copyright (c) Actinic Software Ltd (1999)
#
############################################################

sub DefaultTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;
	my $sXMLTag = $ACTINIC::B2B->GetXML($sTag);
	if (defined $sXMLTag)
		{
		return $sXMLTag;
		}
	return $sFullTag;
	}

############################################################
#
#  XMLTemplateTagHandler - callback for XMLTEMPLATE tags
#  Looks up the NAME parameter in the B2B XML Tags hash
#  If found - replaces the tag by it
#  (meaning the whole <Actinic:$sTag....>  </...> sequence)
#  If not doesn't - removes everything
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Ryszard Zybert  Dec  7 20:58:25 GMT 1999
#
#  Copyright (c) Actinic Software Ltd (1999)
#
############################################################

sub XMLTemplateTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;

	if( $sTag =~ /^\// )									# Ignore end-tag completely
		{
		return "";
		}

	my $sTagname = $ParameterHash->{NAME};
	my $sXMLTag = $ACTINIC::B2B->GetXML($sTagname);

	if (defined $sXMLTag)
		{
		$$sInsideText = "";								# replace (i.e. don't leave enclosed text)
		return $sXMLTag;									# return replacement
		}
	$$sInsideText = "";
	return "";
	}

############################################################
#
#  sub RetailPriceTextTagHandler - callback for retail text
#  Sets XML variable
#  B2B->{XML}->{tag} is set to value of text between tags
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : empty string
#
############################################################


sub RetailPriceTextTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;

	if( $sTag !~ /^\// )									# Ignore end-tag completely
		{
		if(ref($sInsideText))							# If there is text store it in XML variable
			{
			$ACTINIC::B2B->SetXML($sTag, $$sInsideText);
			my $sDigest = $ACTINIC::B2B->Get('UserDigest');
			if ($sDigest)
				{
				$$sInsideText = "";						# Text not needed anymore for logged in
				}
			}
		}
	return "";												# Both tags also removed
	}

############################################################
#
#  DefaultRemovingTagHandler - callback for unknown tags
#  As DefaultTagHandler except that unknown tags are removed
#  together with all text between tags
#
#  Looks up the tag in the B2B XML Tags hash
#  If found - replaces the tag by it
#  (meaning the whole <Actinic:$sTag....> sequence)
#  If not removes everything
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Ryszard Zybert  Dec  7 20:58:25 GMT 1999
#
#  Copyright (c) Actinic Software Ltd (1999)
#
############################################################

sub DefaultRemovingTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;

	my $sXMLTag = $ACTINIC::B2B->GetXML($sTag);
	if( defined($sXMLTag) )								# Don't touch text, return replacement tag
		{
		return $sXMLTag;
		}
	else														# Clear both text and tag
		{
		if( ref($sInsideText) )
			{
			$$sInsideText = "";
			}
		return "";
		}
	}

############################################################
#
#  IgnoreTagHandler
#  Remove text within the tag and the tag
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Ryszard Zybert  Jul 25 22:30:51 BST 2000
#
#  Copyright (c) Actinic Software Ltd (2000)
#
############################################################

sub IgnoreTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;
	if( ref($sInsideText) )
		{
		$$sInsideText = "";
		}
	return "";
	}

############################################################
#
#  RemoveTagHandler
#  Remove text within the tag and the tag if the tag is not defined
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Zoltan Magyar  10:30 PM 3/13/2002
#
#  Copyright (c)2002 Actinic Software Ltd
#
############################################################

sub RemoveTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;

	my $sTagID;
	if( $ParameterHash->{TAG} )					# VALUE contains HREF
		{
		$sTagID = $ParameterHash->{TAG};		# use it
		}
	my $sXMLTag = $ACTINIC::B2B->GetXML($sTagID);
	if( ref($sInsideText) && !$sXMLTag)
		{
		$$sInsideText = "";
		}
	return "";
	}

############################################################
#
#  sub BaseHrefTagHandler
#  Insert BASE HREF tag so that it is only present in dynamic pages
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Zoltan Magyar
#
#   Copyright (c) Actinic Software Ltd (2000)
#
############################################################

sub BaseHrefTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;
	if( $sTag =~ /^\// )									# If not End tag
		{
		return "";
		}
	my $sReplace;
	my $sURL;
	if (defined $::Session)
		{
		$sURL = $::Session->GetBaseUrl();
		}
	#
	# Separated CGI and catalog servers and the store branding are
	# mutually exclusive. So don't care store branding feature when
	# SSL is used for login and checkout pages only
	#
	if ($$::g_pSetupBlob{'SSL_USEAGE'} == "1")	# if SSL is used for some pages
		{
		if( $ParameterHash->{VALUE} )					# VALUE contains HREF
			{
			$sReplace = $ParameterHash->{VALUE};	# use it
			}
		}
	#
	# Otherwise try to detemine the correct BASE HREF value to
	# maintain the store branding feature.
	#
	else
		{
		if ($sURL)										# if non script page found use it
			{
			$sReplace = $sURL;							# use referer
			}
		elsif( $ParameterHash->{VALUE} )				# VALUE contains HREF
			{
			$sReplace = $ParameterHash->{VALUE};	# use it
			}
		#
		# If it is the Brochure index page uploaded above acatalog
		# the fix up the URL by removing acatalog/
		#
		if ( $ParameterHash->{FORCED} )
			{
			my $StoreFolderName = ACTINIC::GetStoreFolderName();
			$sReplace =~ s/$StoreFolderName\/$//;
			}
		}
	$$sInsideText = '<BASE HREF="' . $sReplace . '">';	# Insert the tag

	return "";
	}

############################################################
#
#  NotInB2BTagHandler
#  If there is a registered user removes the tags end text between
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Ryszard Zybert  Jul 28 14:20:06 BST 2000
#
#  Copyright (c) Actinic Software Ltd (2000)
#
############################################################

sub NotInB2BTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;

	if( $sTag !~ /^\// )																						# If not End tag
		{
		my $sDigest = $ACTINIC::B2B->Get('UserDigest');
		if( $sDigest )			# If there is a user remove tags and text
			{
			if( ref($sInsideText) )
				{
				$$sInsideText = "";
				}
			}
		}
	return "";
	}

############################################################
#
#  UnregTagHandler - callback for UNREG tag
#  If there is a registered user removes the tags end text between
#  Otherwise produces a warning page and bounces to login page
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Ryszard Zybert  May 16 15:23:37 BST 2000
#
#  Copyright (c) Actinic Software Ltd (1999)
#
############################################################

sub UnregTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;
	my $sDigest = $ACTINIC::B2B->Get('UserDigest');

	if( $sTag =~ /^\// )																						# If not End tag
		{
		return "";
		}
	#
	# When we get here by an invalid user or password from the login page on a closed B2B site
	# the $sDigest won't be defined and we get "unregistered customers not allowed" error
	# instead of "invalid user" message.
	# So lets be tricky and check this case as well.
	#
	if( $sDigest ||										# If there is a user remove tags and text
		 $::g_bLoginPage )								# or invalid user or password
		{
		if( ref($sInsideText) ) { $$sInsideText = ""; }
		return "";
		}
	elsif ($::prog_name ne "SearchScript" && $::prog_name ne "SearchHighligh")
		{
		#
		# If we were here already then the processing should be stopped here
		# to avoid infinitive loop
		#
		if ($::g_RECURSION_ACTIVE)
			{
			return "";
			}
		#
		# This will only have effect if JavaScript is disabled.
		# Otherwise there is a JavaScript alert and this script is no called
		# So - in this case we just show warning and jup back to original page
		#
		my ($Status, $sError, $sHTML) = ACTINIC::ReturnToLastPage(7," " ,
																					 ACTINIC::GetPhrase(-1, 208),
																					$::g_sWebSiteUrl,
																					$::g_sContentUrl, $::g_pSetupBlob, %::g_InputHash);
		if ($Status != $::SUCCESS)						# If even this didn't work - we give up - there is an error
			{
			ACTINIC::ReportError($sError, ACTINIC::GetPath());
			}
		#
		# ACTINIC::PrintPage calls the parser again
		# We should make sure this function won't be called recursively
		# so se a flag here and check above
		#
		$::g_RECURSION_ACTIVE = $::TRUE;
		ACTINIC::PrintPage($sHTML, undef, $::TRUE);	# Print warning page and exit
		exit;
		}
	return "";
	}

############################################################
#
#  PriceTagHandler - price tag callback
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Ryszard Zybert  Dec  7 21:06:24 GMT 1999
#
#  Copyright (c) Actinic Software Ltd (1999)
#
############################################################

sub PriceTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;
	
	if( $sTag =~ /^\// )									# If not End tag
		{
		return "";
		}
	
	if( !$Self->{CurrentSectionBlob} ||				# If section blob not set
		 !$ACTINIC::B2B->Get('UserDigest') )		# or not Business customer
		{
		return "";											# then nothing to do
		}
		
	my @Response;
	#
	# We need the tax information to calculate the prices
	#
	if (!$ActinicOrder::bTaxDataParsed)
		{
		#
		# read the tax blob
		#
		@Response = ACTINIC::ReadTaxSetupFile(ACTINIC::GetPath());
		if ($Response[0] != $::SUCCESS)
			{
			return (@Response);
			}
		ActinicOrder::ParseAdvancedTax();
		}
	@Response = ACTINIC::GetProduct($ParameterHash->{PROD_REF}, $Self->{CurrentSectionBlob},
												ACTINIC::GetPath());	# get this product object
	my ($Status, $Message, $pProduct) = @Response;
	if ($Status != $::SUCCESS)
		{
		return "";											# if any problem, forget it
		}			
	#
	# If we have prices defined for the product, display them
	#
	if (defined $$pProduct{PRICES})
		{
		@Response = ActinicOrder::GetProductPricesHTML($pProduct, undef, $Self->{CurrentSectionBlob});
		$$sInsideText = ($Response[0] != $::SUCCESS) ? $Response[1] : $Response[2];
		}

	return "";																									# Always remove tag
	}

############################################################
#
#  sub SectionTagHandler - section tag callback
#
#  Note: <Actinic:SECTION BLOB="blob file name"/> acts globally
#        $Self->{CurrentSectionBlob} is set here and kept
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Ryszard Zybert  Dec  20 21:06:24 GMT 1999
#
#  Copyright (c) Actinic Software Ltd (1999)
#
############################################################

sub SectionTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId) = @_;

	if( $sTag !~ /^\// )									# If not End tag
		{
		$Self->{CurrentSectionBlob} = $ParameterHash->{BLOB};
		}
	return "";												# Always remove tag
	}

############################################################
#
#  sub MainFrameTagHandler
#  replace SRC parameter in a FRAME tag
#
#  If MAINFRAME XML variable is defined and SRC=name is found
#  in inside text, name will be replaced by the value of MAINFRAME XML
#  variable.
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Ryszard Zybert  Jul 18 11:26:08 BST 2000
#
#  Copyright (c) Actinic Software Ltd (2000)
#
############################################################

sub MainFrameTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId) = @_;

	if( $sTag =~ /^\// )									# If not End tag
		{
		return "";
		}

	my $sXMLTag;
	if( $::g_InputHash{MAINFRAMEURL} )
		{
		$sXMLTag = $::g_InputHash{MAINFRAMEURL};
		}
	else
		{
		$sXMLTag = $ACTINIC::B2B->GetXML("MAINFRAMEURL");
		}
	if( defined($sXMLTag) )								# Replace SRC parameter by tag value
		{
		if( ref($sInsideText) )
			{
			if( $sXMLTag !~ /^((http(s?):)|(\/))/ )
				{
				#
				# Be sure we don't get frames in frames
				#
				if( $sXMLTag eq $$::g_pSetupBlob{FRAMESET_PAGE} )	# for catalog
					{
					$sXMLTag = $$::g_pSetupBlob{CATALOG_PAGE};
					}
				if( $sXMLTag eq $$::g_pSetupBlob{BROCHURE_FRAMESET_PAGE} )	# for brochure
					{
					$sXMLTag = $$::g_pSetupBlob{BROCHURE_MAIN_PAGE};
					}
				#
				# We should use absolute URLs here
				#
				$sXMLTag = $::g_sAccountScript . '?' . ($::g_InputHash{SHOP} ?	'SHOP=' . $::g_InputHash{SHOP} . "&" : "") . 'PRODUCTPAGE=' . $sXMLTag;
				}
			$$sInsideText =~ s/(\s+SRC\s*=\s*)((\"[^\"]+\")|([^\ \>]+))((\s+)|(\>+))/$1\"$sXMLTag\"$5/is;
			}
		}
	return "";												# Always remove tag
	}

############################################################
#
# LocationTagHandler - callback for LOCATION tag
#
# Displays the location in the appropriate form
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
############################################################

sub LocationTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;

	if( $sTag =~ /^\// )
		{
		return "";
		}

	my $sType = $ParameterHash->{TYPE};
	my ($sHTMLFormat, $sHTML, $sReplace);
	my $sNonEditableFormat = ACTINIC::GetPhrase(-1, 2066);
	my $sEditableFormat = ACTINIC::GetPhrase(-1, 2067, ACTINIC::GetPhrase(-1, 1973), '%s', ACTINIC::GetPhrase(-1, 1970), '%s', '%s', ACTINIC::GetPhrase(0, 18));
	my $sDigest = $ACTINIC::B2B->Get('UserDigest');
	#
	# Get the lists of valid customer account buyer addresses
	#
	my ($pAddress,
		$plistValidInvoiceAddresses, $plistValidDeliveryAddresses,
		$nInvoiceID, $nDeliveryID,
		$sCountryInvoiceHTML, $sStateInvoiceHTML,
		$sCountryDeliveryHTML, $sStateDeliveryHTML);
	$nInvoiceID = -1;
	$nDeliveryID = -1;
	my ($pSingleInvoiceAddress, $pSingleDeliveryAddress);
	if($sDigest ne '')
		{
		my ($Status, $sMessage, $pBuyer, $pAccount) = ACTINIC::GetBuyerAndAccount($sDigest, ACTINIC::GetPath());
		if ($Status != $::SUCCESS)
			{
			ACTINIC::ReportError($sMessage, ACTINIC::GetPath());
			}
		($Status, $sMessage,
			$plistValidInvoiceAddresses, $plistValidDeliveryAddresses,
			$nInvoiceID, $nDeliveryID) =
				ACTINIC::GetCustomerAddressLists($pBuyer, $pAccount, $::TRUE);
		if ($Status != $::SUCCESS)
			{
			ACTINIC::ReportError($sMessage, ACTINIC::GetPath());
			}
		#
		# If there's a single invoice address, get it
		#
		if($nInvoiceID != -1)
			{
			$pSingleInvoiceAddress = pop(@$plistValidInvoiceAddresses);
			}
		elsif($pBuyer->{InvoiceAddressRule} == 1)
			{
			($Status, $sMessage, $sCountryInvoiceHTML, $sStateInvoiceHTML) =
				ActinicOrder::GetBuyerLocationSelections($plistValidInvoiceAddresses,
					'LocationInvoiceCountry', 'LocationInvoiceRegion',
					'lstInvoiceCountry', 'lstInvoiceRegion',
					'INVOICE', $pBuyer->{InvoiceAddressID});
			}
		#
		# If there's a single delivery address, get it
		#
		if($nDeliveryID != -1)
			{
			$pSingleDeliveryAddress = pop(@$plistValidDeliveryAddresses);
			}
		elsif($pBuyer->{DeliveryAddressRule} == 1)
			{
			($Status, $sMessage, $sCountryDeliveryHTML, $sStateDeliveryHTML) =
				ActinicOrder::GetBuyerLocationSelections($plistValidDeliveryAddresses,
					'LocationDeliveryCountry', 'LocationDeliveryRegion',
					'lstDeliveryCountry', 'lstDeliveryRegion',
					'DELIVERY', $pBuyer->{DeliveryAddressID});
			}
		}
	if(ref($sInsideText))
		{
		if(!$$::g_pLocationList{EXPECT_INVOICE} && !$$::g_pLocationList{EXPECT_DELIVERY})
			{
			return('');
			}
		#
		# Handle location selection for customer accounts
		#
		# Start with delivery country selection
		#
		if($sType eq 'DELIVERSELECTCOUNTRY')		# location country selection?
			{
			if($pSingleDeliveryAddress)
				{
				$$sInsideText = sprintf($sNonEditableFormat,
					ACTINIC::GetCountryName($pSingleDeliveryAddress->{CountryCode}),
					'LocationDeliveryCountry',
					$pSingleDeliveryAddress->{CountryCode});
				}
			elsif($sCountryDeliveryHTML ne '')
				{
				$$sInsideText = $sCountryDeliveryHTML;
				}
			}
		#
		# Next with delivery state selection
		#
		if($sType eq 'DELIVERSELECTSTATE')			# location state selection?
			{
			if($pSingleDeliveryAddress)
				{
				my $sStateName = ACTINIC::GetCountryName($pSingleDeliveryAddress->{StateCode});
				$$sInsideText = sprintf($sNonEditableFormat,
					($sStateName ne '') ? $sStateName : '',
					'LocationDeliveryRegion',
					($sStateName ne '') ? $pSingleDeliveryAddress->{StateCode} : $ActinicOrder::UNDEFINED_REGION);
				}
			elsif($sStateDeliveryHTML ne '')
				{
				$$sInsideText = $sStateDeliveryHTML;
				}
			}
		#
		# Next invoice country selection
		#
		if($sType eq 'INVOICESELECTCOUNTRY')		# location country selection?
			{
			if($pSingleInvoiceAddress)
				{
				$$sInsideText = sprintf($sNonEditableFormat,
					ACTINIC::GetCountryName($pSingleInvoiceAddress->{CountryCode}),
					'LocationInvoiceCountry',
					$pSingleInvoiceAddress->{CountryCode});
				}
			elsif($sCountryInvoiceHTML ne '')
				{
				$$sInsideText = $sCountryInvoiceHTML;
				}
			}
		#
		# Next invoice state selection
		#
		if($sType eq 'INVOICESELECTSTATE')			# location state selection?
			{
			if($pSingleInvoiceAddress)
				{
				my $sStateName = ACTINIC::GetCountryName($pSingleInvoiceAddress->{StateCode});
				$$sInsideText = sprintf($sNonEditableFormat,
					($sStateName ne '') ? $sStateName : '',
					'LocationInvoiceRegion',
					($sStateName ne '') ? $pSingleInvoiceAddress->{StateCode} : $ActinicOrder::UNDEFINED_REGION);
				}
			elsif($sStateInvoiceHTML ne '')
				{
				$$sInsideText = $sStateInvoiceHTML;
				}
			}
		if($sType eq 'SEPARATESHIP')					# separate shipping address?
			{
			if($::g_LocationInfo{SEPARATESHIP})		# turned on?
				{
				$sReplace = sprintf($sEditableFormat,
					ACTINIC::GetPhrase(-1, 1914),
					$sType,
					ACTINIC::GetPhrase(-1, 1914));
				}
			else
				{
				$sReplace = sprintf($sEditableFormat,
					ACTINIC::GetPhrase(-1, 1915),
					$sType,
					"");
				}
			$$sInsideText =~ s/<INPUT .*?>/$sReplace/ig;
			#
			# Replace the checkbox instruction prompt with an appropriate label
			#
			my $sPrompt = quotemeta ACTINIC::GetPhrase(0, 16);
			$sReplace = ACTINIC::GetPhrase(0, 19);
			if($sPrompt ne '')
				{
				$$sInsideText =~ s/$sPrompt/$sReplace/;
				}
			}
		#
		# If we're expecting invoice information or
		# we expect delivery but the same addresses are used
		#
		if($$::g_pLocationList{EXPECT_INVOICE} ||
			($$::g_pLocationList{EXPECT_DELIVERY} && $::g_LocationInfo{SEPARATESHIP} eq ''))
			{
			#
			# Get the number of available countries depending upon whether we expect invoica and/or delivery info
			#
			my $nCountryCount;
			if($$::g_pLocationList{EXPECT_INVOICE})
				{
				$nCountryCount = $$::g_pLocationList{INVOICE_COUNTRY_COUNT};
				}
			else
				{
				$nCountryCount = $$::g_pLocationList{DELIVERY_COUNTRY_COUNT};
				}
			#
			# Now go through the location tag types
			#
			if($sType eq 'INVOICEPOSTALCODE')
				{
				if($nInvoiceID != -1)
					{
					$sReplace = sprintf($sNonEditableFormat,
						$::g_LocationInfo{INVOICEPOSTALCODE},
						$sType,
						$::g_LocationInfo{INVOICEPOSTALCODE});

					$$sInsideText =~ s/<INPUT .*?>/$sReplace/ig;
					}
				elsif((defined $$::g_pLocationList{INVOICEPOSTALCODE} &&
					$$::g_pLocationList{INVOICEPOSTALCODE}) ||
					(defined $$::g_pLocationList{DELIVERPOSTALCODE} &&
					$$::g_pLocationList{DELIVERPOSTALCODE} &&
					$::g_LocationInfo{SEPARATESHIP} eq ''))
					{
					$sReplace = sprintf($sEditableFormat,
						$::g_LocationInfo{INVOICEPOSTALCODE},
						$sType,
						$::g_LocationInfo{INVOICEPOSTALCODE});

					$$sInsideText =~ s/<INPUT .*?>/$sReplace/ig;
					}
				}
			elsif($sType eq 'INVOICEADDRESS3')
				{
#					$$sInsideText = '<TD>' .$sType. '</TD>';
				}
			elsif($sType eq 'INVOICEADDRESS4')
				{
				if(((defined $$::g_pLocationList{INVOICEADDRESS4} &&
					$$::g_pLocationList{INVOICEADDRESS4}) ||
					(defined $$::g_pLocationList{DELIVERADDRESS4} &&
					$$::g_pLocationList{DELIVERADDRESS4} &&
					$::g_LocationInfo{SEPARATESHIP} eq '')) &&
					$::g_LocationInfo{INVOICE_REGION_CODE} &&
					$::g_LocationInfo{INVOICE_REGION_CODE} ne $ActinicOrder::UNDEFINED_REGION)
					{
					if($$::g_pLocationList{$::g_LocationInfo{INVOICE_COUNTRY_CODE}}{INVOICE_STATE_COUNT} < 2)
						{
						$sHTMLFormat = $sNonEditableFormat;
						}
					else
						{
						$sHTMLFormat = $sEditableFormat;
						}
					$sReplace = sprintf($sHTMLFormat,
						ACTINIC::GetCountryName($::g_LocationInfo{INVOICE_REGION_CODE}),
						$sType,
						ACTINIC::GetCountryName($::g_LocationInfo{INVOICE_REGION_CODE}));

					$$sInsideText =~ s/<INPUT .*?>/$sReplace/ig;						
					}
				else
					{
					#
					# There is a new case when state is not used but specified by dropdown
					# we should deal with that one as well by determining the state name
					# from the region code
					#
					$sReplace = ACTINIC::GetCountryName($::g_LocationInfo{INVOICE_REGION_CODE});
					$$sInsideText =~ s/VALUE\s*=\s*("|').*('|")/VALUE="$sReplace"/ig;	;
					}				
				}
			elsif($sType eq 'INVOICECOUNTRY')
				{
				if(($$::g_pLocationList{INVOICECOUNTRY} ||
					($$::g_pLocationList{DELIVERCOUNTRY} && $::g_LocationInfo{SEPARATESHIP} eq '')))
					{
					#
					# Find out which country code we should be using
					#
					my $sKnownCountryCode;
					if($$::g_pLocationList{INVOICECOUNTRY})
						{
						if($::g_LocationInfo{INVOICE_COUNTRY_CODE} ne $ActinicOrder::UNDEFINED_COUNTRY &&
							$::g_LocationInfo{INVOICE_COUNTRY_CODE} ne $ActinicOrder::REGION_NOT_SUPPLIED)
							{
							$sKnownCountryCode = $::g_LocationInfo{INVOICE_COUNTRY_CODE};
							}
						}
					elsif($$::g_pLocationList{DELIVERCOUNTRY} && $::g_LocationInfo{SEPARATESHIP} eq '')
						{
						if($::g_LocationInfo{DELIVERY_COUNTRY_CODE} ne $ActinicOrder::UNDEFINED_COUNTRY &&
							$::g_LocationInfo{DELIVERY_COUNTRY_CODE} ne $ActinicOrder::REGION_NOT_SUPPLIED)
							{
							$sKnownCountryCode = $::g_LocationInfo{DELIVERY_COUNTRY_CODE};
							}
						}
					#
					# If we don't have a code, leave untouched
					#
					if($sKnownCountryCode eq '')
						{
						return('');
						}
					#
					# Decide whether we can change it
					#
					if($nCountryCount < 2)
						{
						$sHTMLFormat = $sNonEditableFormat;
						}
					else
						{
						$sHTMLFormat = $sEditableFormat;
						}
					#
					# Format the replacement
					#
					$sReplace = sprintf($sHTMLFormat,
						ACTINIC::GetCountryName($::g_LocationInfo{INVOICE_COUNTRY_CODE}),
						$sType,
						ACTINIC::GetCountryName($::g_LocationInfo{INVOICE_COUNTRY_CODE}));
					#
					# Do the replacement
					#
					$$sInsideText =~ s/<INPUT .*?>/$sReplace/ig;
					}
				}
			}

		if($$::g_pLocationList{EXPECT_DELIVERY} ||
			($$::g_pLocationList{EXPECT_INVOICE} && $::g_LocationInfo{SEPARATESHIP} eq ''))
			{
			#
			# Get the number of available countries depending upon whether we expect invoica and/or delivery info
			#
			my $nCountryCount;
			if($$::g_pLocationList{EXPECT_DELIVERY})
				{
				$nCountryCount = $$::g_pLocationList{DELIVERY_COUNTRY_COUNT};
				}
			else
				{
				$nCountryCount = $$::g_pLocationList{INVOICE_COUNTRY_COUNT};
				}
			if($sType eq 'DELIVERPOSTALCODE')
				{
				if($$::g_pLocationList{DELIVERPOSTALCODE})
					{
					$sReplace = sprintf($sEditableFormat,
						$::g_LocationInfo{DELIVERPOSTALCODE},
						$sType,
						$::g_LocationInfo{DELIVERPOSTALCODE});

					$$sInsideText =~ s/<INPUT .*?>/$sReplace/ig;
					}
				}
			elsif($sType eq 'DELIVERADDRESS3')
				{
#					$$sInsideText = '<TD>' .$sType. '</TD>';
				}
			elsif($sType eq 'DELIVERADDRESS4')
				{
				if($::g_LocationInfo{DELIVERY_REGION_CODE} &&
					$::g_LocationInfo{DELIVERY_REGION_CODE} ne $ActinicOrder::UNDEFINED_REGION &&
					(defined $$::g_pLocationList{DELIVERADDRESS4} &&
					$$::g_pLocationList{DELIVERADDRESS4}))
					{
					if($$::g_pLocationList{$::g_LocationInfo{DELIVERY_COUNTRY_CODE}}{DELIVERY_STATE_COUNT} < 2)
						{
						$sHTMLFormat = $sNonEditableFormat;
						}
					else
						{
						$sHTMLFormat = $sEditableFormat;
						}
					$sReplace = sprintf($sHTMLFormat,
						ACTINIC::GetCountryName($::g_LocationInfo{DELIVERY_REGION_CODE}),
						$sType,
						ACTINIC::GetCountryName($::g_LocationInfo{DELIVERY_REGION_CODE}));

					$$sInsideText =~ s/<INPUT .*?>/$sReplace/ig;
					}
				else
					{
					#
					# There is a new case when state is not used but specified by dropdown
					# we should deal with that one as well by determining the state name
					# from the region code
					#
					$sReplace = ACTINIC::GetCountryName($::g_LocationInfo{DELIVERY_REGION_CODE});
					$$sInsideText =~ s/VALUE\s*=\s*("|').*('|")/VALUE="$sReplace"/ig;	;
					}					
				}
			elsif($sType eq 'DELIVERCOUNTRY')
				{
				if($::g_LocationInfo{DELIVERY_COUNTRY_CODE} &&
					$::g_LocationInfo{DELIVERY_COUNTRY_CODE} ne $ActinicOrder::UNDEFINED_COUNTRY &&
					$::g_LocationInfo{DELIVERY_COUNTRY_CODE} ne $ActinicOrder::REGION_NOT_SUPPLIED)
					{
					if($nCountryCount < 2)
						{
						$sHTMLFormat = $sNonEditableFormat;
						}
					else
						{
						$sHTMLFormat = $sEditableFormat;
						}
					$sReplace = sprintf($sHTMLFormat,
						ACTINIC::GetCountryName($::g_LocationInfo{DELIVERY_COUNTRY_CODE}),
						$sType,
						ACTINIC::GetCountryName($::g_LocationInfo{DELIVERY_COUNTRY_CODE}));

					$$sInsideText =~ s/<INPUT .*?>/$sReplace/ig;
					}
				}
			}
		}

	return('');
	}

############################################################
#
# ExtraFooterTagHandler - callback for ExtraFooter tag
#
# Displays the extra footer in the appropriate form
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Mike Purnell
#
############################################################

sub ExtraFooterTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;

	if( $sTag !~ /^\// )
		{
		if(ref($sInsideText))
			{
			my $nSSPProviderID;
			my $sTemplate = $$sInsideText;
			$$sInsideText = '';
			#
			# For each shipping provider display their trademark text + logo
			#
			my %hTrademarkProviderIDs;
			if ($ACTINIC::B2B->GetXML('ShippingDisclaimingDisplayed') == $::TRUE)											# we are on the shipping charge checkout page
				{
				%hTrademarkProviderIDs = (%::s_Ship_hShippingClassProviderIDs, %::s_Ship_hBasePlusPerProviderIDs); # collect shipping class providers and base-plus-per providers
				}
			if ($::s_Ship_bDisplayExtraCartInformation &&																			# the shipping cost is calculated by a shipping provider
				 $::s_Ship_nSSPProviderID != -1)
				{
				$hTrademarkProviderIDs{$::s_Ship_nSSPProviderID} = $::TRUE;														# add the actual shipping provider
				}
			foreach $nSSPProviderID (keys %hTrademarkProviderIDs)
				{
				my %hVariables;
				$hVariables{$::VARPREFIX . 'POWEREDBYLOGO'} = $$::g_pSSPSetupBlob{$nSSPProviderID}{'POWERED_BY_LOGO'};
				$hVariables{$::VARPREFIX . 'TRADEMARKS'} = $$::g_pSSPSetupBlob{$nSSPProviderID}{'TRADEMARKS'};
				my @Response = ACTINIC::TemplateString($sTemplate, \%hVariables); # make the substitutions
				my ($Status, $Message, $sLine) = @Response;
				if ($Status != $::SUCCESS)
					{
					#
					# Display nothing in case of an error
					#
					$$sInsideText = '';
					return ('');
					}
				$$sInsideText .= $sLine;
				}
			return ('');
			}
		}
	#
	# Nothing will be displayed at this phase
	#
	$$sInsideText = '';
	return('');
	}

############################################################
#
# ExtraCartTagHandler - callback for EXTRACARTTEXT tag
#
# Displays the extra cart text in the appropriate form
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Tibor Vajda
#
############################################################

sub ExtraCartTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;

	if( $sTag !~ /^\// )
		{
		if(ref($sInsideText))
			{
			if ($::s_Ship_bDisplayExtraCartInformation &&
				 $::s_Ship_nSSPProviderID != -1 &&
				 $::s_Ship_sOpaqueShipData !~ /BasePlusIncrement/)
				{
				#
				# Diplay the rate disclaimer text + logo for the current shipping provider
				#
				my %hVariables;
				$hVariables{$::VARPREFIX . 'POWEREDBYLOGO'} = $$::g_pSSPSetupBlob{$::s_Ship_nSSPProviderID}{'POWERED_BY_LOGO'};
				$hVariables{$::VARPREFIX . 'RATEDISCLAIMER'} = $$::g_pSSPSetupBlob{$::s_Ship_nSSPProviderID}{'RATE_DISCLAIMER'};
				my @Response = ACTINIC::TemplateString($$sInsideText, \%hVariables); # make the substitutions
				my ($Status, $Message, $sLine) = @Response;
				if ($Status == $::SUCCESS)
					{
					$$sInsideText = $sLine;
					return ('');
					}
				}
			}
		}
	#
	# Nothing will be displayed at this phase
	#
	$$sInsideText = '';
	return('');
	}

############################################################
#
# ExtraCartBasePlusPerTagHandler - callback for EXTRACARTBASEPLUSPERTEXT tag
#
# Displays the extra cart base plus per text in the appropriate form
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Tibor Vajda
#
############################################################

sub ExtraCartBasePlusPerTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;

	if( $sTag !~ /^\// )
		{
		if(ref($sInsideText))
			{
			if ($::s_Ship_bDisplayExtraCartInformation &&
				 $::s_Ship_nSSPProviderID != -1 &&
				 $::s_Ship_sOpaqueShipData =~ /BasePlusIncrement/)
				{
				#
				# Diplay the rate disclaimer text + logo for the current shipping provider
				#
				my %hVariables;
				$hVariables{$::VARPREFIX . 'BASE_PLUS_PER_RATE_DISCLAIMER'} = $$::g_pSSPSetupBlob{$::s_Ship_nSSPProviderID}{'BASE_PLUS_PER_RATE_DISCLAIMER'};
				my @Response = ACTINIC::TemplateString($$sInsideText, \%hVariables); # make the substitutions
				my ($Status, $Message, $sLine) = @Response;
				if ($Status == $::SUCCESS)
					{
					$$sInsideText = $sLine;
					return ('');
					}
				}
			}
		}
	#
	# Nothing will be displayed at this phase
	#
	$$sInsideText = '';
	return('');
	}

############################################################
#
# ExtraShippingTagHandler - callback for EXTRASHIPPINGTEXT tag
#
# Displays the extra shipping bar text in the appropriate form
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Tibor Vajda
#
############################################################

sub ExtraShippingTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;

	if( $sTag !~ /^\// )
		{
		if(ref($sInsideText))
			{
			#
			# Remember that we displayed provider info cause we have to display tradmark info as well
			#
			$ACTINIC::B2B->SetXML('ShippingDisclaimingDisplayed', $::TRUE);
			#
			# Init variables
			#
			my $nSSPProviderID;
			my $sTemplate = $$sInsideText;
			$$sInsideText = '';
			#
			# For each shipping class provider display their disclaimer text + logo
			#
			foreach $nSSPProviderID (keys %::s_Ship_hShippingClassProviderIDs)
				{
				my %hVariables;
				$hVariables{$::VARPREFIX . 'POWEREDBYLOGO'} = $$::g_pSSPSetupBlob{$nSSPProviderID}{'POWERED_BY_LOGO'};
				$hVariables{$::VARPREFIX . 'RATEDISCLAIMER'} = $$::g_pSSPSetupBlob{$nSSPProviderID}{'RATE_DISCLAIMER'};
				my @Response = ACTINIC::TemplateString($sTemplate, \%hVariables); # make the substitutions
				my ($Status, $Message, $sLine) = @Response;
				if ($Status != $::SUCCESS)
					{
					#
					# Display nothing in case of an error
					#
					$$sInsideText = '';
					return ('');
					}
				$$sInsideText .= $sLine;
				}
			return ('');
			}
		}
	#
	# Nothing will be displayed at this phase
	#
	$$sInsideText = '';
	return('');
	}

############################################################
#
# BasePlusPerInfoTagHandler - callback for EXTRABASEPLUSPERTEXT tag
#
# Displays the extra base plus per warning text in the appropriate form
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Tibor Vajda
#
############################################################

sub BasePlusPerInfoTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;

	if( $sTag !~ /^\// )
		{
		if(ref($sInsideText))
			{
			#
			# Remember that we displayed provider info cause we have to display tradmark info as well
			#
			$ACTINIC::B2B->SetXML('ShippingDisclaimingDisplayed', $::TRUE);
			#
			# Init variables
			#
			my $nSSPProviderID;
			my $sTemplate = $$sInsideText;
			$$sInsideText = '';
			#
			# For each base plus per provider display their disclaimer text + logo
			#
			foreach $nSSPProviderID (keys %::s_Ship_hBasePlusPerProviderIDs)
				{
				my %hVariables;
				$hVariables{$::VARPREFIX . 'BASE_PLUS_PER_RATE_DISCLAIMER'} = $$::g_pSSPSetupBlob{$nSSPProviderID}{'BASE_PLUS_PER_RATE_DISCLAIMER'};
				my @Response = ACTINIC::TemplateString($sTemplate, \%hVariables); # make the substitutions
				my ($Status, $Message, $sLine) = @Response;
				if ($Status != $::SUCCESS)
					{
					#
					# Display nothing in case of an error
					#
					$$sInsideText = '';
					return ('');
					}
				$$sInsideText .= $sLine;
				}
			return ('');
			}
		}
	#
	# Nothing will be displayed at this phase
	#
	$$sInsideText = '';
	return('');
	}

############################################################
#
# DefaultTaxZoneMessageTagHandler - callback for DEFAULTTAXZONEMESSAGE tag
#
# Displays the default tax zone message in the appropriate form
#
#  Input	 : $sTag - tag name
#           $sInsideText - reference to text between start and end,
#           $ParameterHash - hash of parameters,
#           $sId - current tag prefix,
#           $sFullTag - full text of current tag;
#
#  Output : replacement for the tag
#
#  Author :	Mike Purnell
#
############################################################

sub DefaultTaxZoneMessageTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;

	if( $sTag !~ /^\// )
		{
		return "";
		}

	if(ref($sInsideText))
		{
		if($ActinicOrder::s_nContext != $ActinicOrder::FROM_CART)
			{
			return('');
			}
		my ($sMessage, $sLocationDescription);
		#
		# Display message in smallest font
		#
		my $sFontOpen = ACTINIC::GetPhrase(-1, 1967);
		my $sFontClose = ACTINIC::GetPhrase(-1, 1970);
		#
		# Customise the message depending upon delivery or invoice
		#
		if($::g_pTaxSetupBlob->{TAX_BY} != $ActinicOrder::eTaxAlways)
			{
			$sLocationDescription = ACTINIC::GetPhrase(-1, 2084);
			if($::g_pTaxSetupBlob->{TAX_BY} == $ActinicOrder::eTaxByInvoice)
				{
				if(defined $::g_LocationInfo{INVOICE_COUNTRY_CODE} &&
					$::g_LocationInfo{INVOICE_COUNTRY_CODE} ne '' &&
					$::g_LocationInfo{INVOICE_COUNTRY_CODE} ne $ActinicOrder::UNDEFINED_REGION &&
					$::g_LocationInfo{INVOICE_COUNTRY_CODE} ne $ActinicOrder::REGION_NOT_SUPPLIED)
					{
					if(defined $::g_LocationInfo{INVOICE_REGION_CODE} &&
						$::g_LocationInfo{INVOICE_REGION_CODE} ne '' &&
						$::g_LocationInfo{INVOICE_REGION_CODE} ne $ActinicOrder::UNDEFINED_REGION)
						{
						$sLocationDescription = ACTINIC::GetCountryName($::g_LocationInfo{INVOICE_REGION_CODE});
						}
					else
						{
						$sLocationDescription = ACTINIC::GetCountryName($::g_LocationInfo{INVOICE_COUNTRY_CODE});
						}
					}
				}
			else
				{
				if(defined $::g_LocationInfo{DELIVERY_COUNTRY_CODE} &&
					$::g_LocationInfo{DELIVERY_COUNTRY_CODE} ne '' &&
					$::g_LocationInfo{DELIVERY_COUNTRY_CODE} ne $ActinicOrder::UNDEFINED_REGION &&
					$::g_LocationInfo{DELIVERY_COUNTRY_CODE} ne $ActinicOrder::REGION_NOT_SUPPLIED)
					{
					if(defined $::g_LocationInfo{DELIVERY_REGION_CODE} &&
						$::g_LocationInfo{DELIVERY_REGION_CODE} ne '' &&
						$::g_LocationInfo{DELIVERY_REGION_CODE} ne $ActinicOrder::UNDEFINED_REGION)
						{
						$sLocationDescription = ACTINIC::GetCountryName($::g_LocationInfo{DELIVERY_REGION_CODE});
						}
					else
						{
						$sLocationDescription = ACTINIC::GetCountryName($::g_LocationInfo{DELIVERY_COUNTRY_CODE});
						}
					}
				}
			#
			# Customise the message depending upon the location info early flag
			#
			my $bRequestInfoEarly = $$::g_pSetupBlob{'TAX_AND_SHIP_EARLY'};
			my $sMessage = $sFontOpen . sprintf(ACTINIC::GetPhrase(-1, 2083), $sLocationDescription);
			$sMessage .= $sFontClose;
			$$sInsideText = $sMessage;
			}
		else
			{
			$$sInsideText = '';
			}
		}

	return('');
	}

############################################################
#
#  ShowForPriceScheduleTagHandler - process the price schedule tags
#
#  Input			:	$sTag - tag name
#						$sInsideText - reference to text between start and end,
#						$ParameterHash - hash of parameters,
#						$sId - current tag prefix,
#						$sFullTag - full text of current tag;
#
#  Output		:	$sInsideText contains replacement for the tag
#
#  Author		:	Tibor Vajda
#
#  Copyright (c) Actinic Software Ltd (2002)
############################################################

sub ShowForPriceScheduleTagHandler
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;
	#
	# There is nothing to do with the End tag
	#
	if ($sTag =~ /^\//)									# If End tag
		{
		return ('');
		}
	#
	# Find the schedule Id of the actual user
	#
	my $nScheduleID = $ActinicOrder::RETAILID;	# current user's schedule id (retail by default)
	my ($Status, $sMessage, $pBuyer, $pAccount);	# helpers
	my $sDigest = $ACTINIC::B2B->Get('UserDigest');	# get the user identifying digest
	if ($sDigest)											# if there is logged in user
		{
		my ($Status, $sMessage, $pBuyer) = ACTINIC::GetBuyer($sDigest, ACTINIC::GetPath()); # look up the buyer
		if ($Status == $::SUCCESS)						# we found the buyer info associated to this user
			{
			($Status, $sMessage, $pAccount) = ACTINIC::GetCustomerAccount($pBuyer->{AccountID}, ACTINIC::GetPath()); # find the account information
			if ($Status == $::SUCCESS)
				{
				$nScheduleID = $pAccount->{PriceSchedule}
				}
			}
		#
		# Handling error
		#
		if ($Status != $::SUCCESS)						# schedule ID couldn't be located for some reason
			{
			ACTINIC::ReportError($sMessage, ACTINIC::GetPath());
			}
		}
	#
	# Determine html text to be printed out
	# - if the xml element contains attribute 'HTML', then use its content
	# - otherwise use the node's text value (which is actually $sInsideText)
	#
	if ($ParameterHash->{'HTML'})
		{
		$$sInsideText = $ParameterHash->{'HTML'};
		}
	#
	# Loop through the specified inclusive schedule ids.
	# If one of them identical to the user's schedule is,
	# - then pass the specified html code back in the $sInsideText reference
	# - otherwise pass back empty string in $sInsideText
	#
	my @aIncludedScheduleIds = split(/,/, $ParameterHash->{'Schedules'}); # included schedule ids are stored in the Schedule attribute of the xml element
	my $nIncludedScheduleId;
	foreach $nIncludedScheduleId (@aIncludedScheduleIds)
		{
		if ($nIncludedScheduleId eq $nScheduleID)
			{
			#
			# User's schedule id is defined,
			# thus we don't clear $sInsideText (this will be inserted into the generated html)
			return '';										# Always return ''
			}
		}
	#
	# If current user's price schedule is not defined,
	# then clear $sInsideText -> nothing will be added to the generated html
	#
	$$sInsideText = '';
	return ('');											# Always return ''
	}

#######################################################
#
# GetTemplateFragment - get a named fragment of the XML template
#
# Params:	0 - XML entity structure
#				1 - fragment name
#
# Returns:	0 - HTML
#
# Author:	Zoltan Magyar, 9:04 PM 3/13/2002
#
#######################################################

sub GetTemplateFragment
	{
	my $pXML = shift;
	my $sFragment = shift;
	#
	# Find the order line HTML
	#
	my $pNode = $pXML->FindNode("XMLTEMPLATE", "NAME", $sFragment);
	if (!$pNode)											# the error is critical here
		{
		# Suppressing Message, but still can be used in debug	
		#? ACTINIC::RecordErrors(ACTINIC::GetPhrase(-1, 2201, $sFragment), ACTINIC::GetPath());
		return("");
		}
	return ($pNode->GetOriginal());
	}

#######################################################
#
# 	AddCookieCheck - Adding cookie checking code
#
#  Input			:	$sTag - tag name
#						$sInsideText - reference to text between start and end,
#						$ParameterHash - hash of parameters,
#						$sId - current tag prefix,
#						$sFullTag - full text of current tag;
#
#  Output		:	$sInsideText contains replacement for the tag
#
#  Author		:	Tibor Vajda
#
#  Copyright (c) Actinic Software Ltd (2002)
############################################################

sub AddCookieCheck
	{
	my $Self = shift;
	my ($sTag,  $sInsideText, $ParameterHash, $sId, $sFullTag) = @_;


	my $sScript = '';										# stores the cookie checking javascript code if needed

	if ($::bCookieCheckRequired)						# cookie checking javascript should be added to the html
		{
		#
		# Determine the url of the warning page generation script
		#
		my $sCgiUrl = ACTINIC::GetScriptUrl($::sShoppingScriptID);	# shopping script is used to display warning
		$sCgiUrl   .= '?ACTION=COOKIEERROR';		# with this parameter
		#
		# Compose the cookie checking javascript
		#
		$sScript = '<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript">';
		$sScript .= 'if (document.cookie.indexOf("ACTINIC_CART=") == -1)';	# if ACTINIC_CART cookie is not available for the document
		$sScript .= 'document.location.replace("' . $sCgiUrl . '");';			# navigate to the warning page
		$sScript .= '</SCRIPT>';
		}

	$$sInsideText = $sScript;
	return ('');
	}

1;

