NAME

MOJO::Template::HTML


SYNOPSIS

Module for generating html templates for lists and administration

DESCRIPTION

 use MOJO::Template::HTML;

 #print out a admin header template: 
 print admin_html_header(-Title => "hola! I am a list header", 
                                                   -List => $list,
                                                 );

 # now, print the admin footer template: 
 print admin_html_footer();

 # give me the default mojo list template
 my $default_template = default_template($MOJO_URL);

 # do I have a template?

        my $template_exists = check_if_template_exists(-List => $list);                                                 
    print "my template exists!!" if $template_exists >= 1;

 # what lists do have templates? 
 my @list_templates = available_templates();

 # open up my template
 my $list_template = open_template(-List => $list);

 # print a list template header
 print the_html(-List      => $list,    
                                -Path      => 'header', 
                        );

 # print the list template footer                       
  print the_html(-List      => $list,   
                                -Path      => 'footer', 
                                -Site_Name =>  "justin's site", 
                                -Site_URL  =>  "http://skazat.com";, 
                        );

 # print a generic submit form
   print submit_form(-Submit => 'ZOOOOOOOOOM!', 
                                         -Reset  => 'stop.', 
                                         -Align  => 'left', 
                                         -Width  => '100%'
                                        );
 # the 'send this archived message to a friend" link maker
 # print archive_send_link($list, $message_id);


=cut

#html templates for Mojo Mail

sub admin_html_header {

        my %args = (-Title        => "", 
                                -List         => "",
                                -Root_Login   => 0,
                                -Form         => 1,
                                @_); 

        require MOJO::Template::Widgets::Admin_Menu;
        my $ADMIN_MENU; 
        my %list_info =  open_database(-List => $args{-List}); 
        if($args{-Root_Login} == 1){ 
                $ADMIN_MENU = MOJO::Template::Widgets::Admin_Menu::make_admin_menu('superuser'); 
        }else{ 
                $ADMIN_MENU = MOJO::Template::Widgets::Admin_Menu::make_admin_menu('user',\%list_info); 
        }
        my $title = $args{-Title}; 
        my $list = $args{-List}; 
        my $root_login_message;

        if($args{-Root_Login} == 1){
                $root_login_message = '<span style="font-size:14px;font-weight:bold;color:red">Logged in as Root</span>';

=cut            
                require MOJO::Template::Widgets
                $root_login_message = '<form action="$MOJO_URL"><input type=

=cut
        }else{ 
                $root_login_message = '';
        }

my $default_admin_html_header = qq{ <html> <head> <title>[title] - [list_name] - $PROGRAM_NAM&[title] - [list_name] - $PROGRAM_NAM;/title>

<!--[javascript]-->

<style> <!-- body{font-family:verdana, arial;font-size:11px} p{font-family:verdana,arial;font-size:11px;line-height:150%} td{font-family:verdana,arial;font-size:11px}

p.title{font-family:arial;font-weight:bold;font-size:16px} p.small{font-family:verdana,arial;font-size:9px} h3{font-family:arial;font-size:16px} pre{font-family:arial}

a.title:link{font-family:arial;font-size:16px;color:black;text-decoration:none} a.title:active{font-family:arial;font-size:16px;color:black;text-decoration:none} a.title:visited{font-family:arial;font-size:16px;color:black;text-decoration:none}

a.mojotitle:link{font-family:arial;font-size:16px;color:black;text-decoration:none} a.mojotitle:active{font-family:arial;font-size:16px;color:black;text-decoration:none} a.mojotitle:visited{font-family:arial;font-size:16px;color:black;text-decoration:none}

input{color: #333333; font: 11px/125% verdana, arial} textarea{color: #333333; font: 11px/125% verdana, arial} select{color: #333333; font: 11px/125% verdana, arial}

a:link{font-family:arial;size:13px;color:#333399;text-decoration:none} a:hover{font-family:arial;size:13px;color:#3333CC;text-decoration:underline} a:visited{font-family:arial;size:13px;color:#0033CC}

a.black:link{font-family:arial;size:13px;color:#000000;text-decoration:none; cursor:default} a.black:hover{font-family:arial;size:13px;color:#000000;text-decoration:none; cursor:default} a.black:visited{font-family:arial;size:13px;color:#000000;text-decoration:none; cursor:default}

p.smallred{font-family:verdana,arial;font-size:11px;color:#660000}

hr {

width: 66%; height: 1px; color: black;

}

//--> </style>

</head>

<body bgcolor=``#FFFFFF''> <table width=``602'' border=``0'' height=``100%'' align=center> <tr> <td align=``center''>

<table width=``100%'' border=``0'' cellpadding=``1'' cellspacing=``0'' bgcolor=``#000000''> <tr> <td> <table width=``100%'' border=``0'' cellpadding=``5'' cellspacing=``0''> <tr> <td width=``200'' bgcolor=``#CC9966''> <p class=title>.: <a href=[mojo_url] class=title>$PROGRAM_NAM&$PROGRAM_NAM;/a> </p> </td> <td width=``400'' align=``right'' bgcolor=``#CC9966''> <p class=title>[root_login_message] :: [title] ::</p> </td> </tr> </table> </td> </tr> </table>

<!-- top half -->


   <table width="602" border="0" cellpadding="1" cellspacing="0" bgcolor="#000000">
   <tr>
    <td>
              <table width="600" border="0" bgcolor="#FFFFFF" cellspacing="0" cellpadding="5">
                <tr> 
                  <td width="200" valign="top" bgcolor="#FFFFFF" align="left"> 
                    <table width="178" border="0" cellpadding="1" cellspacing="0" bgcolor="#000000">
                      <tr> 
                        <td> 
                          <table width="176" border="0" cellpadding="3" cellspacing=0 bgcolor="#FFFFFF">
                            <tr> 
                              <td width="176">
                              <p>
                              <!-- Admin Menu belongs HERE --> 

                              [admin_menu]

                             <!-- Admin Menu stops HERE -->

                             <p>
                              </td>
                            </tr>
                          </table>
                        </td>
                      </tr>
                    </table>

                  <p>&nbsp;</p></td>
                  <td width="400" valign="top">

};

        my $header_part;
        if($ADMIN_TEMPLATE){    
                my ($saved_header, $saved_footer) = fetch_admin_template($ADMIN_TEMPLATE); 
                $header_part = $saved_header;
        }else{ 
                $header_part = $default_admin_html_header;
        }
        $header_part = $header_part . qq{<form action="[mojo_url]" method=POST name=default_form> } unless $args{-Form} == 0;   
        my $js       = admin_js(); 
        $header_part =~ s/<\!--\[javascript\]-->/$js/g;
        $header_part =~ s/\[javascript\]/$js/g;
        $header_part =~ s/\[admin_menu\]/$ADMIN_MENU/g;
        $header_part =~ s/\[title\]/$title/g;
        $header_part =~ s/\[list\]/$list/g;
        $header_part =~ s/\[list_name\]/$list_info{list_name}/g;
        $header_part =~ s/\[ver\]/$VER/g;
        $header_part =~ s/\[mojo_url\]/$S_MOJO_URL/g;
        $header_part =~ s/\[root_login_message\]/$root_login_message/g;
        $header_part = header(-type => 'text/html',  -charset => $HTML_CHARSET) . $header_part; 
        return $header_part;

}

############################################################################# # holds the default admin template. footer # #############################################################################

sub admin_html_footer {


        my %args = (-Form => 1, -Root_Login => 0, -List => '',  @_); 
        my $default_admin_html_footer =  <<EOF
    </td>
   </tr>
  </table>
    </td>
   </tr>
  </table>

<!-- bottom -->

   <table width="100%" border="0" cellpadding="1" cellspacing="0" bgcolor="#000000">
   <tr>
    <td>
              <table width="100%" border="0" cellpadding="3" cellspacing=0 bgcolor="#FFFFFF">
                <tr align="right"> 
                  <td width="100%"> 
                   <!--
                    <p class=small align=right>copyright &copy; 1999 - 2003 <a href="http://justinsimoni.com"; target=out>justin 
                      simoni</a></p>
                  --> 

                  </td>
                </tr>
              </table> 
       </td>
      </tr>
     </table>
      </td>
   </tr>
  </table>

</body> </html>

EOF ;

        my $footer_part;
        require MOJO::Template::Widgets::Admin_Menu;
        my $ADMIN_MENU; 
        my %list_info =  open_database(-List => $args{-List});  
        if($args{-Root_Login} == 1){ 
                $ADMIN_MENU = MOJO::Template::Widgets::Admin_Menu::make_admin_menu('superuser'); 
        }else{ 
                $ADMIN_MENU = MOJO::Template::Widgets::Admin_Menu::make_admin_menu('user',\%list_info); 
        }

        if($ADMIN_TEMPLATE){ 
                my ($saved_header, $saved_footer) = fetch_admin_template($ADMIN_TEMPLATE); 
                $footer_part = $saved_footer;
        }else{ 
                $footer_part = $default_admin_html_footer;
        }

        $footer_part =~ s/\[admin_menu\]/$ADMIN_MENU/g;
        $footer_part = '</form> ' . $footer_part unless $args{-Form} == 0; 
        return $footer_part;
}

sub default_template { ############################################################################# # holds the default user template. # ############################################################################# my $MOJO_URL = shift; my $default_template = <<EOF

<!-- start header --> <!-- Mojo Mail is Copyright 1999 - 2003 Justin Simoni --> <!-- http://mojo.skazat.com -->

<html> <head> <title>[message] - $PROGRAM_NAME [version]</title>

<style>

<!-- body{font-family:verdana, arial;font-size:11px} p{font-family:verdana,arial;font-size:11px;line-height:125%} td{font-family:verdana,arial;font-size:11px}

p.title{font-family:arial;font-weight:bold;font-size:16px;font-weight:bold}

p.mojotitle{font-family:arial;font-size:16px;font-weight:bold}

p.small{font-family:verdana,arial;font-size:9px}

h3{font-family:arial;font-size:13px}

a.title:link{font-family:arial;font-size:16px;color:black;text-decoration:none} a.title:active{font-family:arial;font-size:16px;color:black;text-decoration:none} a.title:visited{font-family:arial;font-size:16px;color:black;text-decoration:none}

a.mojotitle:link{font-family:arial; font-size:16px; color:black; text-decoration:none; font-weight:bold} a.mojotitle:active{font-family:arial;font-size:16px;color:black;text-decoration:none;font-weight:bold} a.mojotitle:visited{font-family:arial;font-size:16px;color:black;text-decoration:none;font-weight:bold}

input{color: #333333; font: 11px/125% verdana, arial} textarea{color: #333333; font: 11px/125% verdana, arial} select{color: #333333; font: 11px/125% verdana, arial}

a:link{font: 11px/125% verdana, arialcolor:#333399;text-decoration:none} a:hover{font: 11px/125% verdana, arial;size:13px;color:#3333CC;text-decoration:underline} a:visited{font: 11px/125% verdana, arial;size:13px;color:#0033CC}

p.smallred{font-family:verdana,arial;font-size:11px;color:#660000}

div.archivesend { border-top: 1px solid black; border-bottom: 1px solid black; }

hr {

width: 66%; height: 1px; color: black;

}

//-->

</style>

 </head>
 <body bgcolor="#FFFFFF">
 <table width="402" border="0" height="100%" align=center>
  <tr > 
   <td align="center" valign="middle"> 
    <table width="100%" border="0" cellpadding="1" cellspacing="0" bgcolor="#000000">
     <tr>
      <td>

       <table width="100%" border="0" cellpadding="5" cellspacing="0">
        <tr> 
         <td  bgcolor="#CC9966"> 
          <p class=title>.: <a class=mojotitle href=$MOJO_URL>$PROGRAM_NAME</a></p>
           </td>
            <td align="right"  bgcolor="#CC9966">
             <p class=title>:: [message] ::</p>
           </td>
         </tr>
       </table>

     </td>
    </tr>
   </table>
   <table width="100%" border="0" cellpadding="1" cellspacing="0" bgcolor="#000000">
   <tr>
    <td>
     <table width="100%" border="0" bgcolor="#FFFFFF" cellspacing="0" cellpadding="5">
      <tr>
       <td> 

<!-- end header -->


    [mojo]

<!-- start footer -->

 </td>
        </tr>
      </table>
     </td>
    </tr>
   </table>

    </td>
   </tr>
  </table>

 </body>
</html>

<!-- end footer -->

EOF ;

        if(!$USER_TEMPLATE){ 
                return $default_template; 
        }else{ 
                return fetch_user_template($USER_TEMPLATE); 
        }       
}

###################################################################### # templates and such that give the look of mojo # ######################################################################

sub check_if_template_exists { ############################################################################# # mojo utility <+> $template_exists <+> sees if the list has a template # #############################################################################

        my %args = (-List => undef, 
                                @_);

        if($args{-List}){ 
                my(@available_templates) = &available_templates;
                my $template_exists = 0;        
                foreach my $hopefuls(@available_templates) { 
                        if ($hopefuls eq $args{-List}) { 
                                $template_exists++;
                        }
                }    
                return $template_exists;
        }else{ 
                return 0;
        }
}

sub available_templates {
my @all;
my @available_templates;


        my $present_template = "";
        opendir(TEMPLATES, $TEMPLATES) or 
                die "$PROGRAM_NAME $VER error, can't open $TEMPLATES to read: $!";

        while(defined($present_template = readdir TEMPLATES)) { 
                next if $present_template =~ /^\.\.?$/;
                        $present_template =~ s(^.*/)();

                push(@all, $present_template);                             
        }          
        closedir(TEMPLATES);

        foreach my $all_those(@all) { 
                         if($all_those =~ m/.*\.template/) { 
                                   $all_those =~ s/\.template$//;
                                  push(@available_templates, $all_those)
                         }
                 }

         @available_templates = sort(@available_templates); 
        my %seen = (); 
        my @unique = grep {! $seen{$_} ++ }  @available_templates;

        return @unique; 
}

sub fetch_admin_template {
my $file = shift;
my $list_template;


        if($file !~ m/^\//){ 
                $file = $TEMPLATES .'/'. $file;
        }

        sysopen(TEMPLATE,"$file",  O_RDONLY|O_CREAT, $FILE_CHMOD) or 
                die "$PROGRAM_NAME $VER Error: Can't open  list template for reading at '$file': $!";
        flock(TEMPLATE, 1) or 
                die "$PROGRAM_NAME $VER Error: Can't create a shared lock for template file at '$file': $!";
           {
                #slurp it all in
           local $/ = undef; 
                $list_template = <TEMPLATE>;

                }
        close (TEMPLATE);
        my ($header, $FOOTER) = split(/\[content\]/, $list_template); 
        return($header, $FOOTER); 
}

sub fetch_user_template {
my $file = shift;
my $list_template;


        sysopen(TEMPLATE,"$file",  O_RDONLY|O_CREAT, $FILE_CHMOD) or 
                die "$PROGRAM_NAME $VER Error: Can't open  list template for reading at '$file': $!";
        flock(TEMPLATE, 1) or 
                die "$PROGRAM_NAME $VER Error: Can't create a shared lock for template file at '$file': $!";
           {
                #slurp it all in
           local $/ = undef; 
                $list_template = <TEMPLATE>;

                }
        close (TEMPLATE);
        return $list_template; 
}

sub open_template {

        my %args = (-List => undef,
                                @_);

        my $list = $args{-List};

        #untaint 
        $list = make_safer($list); 
        $list =~ /(.*)/; 
        $list = $1;

        my $list_template = "";

        my @template;

        sysopen(TEMPLATE,"$TEMPLATES/$list.template",  O_RDONLY|O_CREAT, $FILE_CHMOD) or 
                die "$PROGRAM_NAME $VER Error: Can't open  list template for reading at '$TEMPLATES/$list.template': $!";
        flock(TEMPLATE, 1) or 
                die "$PROGRAM_NAME $VER Error: Can't create a shared lock for template file at '$TEMPLATES/$list.template': $!";

        @template = <TEMPLATE>; 
        close (TEMPLATE);

        foreach(@template){ 
                $list_template .= $_;
        }
        return  $list_template;
}

sub the_html {

        my %args = (-List       => undef, 
                                -Part       => undef, 
                                -Title      => undef, 
                                -Site_Name  => "", 
                                -Site_URL   => "", 
                                -Start_Form => 1,
                                -End_Form   => 1,
                                -Header     => 1,
                                @_);

        $args{-List} =~ s/ /_/i;

        my $default_template = default_template($MOJO_URL); 
        my $template_exists  = check_if_template_exists(-List => $args{-List});
        my $the_header = "";
        my $the_footer = "";

        my %li; 
        if($args{-List}){ 
                %li = open_database(-List =>  $args{-List}); 
        }else{ 
                %li = ();
        }

        if(exists($li{list})){          
                if($li{get_template_data} eq "from_url"  && $li{url_template} =~ m/^http:\/\//){ 
                        my $list_template = open_template_from_url(-List => $args{-List}, 
                                                                                                           -URL  => $li{url_template}); 
                        ($the_header, $the_footer) = split(/\[mojo\]/,$list_template);
                }elsif($template_exists >= 1) { 
                        my $list_template = open_template(-List => $args{-List}); 
                        ($the_header, $the_footer) = split(/\[mojo\]/,$list_template);
                } else {
                        ($the_header, $the_footer) = split(/\[mojo\]/,$default_template);               
                }
        }else{ 
                ($the_header, $the_footer) = split(/\[mojo\]/,$default_template);               
        }

        if($args{-Part} eq "header")  {

                $the_header =~ s/\[message\]/$args{-Title}/g; 
                $the_header =~ s/\[version\]/$VER/g; 
                $the_header .= "\n<form action=\"$MOJO_URL\" method=POST>\n" if $args{-Start_Form} != 0;
                if($args{-Header} == 1){ 
                        return header(-type => 'text/html; ' . $HTML_CHARSET) . $the_header;
                }else{ 
                        $the_header;
                }
        }else{
                $the_footer = "<p><center>$HTML_FOOTER</center></p>\n" . $the_footer . "\n";

                if($args{-Site_Name} && $args{-Site_URL}) { 
                        $the_footer ="<p>Go back to <a href=\"$args{-Site_URL}\">$args{-Site_Name}</a></p>\n\n $the_footer";
                }               
                $the_footer =~ s/\[message\]/$args{-Title}/g; 
                $the_footer =~ s/\[version\]/$VER/g; 
                $the_footer = '</form> ' . $the_footer if $args{-End_Form} != 0;

                return $the_footer;
        }
}

sub open_template_from_url {
my %args = (-List => undef,
-URL => undef,
@_);
if(!$args{-URL}){
warn ``new url passed! $!'';
return undef;
}else{
eval { require LWP::Simple };
if($@){
warn ``LWP::Simple not installed! $!'';
return undef;
}else{
return LWP::Simple::get($args{-URL});
}
}
}


sub submit_form{

my %args = (-Reset => 'Clear Changes',
-Submit => 'Save Changes',
-Align => 'Right',
-Width => '',
@_);

my $form = <<EOF

 <table width=$args{-Width} align=$args{-Align}> 
 <tr>
  <td><input type=reset  style='$STYLE{yellow_submit}' value="$args{-Reset}"></td>
  <td><input type=submit style='$STYLE{green_submit}' value="$args{-Submit}"></td>
 </tr>
</table>

EOF ;

        return $form;
}

sub archive_send_form {

my ($list, $id, $errors) = @_;

my $error_msg = ' ';


$error_msg = "<p style='color:red'><b><i>This form was filled out incorrectly.</i></b></p>" if $errors > 0;

my $form = <<EOF <div class='archivesend'> <h3>Send this message to a friend:</h3> $error_msg

 </form> 
 <form action=$MOJO_URL method=POST>
  <input type="hidden" name="list"     value="$list" />
  <input type="hidden" name="entry" value="$id" /> 
  <input type=hidden name=flavor value=send_archive> 
  <input type=hidden name=process value=true> 

  <p>Your e-mail address:<br /> 
  <input type="text" name="sender_email" />

  <p>Your friend's email address:<br>

  <input type="text" name="email" /></p>
  <p>Note:<br /> 
  <textarea rows="5" cols="40" name="note"></textarea></p> 
 <p align="right"> 
  <input type=submit style="$STYLE{green_submit}" value="Send Archived Message" />
 </p>

 </form> 
 <form action="$MOJO_URL" method="POST">
</div>
EOF
;

return $form; }

sub admin_js {

return <<EOF

<script language=``javascript''> <!--

function make_html() { the_size = document.the_form.the_size.options[document.the_form.the_size.selectedIndex].value; form_field_label = document.the_form.form_field_label.value; button_label = document.the_form.button_label.value;

var foo = document.the_form.unsub_radio_buttons.options[document.the_form.unsub_radio_buttons.selectedIndex].value;


code  = '<form action="[mojo_url]" method=POST>\\n';

if(foo == ``yes''){ code2 = '<input type=``radio'' name=``flavor'' value=``subscribe'' checked> Subscribe \\n'; code2 += '<input type=``radio'' name=``flavor'' value=``unsubscribe''> Unsubscribe<br>\\n';


}else{ 
code2 =' <input type="hidden" name="flavor" value="subscribe">\\n';

}

code3 = '<input type=``text'' name=``email'' value=``'+form_field_label+''' size=``'+the_size+'''>\\n'; code4 = '<input type=``hidden'' name=``list'' value=``[list]''>\\n';

code5 = '<input type=``submit'' value=``'+button_label+'''>\\n</form>'; //alert(document.the_form.give_prog_credit.options[document.the_form.give_prog_credit.selectedIndex].value); if(document.the_form.give_prog_credit.options[document.the_form.give_prog_credit.selectedIndex].value == ``yes''){ code5 += ``<p style='font-size:10px;font-family:verdana,arial'>powered by <a href= http://mojo.skazat.com target=out style='font-size:10px;font-family:verdana,arial'>$PROGRAM_NAM&$PROGRAM_NAM;/a></p>''; }

var all_code = code + code2 + code3 + code4+ code5;

document.the_form.code.value = all_code; }

function preview() { var new_window = window.open(``'', ``preview'', ``top=100,left=100,resizable,scrollbars,width=400,height=200''); }

function SetChecked(val) {

dml=document.email_form; len = dml.elements.length; var i=0; for( i=0 ; i<len ; i++) { if (dml.elements[i].name=='address') { dml.elements[i].checked=val; } } }

function set_to_default(){


        default_template = document.the_form.default_template.value; 
        document.the_form.template_info.value = default_template;       
}

function list_message_status(thing) { document.the_form.process.value=thing; }

function preview_template() { document.the_form.target=``_blank''; document.the_form.process.value=``preview template''; }

function change_template() {

document.the_form.process.value=``true''; //alert(document.the_form.process.value); }

function check_newest_version() {

var check = ``http://mojo.skazat.com/cgi-bin/support/version.cgi?version=[ver]'';

window.open(check,'version', 'width=325,height=300,top=20,left=20');

}

function add_delete_list() {

var address_list = document.the_form.delete_list.value; var Address = document.the_form.email_list.selectedIndex; var new_address = document.the_form.email_list.options[Address].value; var append_list = address_list+``\\n''+new_address; document.the_form.delete_list.value = append_list;

}

function just_test_message() { document.the_form.process.value=``just_test_message''; }

function real_message() { document.the_form.process.value=``true''; }

function moveDeletion(object) { var chuck_em = object.delete_list.value; for (var Current=0;Current < object.email_list.options.length;Current++) { if (object.email_list.options[Current].selected) { chuck_em += object.email_list.options[Current].value; chuck_em += ``\\n''; } } object.delete_list.value = chuck_em; }


 function checklink(thisbox) {
 if (document.default_form.elements[thisbox].checked == true) {
      document.default_form.elements[thisbox].checked=false;
  }else{
  document.default_form.elements[thisbox].checked=true;
  }
}
 function checkotherlink(thisbox) {
 if (document.checkbox_form.elements[thisbox].checked == true) {
      document.checkbox_form.elements[thisbox].checked=false;
  }else{
  document.checkbox_form.elements[thisbox].checked=true;
  }
}

function testPOPBeforeSMTP() {


        var popcheck = '$S_MOJO_URL?f=checkpop&user='+document.default_form.pop3_username.value+'&pass='+document.default_form.pop3_password.value+'&server='+document.default_form.pop3_server.value;
        window.open(popcheck,'popcheck', 'width=325,height=300,top=20,left=20');
}

function init(){ var list_name = ``[list]''; var title = ``[title]''; window.status = '$PROGRAM_NAME [ver] | '+list_name+' :: '+title;return true; }

onLoad=init();


//-->
</script>

EOF ;

} =pod


Changes

3/29/01 - Tweaked the POD a bit.


COPYRIGHT

Copyright (c) 1999 - 2003 Justin Simoni me@justinsimoni.com http://justinsimoni.com All rights reserved.

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.