# Base.pm - The Base Class that the FrameSet and Normal HTML document Objects
# are derived from.
# Created by James Pattie, 04/27/2000.

# Copyright (c) 2000 PC & Web Xperience, Inc. http://www.pcxperience.com/
# All rights reserved.  This program is free software; you can redistribute it
# and/or modify it under the same terms as Perl itself.

# updated 02/24/2001 - Converted to new method and variable naming convention.

package HTMLObject::Base;
use strict;
use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);

require Exporter;

@ISA = qw(Exporter AutoLoader);
@EXPORT = qw(
);
	
$VERSION = '1.09';

# Internationalization support

my %codeToLanguage = (
		"ab" => "Abkhazian",
		"om" => "Afan",
		"aa" => "Afar",
		"af" => "Afrikaans",
		"sq" => "Albanian",
		"am" => "Amharic",
		"ar" => "Arabic",
		"hy" => "Armenian",
		"as" => "Assamese",
		"ay" => "Aymara",
		"az" => "Azerbaijani",
		"ba" => "Bashkir",
		"eu" => "Basque",
		"bn" => "Bengali",
		"dz" => "Bhutani",
		"bh" => "Bihari",
		"bi" => "Bislama",
		"br" => "Breton",
		"bg" => "Bulgarian",
		"my" => "Burmese",
		"be" => "Byelorussian",
		"km" => "Cambodian",
		"ca" => "Catalan",
		"zh" => "Chinese",
		"co" => "Corsican",
		"hr" => "Croatian",
		"cs" => "Czech",
		"da" => "Danish",
		"nl" => "Dutch",
		"en" => "English",
		"eo" => "Esperanto",
		"et" => "Estonian",
		"fo" => "Faroese",
		"fj" => "Fiji",
		"fi" => "Finnish",
		"fr" => "French",
		"fy" => "Frisian",
		"gl" => "Galician",
		"ka" => "Georgian",
		"de" => "German",
		"el" => "Greek",
		"kl" => "Greenlandic",
		"gn" => "Guarani",
		"gu" => "Gujarati",
		"ha" => "Hausa",
		"he" => "Hebrew", # used to be iw
		"hi" => "Hindi",
		"hu" => "Hungarian",
		"is" => "Icelandic",
		"id" => "Indonesian",
		"ia" => "Interlingua",
		"ie" => "Interlingue",
		"iu" => "Inuktitut",
		"ik" => "Inupiak",
		"ga" => "Irish",
		"it" => "Italian",
		"ja" => "Japanese",
		"jv" => "Javanese",
		"kn" => "Kannada",
		"ks" => "Kashmiri",
		"kk" => "Kazakh",
		"rw" => "Kinyarwanda",
		"ky" => "Kirghiz",
		"rn" => "Kurundi",
		"ko" => "Korean",
		"ku" => "Kurdish",
		"lo" => "Laothian",
		"la" => "Latin",
		"lv" => "Latvian",
		"ln" => "Lingala",
		"lt" => "Lithuanian",
		"mk" => "Macedonian",
		"mg" => "Malagasy",
		"ms" => "Malay",
		"ml" => "Malayalam",
		"mt" => "Maltese",
		"mi" => "Maori",
		"mr" => "Marathi",
		"mo" => "Moldavian",
		"mn" => "Mongolian",
		"na" => "Nauru",
		"ne" => "Nepali",
		"no" => "Norwegian",
		"oc" => "Occitan",
		"or" => "Oriya",
		"ps" => "Pashto",
		"fa" => "Persian",
		"pl" => "Polish",
		"pt" => "Portuguese",
		"pa" => "Punjabi",
		"qu" => "Quechua",
		"rm" => "Rhaeto-Romance",
		"ro" => "Romanian",
		"ru" => "Russian",
		"sm" => "Samoan",
		"sg" => "Sangho",
		"sa" => "Sanskrit",
		"gd" => "Scots Gaelic",
		"sr" => "Serbian",
		"sh" => "Serbo-Croatian",
		"st" => "Sesotho",
		"tn" => "Setswana",
		"sn" => "Shona",
		"sd" => "Sindhi",
		"si" => "Singhalese",
		"ss" => "Siswati",
		"sk" => "Slovak",
		"sl" => "Slovenian",
		"so" => "Somali",
		"es" => "Spanish",
		"su" => "Sundanese",
		"sw" => "Swahili",
		"sv" => "Swedish",
		"tl" => "Tagalog",
		"tg" => "Tajik",
		"ta" => "Tamil",
		"tt" => "Tatar",
		"te" => "Telugu",
		"th" => "Thai",
		"bo" => "Tibetan",
		"ti" => "Tigrinya",
		"to" => "Tonga",
		"ts" => "Tsonga",
		"tr" => "Turkish",
		"tk" => "Turkmen",
		"tw" => "Twi",
		"ug" => "Uigur",
		"uk" => "Ukrainian",
		"ur" => "Urdu",
		"uz" => "Uzbek",
		"vi" => "Vietnamese",
		"vo" => "Volapuk",
		"cy" => "Welsh",
		"wo" => "Wolof",
		"xh" => "Xhosa",
		"yi" => "Yiddish",
		"yo" => "Yoruba",
		"za" => "Zhuang",
		"zu" => "Zulu",
	);
	
# This hash takes the 2 letter abreviation and returns the charset encoding to use with it.  It is possible to return an array if there is more than
# one possible encoding that is standard for that language.
my %codeToCharset = (
		"af" => [ "iso-8859-1", "windows-1252" ],
		"sq" => [ "iso-8859-1", "windows-1252" ],
		"ar" => "iso-8859-6",
		"eu" => [ "iso-8859-1", "windows-1252" ],
		"bg" => "iso-8859-5",
		"be" => "iso-8859-5",
		"ca" => [ "iso-8859-1", "windows-1252" ],
		"hr" => "iso-8859-2",
		"cs" => "iso-8859-2",
		"da" => [ "iso-8859-1", "windows-1252" ],
		"nl" => [ "iso-8859-1", "windows-1252" ],
		"en" => [ "iso-8859-1", "windows-1252" ],
		"eo" => "iso-8859-3",
		"et" => "iso-8859-10",
		"fo" => [ "iso-8859-1", "windows-1252" ],
		"fi" => [ "iso-8859-1", "windows-1252" ],
		"fr" => [ "iso-8859-1", "windows-1252" ],
		"gl" => [ "iso-8859-1", "windows-1252" ],
		"de" => [ "iso-8859-1", "windows-1252" ],
		"el" => "iso-8859-7",
		"he" => "iso-8859-8",
		"hu" => "iso-8859-2",
		"is" => [ "iso-8859-1", "windows-1252" ],
		"ga" => [ "iso-8859-1", "windows-1252" ],
		"it" => [ "iso-8859-1", "windows-1252" ],
		"ja" => [ "shift_jis", "iso-2022", "euc-jp" ],
		"lv" => "iso-8859-10",
		"lt" => "iso-8859-10",
		"mk" => "iso-8859-5",
		"mt" => "iso-8859-3",
		"no" => [ "iso-8859-1", "windows-1252" ],
		"pl" => "iso-8859-2",
		"pt" => [ "iso-8859-1", "windows-1252" ],
		"ro" => "iso-8859-2",
		"ru" => [ "koi-8-r", "windows-1252" ],
		"sr" => "iso-8859-5",
		"sk" => "iso-8859-2",
		"sl" => "iso-8859-2",
		"es" => [ "iso-8859-1", "windows-1252" ],
		"sv" => [ "iso-8859-1", "windows-1252" ],
		"tr" => [ "iso-8859-9", "windows-1254" ],
		"uk" => "iso-8859-5",
	);

my @encodeCharacters = ( '%', '\+', ';', ',', '=', '&', ':', '\s', '\"', '#', '\$', '\/', '\?', '<', '>', '@' );
my %encodeCharactersHash = ( '%' => '%25',
                    '\+' => '%2B',
                    ';' => '%3B',
                    ',' => '%2C',
                    '=' => '%3D',
                    '&' => '%26',
                    ':' => '%3A',
                    '\s' => '+',
                    '\"' => '%22',
                    '#' => '%23',
                    '\$' => '%24',
                    '\/' => '%2F',
                    '\?' => '%3F',
                    '<' => '%3C',
                    '>' => '%3E',
                    '@' => '%40',
                  );
                  
my @formCharacters = ( '&', '<', '>', '\'', '\"', '\$' );
my %formCharactersHash = ( '&' => '&amp;',
                             '<' => '&lt;',
                             '>' => '&gt;',
                             '\'' => '&apos;',
                             '\"' => '&quot;',
                             '\$' => '\$\$',
                           );

# new
sub new
{
  my $class = shift;
  my $self = bless {}, $class;

  $self->{error} = 0; # no error initially.
  $self->{errorMessages} = {   1002 => 'Required Parameter missing',
  			1007 => 'Error Code already being used',
  		     };
  $self->setErrorMessage(code => '-1',   message => 'No error occurred');
  $self->setErrorMessage(code => '1000', message => 'Invalid Content-Type Specified');
  $self->setErrorMessage(code => '1001', message => 'Invalid Focus Specified');
  $self->setErrorMessage(code => '1003', message => "Eval'ing setCookie command failed");
  $self->setErrorMessage(code => '1004', message => 'Invalid Date for Cookie Expires');
  $self->setErrorMessage(code => '1005', message => 'Invalid Domain for Cookie');
  $self->setErrorMessage(code => '1006', message => 'Invalid Section used when Content-Type not equal to "text/html"');
  $self->setErrorMessage(code => '1008', message => 'Error Code does not exist');
  $self->setErrorMessage(code => '1009', message => "Invalid Language Code");
  $self->setErrorMessage(code => '1010', message => "Recognized Language Code but No Charset Encoding Known");
  $self->setErrorMessage(code => '1011', message => "Charset Encoding Not Valid");

  $self->{errorCode} = -1;

  $self->{currentSection} = "head";
  $self->{titleString} = "HTMLObject::Base";
  $self->{contentTypeString} = "text/html";
  $self->{language} = "en";
  $self->{charsetEncoding} = "iso-8859-1";
  $self->{headString} = "";
  $self->{bodyString} = "";
  $self->{bodyBgcolor} = "white";
  $self->{bodyFgcolor} = "black";
  $self->{bodyImage} = "";
  $self->{bodyLinkColor} = "blue";
  $self->{bodyVlinkColor} = "blue";
  $self->{bodyAlinkColor} = "blue";
  $self->{cookies} = [];
  $self->{metaTags} = [];
  $self->{encodeCharacters} = \@encodeCharacters;
  $self->{encodeCharactersHash} = \%encodeCharactersHash;
  $self->{formCharacters} = \@formCharacters;
  $self->{formCharactersHash} = \%formCharactersHash;

  $self->{codeToLanguageHash} = \%codeToLanguage;
  $self->{codeToCharsetHash} = \%codeToCharset;

  return $self;
}

# set_error_message
# parameters:  code, message
sub set_error_message
{
  my $self = shift;
  my %args = ( @_, );

  if (!exists $args{'code'})
  {
    $self->doRequiredParameterError('set_error_message', 'code');
  }
  if (!exists $args{'message'})
  {
    $self->doRequiredParameterError('set_error_message', 'message');
  }

  my $code = $args{'code'};
  my $message = $args{'message'};

  if (exists $self->{errorMessages}{$code})
  {
    $self->set_error(code => '1007');
    $self->displayError(title => 'Error:  set_error_message', message => "Error Code = '$code' already exists!");
  }

  # otherwise assign this message and code to the hash.
  $self->{errorMessages}{$code} = $message;
}

# setErrorMessage
# parameters:  code, message
sub setErrorMessage
{
  my $self = shift;
  my %args = ( @_, );

  if (!exists $args{'code'})
  {
    $self->doRequiredParameterError('setErrorMessage', 'code');
  }
  if (!exists $args{'message'})
  {
    $self->doRequiredParameterError('setErrorMessage', 'message');
  }

  my $code = $args{'code'};
  my $message = $args{'message'};

  if (exists $self->{errorMessages}{$code})
  {
    $self->setError(code => '1007');
    $self->displayError(title => 'Error:  setErrorMessage', message => "Error Code = '$code' already exists!");
  }

  # otherwise assign this message and code to the hash.
  $self->{errorMessages}{$code} = $message;
}

# clear_error_message
# parameters: code
sub clear_error_message
{
  my $self = shift;
  my %args = ( @_, );

  if (!exists $args{'code'})
  {
    $self->doRequiredParameterError('set_error_message', 'code');
  }

  my $code = $args{'code'};

  if (!exists $self->{errorMessages}{$code})
  {
    $self->set_error(code => '1008');
    $self->displayError(title => 'Error:  set_error_message', message => "Error Code = '$code' does not exist in the errorMessages hash!");
  }

  # otherwise remove this message and code from the hash.
  delete($self->{errorMessages}{$code});
}

# clearErrorMessage
# parameters: code
sub clearErrorMessage
{
  my $self = shift;
  my %args = ( @_, );

  if (!exists $args{'code'})
  {
    $self->doRequiredParameterError('setErrorMessage', 'code');
  }

  my $code = $args{'code'};

  if (!exists $self->{errorMessages}{$code})
  {
    $self->set_error(code => '1008');
    $self->displayError(title => 'Error:  setErrorMessage', message => "Error Code = '$code' does not exist in the errorMessages hash!");
  }

  # otherwise remove this message and code from the hash.
  delete($self->{errorMessages}{$code});
}

# set_error - Signals that an error occurred and what the code is.
# parameters: code
sub set_error
{
  my $self = shift;
  my %args = ( @_, );

  if (!exists $args{'code'})
  {
    $self->doRequiredParameterError('set_error', 'code');
  }

  my $code = $args{'code'};

  $self->{error} = 1;
  $self->{errorCode} = $code;
}

# setError - Signals that an error occurred and what the code is.
# parameters: code
sub setError
{
  my $self = shift;
  my %args = ( @_, );

  if (!exists $args{'code'})
  {
    $self->doRequiredParameterError('setError', 'code');
  }

  my $code = $args{'code'};

  $self->{error} = 1;
  $self->{errorCode} = $code;
}

# This method is going away in the 2.x series.
# didErrorOccurr - Returns the flag value to indicate if an error occurred.
sub didErrorOccurr
{
  my $self = shift;

  return $self->{error};
}

# didErrorOccur - Returns the flag value to indicate if an error occurred.
sub didErrorOccur
{
  my $self = shift;
  
  return $self->{error};
}

# getErrorMessage - Returns the Error Message created by the class.
sub getErrorMessage
{
  my $self = shift;

  return $self->{errorMessages}{$self->{errorCode}};
}

# getErrorCode - Returns the Error Code of the error that happened.
sub getErrorCode
{
  my $self = shift;

  return $self->{errorCode};
}

# reset
sub reset
{
  my $self = shift;

  $self->{error} = 0; # no error initially.
  %{$self->{errorMessages}} = (   1002 => 'Required Parameter missing',
  			1007 => 'Error Code already being used',
  		     );
  $self->setErrorMessage(code => '-1',   message => 'No error occurred');
  $self->setErrorMessage(code => '1000', message => 'Invalid Content-Type Specified');
  $self->setErrorMessage(code => '1001', message => 'Invalid Focus Specified');
  $self->setErrorMessage(code => '1003', message => "Eval'ing setCookie command failed");
  $self->setErrorMessage(code => '1004', message => 'Invalid Date for Cookie Expires');
  $self->setErrorMessage(code => '1005', message => 'Invalid Domain for Cookie');
  $self->setErrorMessage(code => '1006', message => 'Invalid Section used when Content-Type not equal to "text/html"');
  $self->setErrorMessage(code => '1008', message => 'Error Code does not exist');
  $self->setErrorMessage(code => '1009', message => "Invalid Language Code");
  $self->setErrorMessage(code => '1010', message => "Recognized Language Code but No Charset Encoding Known");
  $self->setErrorMessage(code => '1011', message => "Charset Encoding Not Valid");

  $self->{errorCode} = -1;

  $self->{currentSection} = "head";
  $self->{titleString} = "HTMLObject::Base";
  $self->{contentTypeString} = "text/html";
  $self->{language} = "en";
  $self->{charsetEncoding} = "iso-8859-1";
  $self->{headString} = "";
  $self->{bodyString} = "";
  $self->{bodyBgcolor} = "white";
  $self->{bodyFgcolor} = "black";
  $self->{bodyImage} = "";
  $self->{bodyLinkColor} = "blue";
  $self->{bodyVlinkColor} = "blue";
  $self->{bodyAlinkColor} = "blue";
  $self->{cookies} = [];
  $self->{metaTags} = [];
  $self->{encodeCharacters} = \@encodeCharacters;
  $self->{encodeCharactersHash} = \%encodeCharactersHash;
  $self->{formCharacters} = \@formCharacters;
  $self->{formCharactersHash} = \%formCharactersHash;

  $self->{codeToLanguageHash} = \%codeToLanguage;
  $self->{codeToCharsetHash} = \%codeToCharset;
}

# displayError - Displays the specified error document and then exits.
sub displayError
{
  my $self = shift;
  my %args = (  title => 'Error: HTMLObject::Base',
  		message => 'An Error Occurred!',
  		@_	# arguments passed in go here.
  	     );
  	
  my $doc = HTMLObject::Base->new();

  $doc->setTitle($args{'title'});
  $doc->setFocus("body");
  $doc->print("<h1>Error: &nbsp;<b>" . $self->getErrorCode() . "</b> Occurred!</h1>\n");
  $doc->print("Message: &nbsp;" . $self->getErrorMessage() . "\n<br>\n");
  $doc->print("<br>\n<br>\n$args{'message'}\n<br>\n");

  $doc->display();

  exit 0;
}

# displayCookies
sub displayCookies
{
  my $self = shift;

  my $output = "";
  if (scalar @{$self->{cookies}} > 0)
  {
    foreach my $cookie (@{$self->{cookies}})
    {
      $output .= "Set-Cookie: $cookie\n";
    }
  }

  return $output;
}

# displayMetaTags
sub displayMetaTags
{
  my $self = shift;

  my $output .= "";
  if (scalar @{$self->{metaTags}} > 0)
  {
    foreach my $metaTag (@{$self->{metaTags}})
    {
      $output .= "    $metaTag\n";
    }
  }

  return $output;
}

# display
sub display
{
  my $self = shift;

  my $output = "";

  #make sure that all output is properly indented, this way the user doesn't have to do any indentation to fit our output indentation.
  my ($tempHeadString, $tempBodyString);
  ($tempHeadString = $self->{headString}) =~ s/^(.*)$/    $1/mg;  # currently 4 spaces.
  ($tempBodyString = $self->{bodyString}) =~ s/^(.*)$/    $1/mg;

  if ($self->{contentTypeString} =~ /text\/html/i)
  {
    # display Cookies if needed  (they must come before the Content-Type header)
    my $tempStr = $self->displayCookies();
    $output .= $tempStr if (length $tempStr > 0);

    $output .= "Content-Type: $self->{contentTypeString}; charset=$self->{charsetEncoding}\n\n";  # Display the Content-Type block.

    # output the Document Type header.
    $output .= "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">\n";
    $output .= "<html lang=\"$self->{language}\">\n";
    $output .= "  <head>\n";

    # display Meta Tags if needed.
    $tempStr = $self->displayMetaTags();
    $output .= $tempStr if (length $tempStr > 0);

    $output .= "    <title>$self->{titleString}</title>\n";
    $output .= "    $tempHeadString" if (length $self->{headString} > 0);
    $output .= "  </head>\n\n";
    $output .= "  <body bgcolor=\"$self->{bodyBgcolor}\" text=\"$self->{bodyFgcolor}\" link=\"$self->{bodyLinkColor}\" vlink=\"$self->{bodyVlinkColor}\" alink=\"$self->{bodyAlinkColor}\"";
    $output .= " background=\"$self->{bodyImage}\"" if (length $self->{bodyImage} > 0);
    $output .= ">\n";
    $output .= "$tempBodyString" if (length $self->{bodyString} > 0);
    $output .= "  </body>\n";
    $output .= "</html>\n";
  }
  else
  {
    $output .= "Content-Type: $self->{contentTypeString}\n";
    $output .= "\n";  # Close the Content-Type block.
    $output .= $self->{bodyString};
  }

  print $output;
}

# doRequiredParameterError - Displays the customized title and message and then exits the program.
sub doRequiredParameterError
{
  my $self = shift;
  my $titleName = shift;
  my $messageName = shift;

  $self->setError(code => '1002');
  $self->displayError(title => "Error:  $titleName", message => "<b>$messageName</b> is required!");
}

# set_content_type
sub set_content_type
{
  my $self = shift;

  if (!defined $_[0])
  {
    $self->doRequiredParameterError('set_content_type', 'Content-Type');
  }

  my $temp = shift;

  if (!($temp =~ /text\/html/i || $temp =~ /image\/gif/i || $temp =~ /text\/plain/i || $temp =~ /image\/jpeg/i))
  {
    $self->setError(code => '1000');
    $self->displayError(title => 'Error:  set_content_type', message => "Content-Type = \"$temp\" is invalid!");
  }

  if ($temp !~ /text\/html/i)
  {
    $self->{currentSection} = "body";	# make sure the only valid section is the body.
  }

  $self->{contentTypeString} = $temp;
}

# setContentType
sub setContentType
{
  my $self = shift;

  if (!defined $_[0])
  {
    $self->doRequiredParameterError('setContentType', 'Content-Type');
  }

  my $temp = shift;

  if (!($temp =~ /text\/html/i || $temp =~ /image\/gif/i || $temp =~ /text\/plain/i || $temp =~ /image\/jpeg/i))
  {
    $self->setError(code => '1000');
    $self->displayError(title => 'Error:  setContentType', message => "Content-Type = \"$temp\" is invalid!");
  }

  if ($temp !~ /text\/html/i)
  {
    $self->{currentSection} = "body";	# make sure the only valid section is the body.
  }

  $self->{contentTypeString} = $temp;
}

# get_content_type - Returns the charset encoding if valid.
sub get_content_type
{
  my $self = shift;
  my $content_type = $self->{contentTypeString};
  
  if ($content_type =~ /text\/html/i)
  {
    $content_type .= "; charset=" . $self->{charsetEncoding};
  }

  return $content_type;
}

# getContentType - Returns the charset encoding if valid.
sub getContentType
{
  my $self = shift;
  my $contentType = $self->{contentTypeString};
  
  if ($contentType =~ /text\/html/i)
  {
    $contentType .= "; charset=" . $self->{charsetEncoding};
  }

  return $contentType;
}

# set_language_encoding - Sets the language and charset encoding to work with.
sub set_language_encoding
{
  my $self = shift;
  my %args = ( language => 'en', encoding => 'iso-8859-1', @_, );
  my $language = $args{'language'};
  my $encoding = $args{'encoding'};
  
  # validate that we have valid language code and encoding values and then that they are valid together.
  if (!exists $codeToLanguage{$language})
  {
    $self->setError(code => '1009');
    $self->displayError(title => "Error: set_language_encoding", message => "Language Code = '$language' is not recognized!");
  }
  if (!exists $codeToCharset{$language})
  {
    $self->setError(code => '1010');
    $self->displayError(title => "Error: set_language_encoding", message => "Language Code = '$language' does not have a charset encoding!");
  }
  else
  {
    my $char_encoding = $codeToCharset{$language};
    if (ref($char_encoding) eq "ARRAY")
    {
      my @encodings = @{$codeToCharset{$language}};
      my $found = 0;
      for (my $i=0; $i < scalar @encodings && !$found; $i++)
      {
        if ($encodings[$i] eq $encoding)
        {
          $found = 1;
        }
      }
      if (!$found)
      {
        $self->setError(code => '1011');
        $self->displayError(title => "Error: set_language_encoding", message => "Charset Encoding = '$encoding' is not valid!");     
      }
    }
    else
    {
      if ($char_encoding ne $encoding)
      {
        $self->setError(code => '1011');
        $self->displayError(title => "Error: set_language_encoding", message => "Charset Encoding = '$encoding' is not valid!");     
      }
    }
  }
  
  $self->{language} = $language;
  $self->{charsetEncoding} = $encoding;
}

# setLanguageEncoding - Sets the language and charset encoding to work with.
sub setLanguageEncoding
{
  my $self = shift;
  my %args = ( language => 'en', encoding => 'iso-8859-1', @_, );
  my $language = $args{'language'};
  my $encoding = $args{'encoding'};
  
  # validate that we have valid language code and encoding values and then that they are valid together.
  if (!exists $codeToLanguage{$language})
  {
    $self->setError(code => '1009');
    $self->displayError(title => "Error: setLanguageEncoding", message => "Language Code = '$language' is not recognized!");
  }
  if (!exists $codeToCharset{$language})
  {
    $self->setError(code => '1010');
    $self->displayError(title => "Error: setLanguageEncoding", message => "Language Code = '$language' does not have a charset encoding!");
  }
  else
  {
    my $charEncoding = $codeToCharset{$language};
    if (ref($charEncoding) eq "ARRAY")
    {
      my @encodings = @{$codeToCharset{$language}};
      my $found = 0;
      for (my $i=0; $i < scalar @encodings && !$found; $i++)
      {
        if ($encodings[$i] eq $encoding)
        {
          $found = 1;
        }
      }
      if (!$found)
      {
        $self->setError(code => '1011');
        $self->displayError(title => "Error: setLanguageEncoding", message => "Charset Encoding = '$encoding' is not valid!");     
      }
    }
    else
    {
      if ($charEncoding ne $encoding)
      {
        $self->setError(code => '1011');
        $self->displayError(title => "Error: setLanguageEncoding", message => "Charset Encoding = '$encoding' is not valid!");     
      }
    }
  }
  
  $self->{language} = $language;
  $self->{charsetEncoding} = $encoding;
}

# get_language
sub get_language
{
  my $self = shift;
  
  return $self->{language};
}

# getLanguage
sub getLanguage
{
  my $self = shift;
  
  return $self->{language};
}

# get_language_name
sub get_language_name
{
  my $self = shift;
  
  return $codeToLanguage{$self->{language}};
}

# getLanguageName
sub getLanguageName
{
  my $self = shift;
  
  return $codeToLanguage{$self->{language}};
}

# lookup_language_name
sub lookup_language_name
{
  my $self = shift;
  my %args = (code => 'en', @_, );  # default to english.
  my $code = $args{'code'};
  
  my $name = $codeToLanguage{$code};
  
  return $name;
}

# lookupLanguageName
sub lookupLanguageName
{
  my $self = shift;
  my %args = (code => 'en', @_, );  # default to english.
  my $code = $args{'code'};
  
  my $name = $codeToLanguage{$code};
  
  return $name;
}

# get_char_encoding
sub get_char_encoding
{
  my $self = shift;
  
  return $self->{charsetEncoding};
}

# getCharEncoding
sub getCharEncoding
{
  my $self = shift;
  
  return $self->{charsetEncoding};
}

# lookup_char_encoding
sub lookup_char_encoding
{
  my $self = shift;
  my %args = (code => 'en', @_, );  # default to english.
  my $code = $args{'code'};
  
  return $codeToCharset{$code};  # this could be an array ref.
}

# lookupCharEncoding
sub lookupCharEncoding
{
  my $self = shift;
  my %args = (code => 'en', @_, );  # default to english.
  my $code = $args{'code'};
  
  return $codeToCharset{$code};  # this could be an array ref.
}

# set_title
sub set_title
{
  my $self = shift;

  if (!defined $_[0])
  {
    $self->doRequiredParameterError('set_title', 'Title');
  }

  $self->{titleString} = shift;
}

# setTitle
sub setTitle
{
  my $self = shift;

  if (!defined $_[0])
  {
    $self->doRequiredParameterError('setTitle', 'Title');
  }

  $self->{titleString} = shift;
}

# get_title
sub get_title
{
  my $self = shift;

  return $self->{titleString};
}

# getTitle
sub getTitle
{
  my $self = shift;

  return $self->{titleString};
}

# get_head_string
sub get_head_string
{
  my $self = shift;

  return $self->{headString};
}

# getHeadString
sub getHeadString
{
  my $self = shift;

  return $self->{headString};
}

# get_body_string
sub get_body_string
{
  my $self = shift;

  return $self->{bodyString};
}

# getBodyString
sub getBodyString
{
  my $self = shift;

  return $self->{bodyString};
}

# encode_string
# parameters are: string
# returns: url encoded string
sub encode_string
{
  my $self = shift;
  my %args = ( @_,  # arguments go here.
  	     );

  my $string = $args{'string'};

  if (!exists $args{'string'})
  {
    $self->doRequiredParameterError('encode_string', 'string');
  }

  foreach my $char (@{$self->{encodeCharacters}})
  {
    my $value = $self->{encodeCharactersHash}->{$char};
    $string  =~ s/$char/$value/g;
  }

  return $string;
}

# encodeString
# parameters are: string
# returns: url encoded string
sub encodeString
{
  my $self = shift;
  my %args = ( @_,  # arguments go here.
  	     );

  my $string = $args{'string'};

  if (!exists $args{'string'})
  {
    $self->doRequiredParameterError('encodeString', 'string');
  }

  foreach my $char (@{$self->{encodeCharacters}})
  {
    my $value = $self->{encodeCharactersHash}->{$char};
    $string  =~ s/$char/$value/g;
  }

  return $string;
}

# form_encode_string
# takes: string
# returns: form encoded string
sub form_encode_string
{
  my $self = shift;
  my %args = ( @_ );
  my $string = $args{string};
  
  if (!exists $args{string})
  {
    $self->doRequiredParameterError('form_encode_string', 'string');
  }
  
  foreach my $char (@{$self->{formCharacters}})
  {
    my $value = $self->{formCharactersHash}->{$char};
    $string =~ s/$char/$value/g;
  }
  
  return $string;
}

# formEncodeString
# takes: string
# returns: form encoded string
sub formEncodeString
{
  my $self = shift;
  my %args = ( @_ );
  my $string = $args{string};
  
  if (!exists $args{string})
  {
    $self->doRequiredParameterError('formEncodeString', 'string');
  }
  
  foreach my $char (@{$self->{formCharacters}})
  {
    my $value = $self->{formCharactersHash}->{$char};
    $string =~ s/$char/$value/g;
  }
  
  return $string;
}

# set_cookie
# parameters are: name, value, expires, path, domain, secure
sub set_cookie
{
  my $self = shift;
  my %args = ( name => '',
  	       value => '',
  	       @_,  # arguments go here.
  	     );

  my $name = $args{'name'};
  my $value = $args{'value'};

  if (length $name == 0)
  {
    $self->doRequiredParameterError('set_cookie', 'name');
  }

  $name = $self->encodeString( string => "$name" );
  $value = $self->encodeString( string => "$value" );
  	
  my $cookie = "$name=$value;";

  if (exists $args{'expires'})
  {
    my $date = $args{'expires'};

    if ($date =~ /^\w{3}\,\s\d{2}\-\w{3}-\d{4}\s\d{2}\:\d{2}\:\d{2}\sGMT$/)
    {
      $cookie .= " expires=$args{'expires'};";
    }
    else
    {
      $self->setError(code => '1004');
      $self->displayError(title => 'set_cookie', message => "date = '$date' is invalid!");
    }
  }
  if (exists $args{'path'})
  {
    $cookie .= " path=$args{'path'};";
  }
  if (exists $args{'domain'})
  {
    my $domain = $args{'domain'};
    if ($domain =~ /(.com|.edu|.net|.org|.gov|.mil|.int)$/i && $domain =~ /\..+\.\w{3}$/)
    {
      $cookie .= " domain=$args{'domain'};";
    }
    elsif ($domain !~ /(.com|.edu|.net|.org|.gov|.mil|.int)$/i && $domain =~ /\..+\..+\..+/)
    {
      $cookie .= " domain=$args{'domain'};";
    }
    else
    {
      $self->setError(code => '1005');
      $self->displayError(title => 'set_cookie', message => "domain = '$domain' is invalid!");
    }
  }
  if (exists $args{'secure'})
  {
    $cookie .= " secure";
  }

  my $num = scalar @{$self->{cookies}};
  $self->{cookies}[$num] = $cookie;  # store the cookie string in the cookies array.
}

# setCookie
# parameters are: name, value, expires, path, domain, secure
sub setCookie
{
  my $self = shift;
  my %args = ( name => '',
  	       value => '',
  	       @_,  # arguments go here.
  	     );

  my $name = $args{'name'};
  my $value = $args{'value'};

  if (length $name == 0)
  {
    $self->doRequiredParameterError('setCookie', 'name');
  }

  $name = $self->encodeString( string => "$name" );
  $value = $self->encodeString( string => "$value" );
  	
  my $cookie = "$name=$value;";

  if (exists $args{'expires'})
  {
    my $date = $args{'expires'};

    if ($date =~ /^\w{3}\,\s\d{2}\-\w{3}-\d{4}\s\d{2}\:\d{2}\:\d{2}\sGMT$/)
    {
      $cookie .= " expires=$args{'expires'};";
    }
    else
    {
      $self->setError(code => '1004');
      $self->displayError(title => 'setCookie', message => "date = '$date' is invalid!");
    }
  }
  if (exists $args{'path'})
  {
    $cookie .= " path=$args{'path'};";
  }
  if (exists $args{'domain'})
  {
    my $domain = $args{'domain'};
    if ($domain =~ /(.com|.edu|.net|.org|.gov|.mil|.int)$/i && $domain =~ /\..+\.\w{3}$/)
    {
      $cookie .= " domain=$args{'domain'};";
    }
    elsif ($domain !~ /(.com|.edu|.net|.org|.gov|.mil|.int)$/i && $domain =~ /\..+\..+\..+/)
    {
      $cookie .= " domain=$args{'domain'};";
    }
    else
    {
      $self->setError(code => '1005');
      $self->displayError(title => 'setCookie', message => "domain = '$domain' is invalid!");
    }
  }
  if (exists $args{'secure'})
  {
    $cookie .= " secure";
  }

  my $num = scalar @{$self->{cookies}};
  $self->{cookies}[$num] = $cookie;  # store the cookie string in the cookies array.
}

# set_compressed_cookie
# parameters: name, @cookies, expires, path, domain, secure
sub set_compressed_cookie
{
  my $self = shift;
  my %args = ( name => '',
  	       @_,  # arguments go here.
  	     );

  if (!exists $args{'cookies'})
  {
    $self->doRequiredParameterError('set_compressed_cookie', 'cookies');
  }
  	
  my $name = $args{'name'};
  my @local_cookies = @{$args{'cookies'}};
  my $cookie_value = "";  # The value for this compressed cookie to be set.

  if (length $name == 0)
  {
    $self->doRequiredParameterError('set_compressed_cookie', 'name');
  }
  if (scalar @local_cookies == 0)
  {
    $self->doRequiredParameterError('set_compressed_cookie', 'cookies');
  }

  for (my $i=0; $i < scalar @local_cookies; $i++)
  {
    my $sub_cookie = $local_cookies[$i][0];
    my $sub_value  = $local_cookies[$i][1];

    $sub_cookie = $self->encodeString( string => "$sub_cookie" );
    $sub_value = $self->encodeString( string => "$sub_value" );

    if (length $cookie_value > 0)
    {
      $cookie_value .= "&" . $sub_cookie . "::" . $sub_value;
    }
    else
    {
      $cookie_value = $sub_cookie . "::" . $sub_value;
    }
  }

  my $arguments = "";
  if (exists $args{'path'})
  {
    $arguments .= ", path => '$args{'path'}'";
  }
  if (exists $args{'domain'})
  {
    $arguments .= ", domain => '$args{'domain'}'";
  }
  if (exists $args{'expires'})
  {
    $arguments .= ", expires => '$args{'expires'}'";
  }
  if (exists $args{'secure'})
  {
    $arguments .= ", secure => ''";
  }

  # now set the cookie by calling setCookie.
  eval("\$self->setCookie(name => \"$name\", value => \"$cookie_value\"$arguments);");
  if ($@)
  {
    $self->setError(code => '1003');
    $self->displayError(title => 'set_compressed_cookie', message => "\$@ = $@");
  }
}

# setCompressedCookie
# parameters: name, @cookies, expires, path, domain, secure
sub setCompressedCookie
{
  my $self = shift;
  my %args = ( name => '',
  	       @_,  # arguments go here.
  	     );

  if (!exists $args{'cookies'})
  {
    $self->doRequiredParameterError('setCompressedCookie', 'cookies');
  }
  	
  my $name = $args{'name'};
  my @localCookies = @{$args{'cookies'}};
  my $cookieValue = "";  # The value for this compressed cookie to be set.

  if (length $name == 0)
  {
    $self->doRequiredParameterError('setCompressedCookie', 'name');
  }
  if (scalar @localCookies == 0)
  {
    $self->doRequiredParameterError('setCompressedCookie', 'cookies');
  }

  for (my $i=0; $i < scalar @localCookies; $i++)
  {
    my $subCookie = $localCookies[$i][0];
    my $subValue  = $localCookies[$i][1];

    $subCookie = $self->encodeString( string => "$subCookie" );
    $subValue = $self->encodeString( string => "$subValue" );

    if (length $cookieValue > 0)
    {
      $cookieValue .= "&" . $subCookie . "::" . $subValue;
    }
    else
    {
      $cookieValue = $subCookie . "::" . $subValue;
    }
  }

  my $arguments = "";
  if (exists $args{'path'})
  {
    $arguments .= ", path => '$args{'path'}'";
  }
  if (exists $args{'domain'})
  {
    $arguments .= ", domain => '$args{'domain'}'";
  }
  if (exists $args{'expires'})
  {
    $arguments .= ", expires => '$args{'expires'}'";
  }
  if (exists $args{'secure'})
  {
    $arguments .= ", secure => ''";
  }

  # now set the cookie by calling setCookie.
  eval("\$self->setCookie(name => \"$name\", value => \"$cookieValue\"$arguments);");
  if ($@)
  {
    $self->setError(code => '1003');
    $self->displayError(title => 'setCompressedCookie', message => "\$@ = $@");
  }
}

# set_meta_tag
# parameters:  http-equiv, content
sub set_meta_tag
{
  my $self = shift;
  my %args = ( @_,  # arguments go here.
  	     );
  	
  if (!exists $args{'http-equiv'})
  {
    $self->doRequiredParameterError('set_meta_tag', 'http-equiv');
  }
  if (!exists $args{'content'})
  {
    $self->doRequiredParameterError('set_meta_tag', 'content');
  }

  my $http_equiv = $args{'http-equiv'};
  my $content = $args{'content'};

  if (length $http_equiv == 0)
  {
    $self->doRequiredParameterError('set_meta_tag', 'http-equiv');
  }
  if (length $content == 0)
  {
    $self->doRequiredParameterError('set_meta_tag', 'content');
  }

  my $meta_tag = "<meta http-equiv=\"$http_equiv\" content=\"$content\">";
  my $num = scalar @{$self->{metaTags}};
  $self->{metaTags}[$num] = $meta_tag;  # store the meta tag info for later display.
}

# setMetaTag
# parameters:  http-equiv, content
sub setMetaTag
{
  my $self = shift;
  my %args = ( @_,  # arguments go here.
  	     );
  	
  if (!exists $args{'http-equiv'})
  {
    $self->doRequiredParameterError('setMetaTag', 'http-equiv');
  }
  if (!exists $args{'content'})
  {
    $self->doRequiredParameterError('setMetaTag', 'content');
  }

  my $httpEquiv = $args{'http-equiv'};
  my $content = $args{'content'};

  if (length $httpEquiv == 0)
  {
    $self->doRequiredParameterError('setMetaTag', 'http-equiv');
  }
  if (length $content == 0)
  {
    $self->doRequiredParameterError('setMetaTag', 'content');
  }

  my $metaTag = "<meta http-equiv=\"$httpEquiv\" content=\"$content\">";
  my $num = scalar @{$self->{metaTags}};
  $self->{metaTags}[$num] = $metaTag;  # store the meta tag info for later display.
}

# set_focus
sub set_focus
{
  my $self = shift;

  if (!defined $_[0])
  {
    $self->doRequiredParameterError('set_focus', 'Section Name');
  }

  my $focus = shift;

  if ($focus ne "head" && $focus ne "body")
  {
    $self->setError(code => '1001');
    $self->displayError(title => 'Error:  set_focus', message => 'Focus = "$focus" is invalid!');
  }

  if ($self->{contentTypeString} !~ /text\/html/i && $focus ne "body")
  {
    $self->setError(code => '1006');
    $self->displayError(title => 'Error:  set_focus', message => 'Focus = "$focus" is invalid when Content-Type = "$self->{contentTypeString}" is used!');
  }

  $self->{currentSection} = $focus;
}

# setFocus
sub setFocus
{
  my $self = shift;

  if (!defined $_[0])
  {
    $self->doRequiredParameterError('setFocus', 'Section Name');
  }

  my $focus = shift;

  if ($focus ne "head" && $focus ne "body")
  {
    $self->setError(code => '1001');
    $self->displayError(title => 'Error:  setFocus', message => 'Focus = "$focus" is invalid!');
  }

  if ($self->{contentTypeString} !~ /text\/html/i && $focus ne "body")
  {
    $self->setError(code => '1006');
    $self->displayError(title => 'Error:  setFocus', message => 'Focus = "$focus" is invalid when Content-Type = "$self->{contentTypeString}" is used!');
  }

  $self->{currentSection} = $focus;
}

# get_focus
sub get_focus
{
  my $self = shift;

  return $self->{currentSection};
}

# getFocus
sub getFocus
{
  my $self = shift;

  return $self->{currentSection};
}

# print
sub print
{
  my $self = shift;

  if (!defined $_[0])
  {
    $self->doRequiredParameterError('print', 'Text');
  }

  my $text = shift;

  if ($self->{currentSection} eq "head")
  {
    $self->{headString} .= $text;
  }
  elsif ($self->{currentSection} eq "body")
  {
    $self->{bodyString} .= $text;
  }
}

# read
sub read
{
  my $self = shift;
  my $text = "";

  if ($self->{currentSection} eq "head")
  {
    $text = $self->{headString};
  }
  elsif ($self->{currentSection} eq "body")
  {
    $text = $self->{bodyString};
  }

  return $text;
}

# delete
sub delete
{
  my $self = shift;

  if ($self->{currentSection} eq "head")
  {
    $self->{headString} = "";
  }
  elsif ($self->{currentSection} eq "body")
  {
    $self->{bodyString} = "";
  }
}

# set_body_bgcolor
sub set_body_bgcolor
{
  my $self = shift;

  if (!defined $_[0])
  {
    $self->doRequiredParameterError('set_body_bgcolor', 'Background Color');
  }

  $self->{bodyBgcolor} = shift;
}

# setBodyBgcolor
sub setBodyBgcolor
{
  my $self = shift;

  if (!defined $_[0])
  {
    $self->doRequiredParameterError('setBodyBgcolor', 'Background Color');
  }

  $self->{bodyBgcolor} = shift;
}

# get_body_bgcolor
sub get_body_bgcolor
{
  my $self = shift;

  return $self->{bodyBgcolor};
}

# getBodyBgcolor
sub getBodyBgcolor
{
  my $self = shift;

  return $self->{bodyBgcolor};
}

# set_body_fgcolor
sub set_body_fgcolor
{
  my $self = shift;

  if (!defined $_[0])
  {
    $self->doRequiredParameterError('set_body_fgcolor', 'Text Color');
  }

  $self->{bodyFgcolor} = shift;
}

# setBodyFgcolor
sub setBodyFgcolor
{
  my $self = shift;

  if (!defined $_[0])
  {
    $self->doRequiredParameterError('setBodyFgcolor', 'Text Color');
  }

  $self->{bodyFgcolor} = shift;
}

# get_body_fgcolor
sub get_body_fgcolor
{
  my $self = shift;

  return $self->{bodyFgcolor};
}

# getBodyFgcolor
sub getBodyFgcolor
{
  my $self = shift;

  return $self->{bodyFgcolor};
}

# set_body_link_color
sub set_body_link_color
{
  my $self = shift;

  if (!defined $_[0])
  {
    $self->doRequiredParameterError('set_body_link_color', 'Link Color');
  }

  $self->{bodyLinkColor} = shift;
}

# setBodyLinkColor
sub setBodyLinkColor
{
  my $self = shift;

  if (!defined $_[0])
  {
    $self->doRequiredParameterError('setBodyLinkColor', 'Link Color');
  }

  $self->{bodyLinkColor} = shift;
}

# get_body_link_color
sub get_body_link_color
{
  my $self = shift;

  return $self->{bodyLinkColor};
}

# getBodyLinkColor
sub getBodyLinkColor
{
  my $self = shift;

  return $self->{bodyLinkColor};
}

# set_body_vlink_color
sub set_body_vlink_color
{
  my $self = shift;

  if (!defined $_[0])
  {
    $self->doRequiredParameterError('set_body_vlink_color', 'VLink Color');
  }

  $self->{bodyVlinkColor} = shift;
}

# setBodyVlinkColor
sub setBodyVlinkColor
{
  my $self = shift;

  if (!defined $_[0])
  {
    $self->doRequiredParameterError('setBodyVlinkColor', 'VLink Color');
  }

  $self->{bodyVlinkColor} = shift;
}

# get_body_vlink_color
sub get_body_vlink_color
{
  my $self = shift;

  return $self->{bodyVlinkColor};
}

# getBodyVlinkColor
sub getBodyVlinkColor
{
  my $self = shift;

  return $self->{bodyVlinkColor};
}

# set_body_alink_color
sub set_body_alink_color
{
  my $self = shift;

  if (!defined $_[0])
  {
    $self->doRequiredParameterError('set_body_alink_color', 'ALink Color');
  }

  $self->{bodyAlinkColor} = shift;
}

# setBodyAlinkColor
sub setBodyAlinkColor
{
  my $self = shift;

  if (!defined $_[0])
  {
    $self->doRequiredParameterError('setBodyAlinkColor', 'ALink Color');
  }

  $self->{bodyAlinkColor} = shift;
}

# get_body_alink_color
sub get_body_alink_color
{
  my $self = shift;

  return $self->{bodyAlinkColor};
}

# getBodyAlinkColor
sub getBodyAlinkColor
{
  my $self = shift;

  return $self->{bodyAlinkColor};
}

# set_body_image
sub set_body_image
{
  my $self = shift;

  if (!defined $_[0])
  {
    $self->doRequiredParameterError('set_body_image', 'Image');
  }

  $self->{bodyImage} = shift;
}

# setBodyImage
sub setBodyImage
{
  my $self = shift;

  if (!defined $_[0])
  {
    $self->doRequiredParameterError('setBodyImage', 'Image');
  }

  $self->{bodyImage} = shift;
}

1;
__END__

=head1 NAME

HTMLObject::Base - Perl extension for HTMLObject.

=head1 SYNOPSIS

  use HTMLObject::Base;
  my $doc = HTMLObject::Base->new();

  $doc->setTitle("Test of HTMLObject::Base");
  $doc->setFocus("body");
  $doc->print(<<"END_OF_BODY");
  <center>
  <h1>HTMLObject::Base</h1>
  <br>
  This is cool!
  END_OF_BODY

  $doc->setCookie(name => 'cookie name', value => 'This rocks!');

  # Actually generate the entire document, cookie and all!
  $doc->display();

=head1 DESCRIPTION

HTMLObject::Base provides the Base methods needed to create a generic
HTML document dynamically.  See documentation.html for complete details.
It now supports Internationalization via the lang and charset
attributes of the html tag and the Content-type.

=head1 Exported FUNCTIONS

  scalar new()
    Creates a new instance of the HTMLObject::Base document type.

  void reset()
    Resets the HTMLObject::Base document back to the defaults.

  void set_error_message(code => '', message => '')
    This adds the error message associated with code to the
    errorMessages hash. Modifies %errorMessages.

  void setErrorMessage(code => '', message => '')
    This adds the error message associated with code to the
    errorMessages hash. Modifies %errorMessages.

  void clear_error_message(code => '')
    This removes the message associated with code from the
    errorMessages hash. Modifies %errorMessages.

  void clearErrorMessage(code => '')
    This removes the message associated with code from the
    errorMessages hash. Modifies %errorMessages.

  void set_error(code => '')
    This takes the code and sets $error=1, $errorCode = $code. This is a
    helper function for the derived classes to use to signal when an
    error has occurred. Modifies $error and $errorCode.

  void setError(code => '')
    This takes the code and sets $error=1, $errorCode = $code. This is a
    helper function for the derived classes to use to signal when an
    error has occurred. Modifies $error and $errorCode.

  scalar didErrorOccurr() - (This is gone in 2.x series.)
    Returns 1 if an error occurred, 0 otherwise.

  scalar didErrorOccur()
    Returns 1 if an error occurred, 0 otherwise.
  
  scalar getErrorMessage()
    Returns the message that was generated via the code that was set.

  scalar getErrorCode()
    Returns the code that was set to indicate the error that occurred.

  void doRequiredParameterError(title => '', message => '')
    Creates an Error document using the customized title to display the
    error of Required Parameter missing. The specified message is also
    included in the body so that the program can notify the user of what
    variable is missing. Uses displayError() to generate the Error
    document.

  void display()
    This function generates the Base Document displaying any cookies,
    plus the contents of the Body that the user created.  This function
    prints the generated document to standard out which is then hopefully
    being sent to a web server to process.

  void displayError(title => '', message => '')
    Creates a HTML document that displays the user specified error
    message along with the error message generated by the program. The
    user specified title is used also. The program is exited after the
    document is displayed. Uses display() to generate the actual document.

  void set_content_type(content_type) (scalar value)
    Uses the specified string to set the content-type: header with.
    Modifies $contentTypeString. If $contentType not equal to
    "text/html" then the focus is automatically set to "body".

  void setContentType(contentType) (scalar value)
    Uses the specified string to set the content-type: header with.
    Modifies $contentTypeString. If $contentType not equal to
    "text/html" then the focus is automatically set to "body".

  scalar get_content_type()
    Returns $contentTypeString.  If the content-type string is 
    text/html, then the ; charset=xxxx is also appended.
    
  scalar getContentType()
    Returns $contentTypeString.  If the content-type string is 
    text/html, then the ; charset=xxxx is also appended.
    
  void set_language_encoding(language => 'en', encoding => 'iso-8859-1')
    Sets the language and encoding values to the specified values after
    validating that they exist and are valid together.
    
  void setLanguageEncoding(language => 'en', encoding => 'iso-8859-1')
    Sets the language and encoding values to the specified values after
    validating that they exist and are valid together.
    
  scalar get_language()
    Returns the value of $language.
    
  scalar getLanguage()
    Returns the value of $language.
    
  scalar get_language_name()
    Returns the name of the language we are using.
    
  scalar getLanguageName()
    Returns the name of the language we are using.
    
  scalar lookup_language_name(code => 'en')
    Returns the name of the language code that is specified.  Defaults
    to looking up english if nothing specified.  Returns an empty string
    if the language code is not defined in our hash.
    
  scalar lookupLanguageName(code => 'en')
    Returns the name of the language code that is specified.  Defaults
    to looking up english if nothing specified.  Returns an empty string
    if the language code is not defined in our hash.
    
  scalar get_char_encoding()
    Returns the value of $charsetEncoding.
    
  scalar getCharEncoding()
    Returns the value of $charsetEncoding.
    
  (scalar or @ ref) lookup_char_encoding(code => 'en')
    Returns the array ref or string that represents the valid charset
    encodings that this language code supports.  Defaults to looking up
    english if nothing specified.

  (scalar or @ ref) lookupCharEncoding(code => 'en')
    Returns the array ref or string that represents the valid charset
    encodings that this language code supports.  Defaults to looking up
    english if nothing specified.

  void set_title(title)  (scalar value)
    Uses the specified string to set the title with. Modifies
    $titleString.

  void setTitle(title)  (scalar value)
    Uses the specified string to set the title with. Modifies
    $titleString.

  scalar get_title()
    Returns $titleString.

  scalar getTitle()
    Returns $titleString.

  scalar get_head_string()
    Returns $headString.

  scalar getHeadString()
    Returns $headString.

  scalar get_body_string()
    Returns $bodyString.

  scalar getBodyString()
    Returns $bodyString.

  scalar encode_string(string => '')
    URI encodes the string and returns the result.
    
  scalar encodeString(string => '')
    URI encodes the string and returns the result.
    
  scalar form_encode_string(string => '')
    encode the string to replace all HTML special characters with their
    tag equivalents.  Ex.  & => &amp;

  scalar formEncodeString(string => '')
    encode the string to replace all HTML special characters with their
    tag equivalents.  Ex.  & => &amp;

  void set_cookie(name => '', value => '', expires => '', path => '',
                  domain => '', secure => '')
    Creates an entry in the cookies array that specifies the name=value
    pair and the expiration date and if it is to be secure for the
    specified cookie.  If secure is defined then it is included in the
    Set-Cookie line, else it is left out. The value does not matter as it
    is a tag in the Set-Cookie line and not a name=value item. Modifies
    @cookies.

    Valid formats for the expiration date are:
             Weekday, dd-Mon-yyyy hh:mm:ss GMT
    Valid formats for the domain are:
             The domain must be within the current domain and must have
             2 or more periods depending on the type of domain.
             Ex. ".host.com"

  void setCookie(name => '', value => '', expires => '', path => '',
                 domain => '', secure => '')
    Creates an entry in the cookies array that specifies the name=value
    pair and the expiration date and if it is to be secure for the
    specified cookie.  If secure is defined then it is included in the
    Set-Cookie line, else it is left out. The value does not matter as it
    is a tag in the Set-Cookie line and not a name=value item. Modifies
    @cookies.

    Valid formats for the expiration date are:
             Weekday, dd-Mon-yyyy hh:mm:ss GMT
    Valid formats for the domain are:
             The domain must be within the current domain and must have
             2 or more periods depending on the type of domain.
             Ex. ".host.com"

  void set_compressed_cookie(name => '', cookies => [name, value],
                             expires => '', path => '', domain => '',
                             secure => '')
    Creates an entry in the cookies array that specifes the name=value
    pair where the value is the embedded cookies to be stored in this
    cookie. The embedded cookies are seperated with a :: but other than
    that everything else is the same as setCookie. The cookies hash
    entry is pointing to an array where each entry is another array with
    the first entry being the name and the second entry the value for
    each embedded cookie. Modifies @cookies.

  void setCompressedCookie(name => '', cookies => [name, value],
                           expires => '', path => '', domain => '',
                           secure => '')
    Creates an entry in the cookies array that specifes the name=value
    pair where the value is the embedded cookies to be stored in this
    cookie. The embedded cookies are seperated with a :: but other than
    that everything else is the same as setCookie. The cookies hash
    entry is pointing to an array where each entry is another array with
    the first entry being the name and the second entry the value for
    each embedded cookie. Modifies @cookies.

  void set_meta_tag('http-equiv' => '', content => '')
    Creates an entry in the meta_tags array that specifies the http-equiv
    and content values for the specified Meta tag to be created when
    display is called. Modifies @metaTags.

  void setMetaTag('http-equiv' => '', content => '')
    Creates an entry in the meta_tags array that specifies the http-equiv
    and content values for the specified Meta tag to be created when
    display is called. Modifies @metaTags.

  void set_focus(section) (scalar value)
    Validates the section name specified and then sets the internal
    pointer to the specified section. The output of any following print,
    read, or delete commands will work with the specified section.
    Modifies $currentSection.

  void setFocus(section) (scalar value)
    Validates the section name specified and then sets the internal
    pointer to the specified section. The output of any following print,
    read, or delete commands will work with the specified section.
    Modifies $currentSection.

  scalar get_focus()
    Returns the currently specified section.

  scalar getFocus()
    Returns the currently specified section.

  void print(string) (scalar value)
    Appends the contents of string to the currently specified section.
    This could modify $headString or $bodyString.

  scalar read()
    Returns the contents of the currently specified section. This could
    be $headString or $bodyString.

  void delete()
    Deletes the contents of the currently specified section. You should
    call read() before doing this so you can restore if this was an
    accident. This could modify $headString or $bodyString.

  void set_body_bgcolor(color)  (scalar value)
    This function sets the background color for the body. Modifies
    $bodyBgcolor.

  void setBodyBgcolor(color)  (scalar value)
    This function sets the background color for the body. Modifies
    $bodyBgcolor.

  scalar get_body_bgcolor()
    This function returns the background color for the body.

  scalar getBodyBgcolor()
    This function returns the background color for the body.

  void set_body_fgcolor(color)  (scalar value)
    This function sets the text color for the body. Modifies
    $bodyFgcolor.

  void setBodyFgcolor(color)  (scalar value)
    This function sets the text color for the body. Modifies
    $bodyFgcolor.

  scalar get_body_fgcolor()
    This function returns the text color for the body.

  scalar getBodyFgcolor()
    This function returns the text color for the body.

  void set_body_link_color(color)  (scalar value)
    This function sets the default link color for the body. Modifies
    $bodyLinkColor.

  void setBodyLinkColor(color)  (scalar value)
    This function sets the default link color for the body. Modifies
    $bodyLinkColor.

  scalar get_body_link_color()
    This function returns the default link color for the body.

  scalar getBodyLinkColor()
    This function returns the default link color for the body.

  void set_body_vlink_color(color)  (scalar value)
    This function sets the visited link color for the body. Modifies
    $bodyVlinkColor.

  void setBodyVlinkColor(color)  (scalar value)
    This function sets the visited link color for the body. Modifies
    $bodyVlinkColor.

  scalar get_body_vlink_color()
    This function returns the visited link color for the body.

  scalar getBodyVlinkColor()
    This function returns the visited link color for the body.

  void set_body_alink_color(color)  (scalar value)
    This function sets the active link color for the body. Modifies
    $bodyAlinkColor.

  void setBodyAlinkColor(color)  (scalar value)
    This function sets the active link color for the body. Modifies
    $bodyAlinkColor.

  scalar get_body_alink_color()
    This function returns the active link color for the body.

  scalar getBodyAlinkColor()
    This function returns the active link color for the body.

  void set_body_image(image)  (scalar value)
    This function sets the background image for the body. Modifies
    $bodyImage.

  void setBodyImage(image)  (scalar value)
    This function sets the background image for the body. Modifies
    $bodyImage.

=head1 AUTHOR

James A. Pattie, htmlobject@pcxperience.com

=head1 SEE ALSO

perl(1), HTMLObject::Normal(3), HTMLObject::FrameSet(3), HTMLObject::ReadCookie(3).

=cut
