/*
FILE:     ndb_htmllib.C
*/
/*
VERSION:  1.600
*/
/*
DATE:     2/3/2005
*/
/*
  Comments and Questions to: sw-help@rcsb.rutgers.edu
*/
/*
COPYRIGHT 1999-2005 Rutgers - The State University of New Jersey

This software is provided WITHOUT WARRANTY OF MERCHANTABILITY OR
FITNESS FOR A PARTICULAR PURPOSE OR ANY OTHER WARRANTY, EXPRESS OR
IMPLIED.  RUTGERS MAKE NO REPRESENTATION OR WARRANTY THAT THE
SOFTWARE WILL NOT INFRINGE ANY PATENT, COPYRIGHT OR OTHER
PROPRIETARY RIGHT.

The user of this software shall indemnify, hold harmless and defend
Rutgers, its governors, trustees, officers, employees, students,
agents and the authors against any and all claims, suits,
losses, liabilities, damages, costs, fees, and expenses including
reasonable attorneys' fees resulting from or arising out of the
use of this software.  This indemnification shall include, but is
not limited to, any and all claims alleging products liability.
*/
/*
               PDB SOFTWARE LICENSE AGREEMENT

BY CLICKING THE ACCEPTANCE BUTTON OR INSTALLING OR USING 
THIS "SOFTWARE, THE INDIVIDUAL OR ENTITY LICENSING THE  
SOFTWARE ("LICENSEE") IS CONSENTING TO BE BOUND BY AND IS 
BECOMING A PARTY TO THIS AGREEMENT.  IF LICENSEE DOES NOT 
AGREE TO ALL OF THE TERMS OF THIS AGREEMENT
THE LICENSEE MUST NOT INSTALL OR USE THE SOFTWARE.

1. LICENSE AGREEMENT

This is a license between you ("Licensee") and the Protein Data Bank (PDB) 
at Rutgers, The State University of New Jersey (hereafter referred to 
as "RUTGERS").   The software is owned by RUTGERS and protected by 
copyright laws, and some elements are protected by laws governing 
trademarks, trade dress and trade secrets, and may be protected by 
patent laws. 

2. LICENSE GRANT

RUTGERS grants you, and you hereby accept, non-exclusive, royalty-free 
perpetual license to install, use, modify, prepare derivative works, 
incorporate into other computer software, and distribute in binary 
and source code format, or any derivative work thereof, together with 
any associated media, printed materials, and on-line or electronic 
documentation (if any) provided by RUTGERS (collectively, the "SOFTWARE"), 
subject to the following terms and conditions: (i) any distribution 
of the SOFTWARE shall bind the receiver to the terms and conditions 
of this Agreement; (ii) any distribution of the SOFTWARE in modified 
form shall clearly state that the SOFTWARE has been modified from 
the version originally obtained from RUTGERS.  

2. COPYRIGHT; RETENTION OF RIGHTS.  

The above license grant is conditioned on the following: (i) you must 
reproduce all copyright notices and other proprietary notices on any 
copies of the SOFTWARE and you must not remove such notices; (ii) in 
the event you compile the SOFTWARE, you will include the copyright 
notice with the binary in such a manner as to allow it to be easily 
viewable; (iii) if you incorporate the SOFTWARE into other code, you 
must provide notice that the code contains the SOFTWARE and include 
a copy of the copyright notices and other proprietary notices.  All 
copies of the SOFTWARE shall be subject to the terms of this Agreement.  

3. NO MAINTENANCE OR SUPPORT; TREATMENT OF ENHANCEMENTS 

RUTGERS is under no obligation whatsoever to: (i) provide maintenance 
or support for the SOFTWARE; or (ii) to notify you of bug fixes, patches, 
or upgrades to the features, functionality or performance of the 
SOFTWARE ("Enhancements") (if any), whether developed by RUTGERS 
or third parties.  If, in its sole discretion, RUTGERS makes an 
Enhancement available to you and RUTGERS does not separately enter 
into a written license agreement with you relating to such bug fix, 
patch or upgrade, then it shall be deemed incorporated into the SOFTWARE 
and subject to this Agreement. You are under no obligation whatsoever 
to provide any Enhancements to RUTGERS or the public that you may 
develop over time; however, if you choose to provide your Enhancements 
to RUTGERS, or if you choose to otherwise publish or distribute your 
Enhancements, in source code form without contemporaneously requiring 
end users or RUTGERS to enter into a separate written license agreement 
for such Enhancements, then you hereby grant RUTGERS a non-exclusive,
royalty-free perpetual license to install, use, modify, prepare
derivative works, incorporate into the SOFTWARE or other computer
software, distribute, and sublicense your Enhancements or derivative
works thereof, in binary and source code form.

4. FEES.  There is no license fee for the SOFTWARE.  If Licensee
wishes to receive the SOFTWARE on media, there may be a small charge
for the media and for shipping and handling.  Licensee is
responsible for any and all taxes.

5. TERMINATION.  Without prejudice to any other rights, Licensor
may terminate this Agreement if Licensee breaches any of its terms
and conditions.  Upon termination, Licensee shall destroy all
copies of the SOFTWARE.

6. PROPRIETARY RIGHTS.  Title, ownership rights, and intellectual
property rights in the Product shall remain with RUTGERS.  Licensee 
acknowledges such ownership and intellectual property rights and will 
not take any action to jeopardize, limit or interfere in any manner 
with RUTGERS' ownership of or rights with respect to the SOFTWARE.  
The SOFTWARE is protected by copyright and other intellectual 
property laws and by international treaties.  Title and related 
rights in the content accessed through the SOFTWARE is the property 
of the applicable content owner and is protected by applicable law.  
The license granted under this Agreement gives Licensee no rights to such
content.

7. DISCLAIMER OF WARRANTY.  THE SOFTWARE IS PROVIDED FREE OF 
CHARGE, AND, THEREFORE, ON AN "AS IS" BASIS, WITHOUT WARRANTY OF 
ANY KIND, INCLUDING WITHOUT LIMITATION THE WARRANTIES THAT IT 
IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE 
OR NON-INFRINGING.  THE ENTIRE RISK AS TO THE QUALITY AND 
PERFORMANCE OF THE SOFTWARE IS BORNE BY LICENSEE.  SHOULD THE 
SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, THE LICENSEE AND NOT 
LICENSOR ASSUMES THE ENTIRE COST OF ANY SERVICE AND REPAIR.  
THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF 
THIS AGREEMENT.  NO USE OF THE PRODUCT IS AUTHORIZED HEREUNDER 
EXCEPT UNDER THIS DISCLAIMER.

8. LIMITATION OF LIABILITY.  TO THE MAXIMUM EXTENT PERMITTED BY
APPLICABLE LAW,  IN NO EVENT WILL LICENSOR BE LIABLE FOR ANY 
INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 
OUT OF THE USE OF OR INABILITY TO USE THE SOFTWARE, INCLUDING, 
WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK 
STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL 
OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF ADVISED OF THE
POSSIBILITY THEREOF. 
*/
/*

  PURPOSE:      HTML utility library ... 
*/

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>

#include "ndb_htmllib.h"
#include "ndb_misclib.h"

static char *HT_SERVER_URL=NULL;
static char *HT_CGI_PATH=NULL;

static char JSCRIPT_LOCAL_1[] = "\
<SCRIPT LANGUAGE=\"JavaScript\">\n\
\n\
<!--  Hide this from JavaScript-challenged browsers\n\
\n\
function Display2(f1, hRef1, f2, hRef2)\n\
{\n\
        parent.frames[f1].location.href = hRef1;\n\
        parent.frames[f2].location.href = hRef2;\n\
}\n\
\n\
function Display3(f1, hRef1, f2, hRef2, f3, hRef3)\n\
{\n\
        parent.frames[f1].location.href = hRef1;\n\
        parent.frames[f2].location.href = hRef2;\n\
        parent.frames[f3].location.href = hRef3;\n\
}\n\
\n\
function Display4(f1, hRef1, f2, hRef2, f3, hRef3, f4, hRef4)\n\
{\n\
        parent.frames[f1].location.href = hRef1;\n\
        parent.frames[f2].location.href = hRef2;\n\
        parent.frames[f3].location.href = hRef3;\n\
        parent.frames[f4].location.href = hRef4;\n\
}\n\
\n\
//  End of hiding comment -->\n\
\n\
</SCRIPT>\n\
\n";

static int  dq = '"';
static const char *get_short_db_text_name(const char *dbnm, const char *dbvr);



void ht_put_open_frameset(FILE *fph, char *rows, char *cols)
{
   fprintf(fph,"<FRAMESET ");
   if ((rows != NULL) && (strlen(rows) > 0)) fprintf(fph," ROWS=%c%s%c ",dq,rows,dq);

   if ((cols != NULL) && (strlen(cols) > 0)) fprintf(fph," COLS=%c%s%c ",dq,cols,dq);
//   fprintf(fph," border=0 frameborder=0 ");
   fprintf(fph,">\n");
}

void ht_put_open_frame(FILE *fph, char *src, char *name, int mwidth, int mheight, 
		   char *scroll, int resize_flag, int border)
{

  fprintf(fph,"<FRAME ");
  if ((src != NULL) && (strlen(src) > 0)) fprintf(fph," SRC=%c%s%c ",
						  dq,src,dq);
  
  if ((name != NULL) && (strlen(name) > 0)) fprintf(fph," NAME=%c%s%c ",
						    dq,name,dq);
  
  if ((scroll != NULL) && (strlen(scroll) > 0)) fprintf(fph," SCROLLING=%c%s%c ",
							dq,scroll,dq);
  
  if (!resize_flag) fprintf(fph," NORESIZE ");
  
  fprintf(fph," MARGINWIDTH=%c%d%c MARGINHEIGHT=%c%d%c ",
	  dq,mwidth,dq,
	  dq,mheight,dq);
  fprintf(fph," BORDER=%d ",border);
  
  fprintf(fph,">\n");
}

void ht_put_close_frameset(FILE *fph)
{

    fprintf(fph,"</FRAMESET>\n");
}


void ht_put_content_type(FILE *fph) 
{
  fprintf(fph,"Content-type: text/html%c%c",10,10);
}

void ht_put_a_content_type(FILE *fph, const char *type) 
{
  fprintf(fph,"Content-type: %s%c%c",type,10,10);
}

void ht_put_content_type_target(FILE *fph, char *target) 
{
  fprintf(fph,"Content-type: text/html\n");
  fprintf(fph,"Window-target: %s%c%c",target,10,10);
}


void ht_put_location_type_script(FILE *fph, char *script) 
{
  fprintf(fph,"Location: %s%s%s%c%c",
	 HT_SERVER_URL,
	 HT_CGI_PATH,
	 script,
	 10,10);
}

void ht_put_location_jscript(FILE *fph, char *jscript) 
{
  fprintf(fph,"Location: %s/%s%c%c",
	 HT_SERVER_URL,
	 jscript,
	 10,10);
}

void ht_put_location(FILE *fph, char *ref) 
{
  fprintf(fph,"Location: %s%c%c",
	 ref,
	 10,10);
}

void ht_put_location_on_server(FILE *fph, char *ref) 
{
  fprintf(fph,"Location: %s%s%c%c",
	 HT_SERVER_URL,
	 ref,
	 10,10);
}

void ht_put_title(FILE *fph, char *title)
{
  fprintf(fph,"<HEAD><TITLE>%s</TITLE></HEAD>\n",title);
}

void ht_put_title_w_local_jscripts(FILE *fph, char *title)
{
  fprintf(fph,"<HEAD>\n<TITLE>%s</TITLE>\n",title);
  fprintf(fph,"%s",JSCRIPT_LOCAL_1);
  fprintf(fph,"</HEAD>\n\n");
}


void ht_put_open_body_with_attributes(FILE *fph, const char *bgcolor,  const char *vlink, const char *link, const char *alink)
{
  fprintf(fph,"<BODY bgcolor=\"%s\" vlink=\"%s\" link=\"%s\" alink=\"%s\">\n",
	  bgcolor,vlink,link,alink);
  fprintf(fph,"<BASEFONT SIZE=%d >",HT_FONT_SIZE_BASE);
}

void ht_put_open_body_for_db(FILE *fph, const char *dbnm, const char *dbvr)
{

  if (!strncmp(dbnm,"ndb",3)) {
    fprintf(fph,"<BODY bgcolor=\"#FFFFFF\" vlink=\"#241583\" link=\"#241583\" alink=\"#000033\">\n");
    fprintf(fph,"<BASEFONT SIZE=%d >",HT_FONT_SIZE_BASE);
  } else if (!strncmp(dbnm,"nanmr",5)) {
    fprintf(fph,"<BODY bgcolor=\"#FFFFFF\" vlink=\"#0000ff\" link=\"#0000ff\" alink=\"#000033\">\n");
    fprintf(fph,"<BASEFONT SIZE=%d >",HT_FONT_SIZE_BASE);
  } else if (!strncmp(dbnm,"pfnd",4)) {
    fprintf(fph,"<BODY bgcolor=\"#FFFFFF\" vlink=\"#ff0066\" link=\"#ff0066\" alink=\"#000033\">\n");
    fprintf(fph,"<BASEFONT SIZE=%d >",HT_FONT_SIZE_BASE);
  } else if (!strncmp(dbnm,"dnabind",7)) {
    fprintf(fph,"<BODY bgcolor=\"#FFFFFF\" vlink=\"#006699\" link=\"#006699\" alink=\"#000033\">\n");
    fprintf(fph,"<BASEFONT SIZE=%d >",HT_FONT_SIZE_BASE);
  } else if (!strncmp(dbnm,"ribo",4)) {
    fprintf(fph,"<BODY bgcolor=\"#FFFFFF\" vlink=\"#ff0000\" link=\"#ff0000\" alink=\"#000033\">\n");
    fprintf(fph,"<BASEFONT SIZE=%d >",HT_FONT_SIZE_BASE);
  } else {
    fprintf(fph,"<BODY bgcolor=\"#FFFFFF\" vlink=\"#241583\" link=\"#241583\" alink=\"#000033\">\n");
    fprintf(fph,"<BASEFONT SIZE=%d >",HT_FONT_SIZE_BASE);
  }
}



void ht_put_open_body(FILE *fph)
{
  fprintf(fph,"<BODY>\n");
  fprintf(fph,"<BASEFONT SIZE=%d BGCOLOR=\"#ffffff\">",HT_FONT_SIZE_BASE);
}

void ht_put_close_body(FILE *fph)
{
  fprintf(fph,"</BODY>\n");
}

void ht_put_open_form(FILE *fph, char *script)
{
  fprintf(fph,"<FORM method=POST action=%c%s%s%s%c>\n",
	 dq,
	 HT_SERVER_URL,
	 HT_CGI_PATH,
	 script,dq);
}

void ht_put_submit_reset_form_fancy(FILE *fph, char *label_submit, char *label_reset)
{
  ht_put_open_center(fph);
  fprintf(fph,"<IMG ALIGN=%cbottom%c SRC=%c%s%s%s%c> <INPUT  type=%csubmit%c value=%c%s%c>",
	 dq,dq,
	 dq,HT_SERVER_URL,HT_ICON_PATH,HT_ICON_SUBMIT_FORM,dq,
	 dq,dq,
	 dq,label_submit,dq);
  ht_put_line_break(fph);
  fprintf(fph,"<IMG ALIGN=%cbottom%c SRC=%c%s%s%s%c> <INPUT  type=%creset%c value=%c%s%c>",
	 dq,dq,
	 dq,HT_SERVER_URL,HT_ICON_PATH,HT_ICON_RESET_FORM,dq,
	 dq,dq,
	 dq,label_reset,dq);
  ht_put_close_center(fph);
}


void ht_put_submit_reset_form(FILE *fph, char *label_submit, char *label_reset)
{
  ht_put_open_center(fph);
  fprintf(fph,"<INPUT  type=%csubmit%c value=%c%s%c>",
	 dq,dq,
	 dq,label_submit,dq);
/*   ht_put_line_break(fph);  */
  fprintf(fph,"<INPUT  type=%creset%c value=%c%s%c>",
	 dq,dq,
	 dq,label_reset,dq);
  ht_put_close_center(fph);
}

void ht_put_submit_form(FILE *fph, char *label_submit)
{
  ht_put_open_center(fph);
  fprintf(fph,"<INPUT  type=%csubmit%c value=%c%s%c>",
	 dq,dq,
	 dq,label_submit,dq);
  ht_put_close_center(fph);
}

void ht_put_close_form(FILE *fph)
{
  fprintf(fph,"</FORM>\n");
}

void ht_put_separator(FILE *fph)
{
  ht_put_open_center(fph);
  fprintf(fph,"<IMG SRC=%c%s%s%s%c ALIGN=MIDDLE>\n",
	 dq,
	 HT_SERVER_URL,
	 HT_ICON_PATH,
	 HT_ICON_BAR,
	 dq);
  ht_put_close_center(fph);
}


void ht_put_sf_address(FILE *fph)
{
  fprintf(fph,"<!---                                 Address    ->\n");
  fprintf(fph,"<h5 align=right><a href=\"mailto:ndbadmin@ndbserver.rutgers.edu\"><I>ndbadmin@ndbserver.rutgers.edu</I></a>\n");
  fprintf(fph,"<BR>The Nucleic Acid Database Project<BR>\n");
  fprintf(fph,"Rutgers, The State University of New Jersey</h5>\n");
}

void ht_put_sf_help_address(FILE *fph)
{
  fprintf(fph,"<p align=center>\n");
  fprintf(fph,"Questions or comments about the Structure Finder interface should be sent to \n");
  fprintf(fph,"<a href=\"mailto:ndbadmin@ndbserver.rutgers.edu\"><B>ndbadmin@ndbserver.rutgers.edu</B></a>.\n");
}



void  ht_put_sf_logo_and_navigator(FILE *fph, const char *qfile, const char *dbnm, const char *dbvr, int iflag1)
{
  fprintf(fph,"<TABLE width=500 cellpadding=3>\n");
  fprintf(fph,"<TR>\n");
  fprintf(fph,"<TD VALIGN=TOP NOWRAP><p align=center><img src=\"%s%s\" alt=\"NDB\"></TD>\n",
	  HT_ICON_PATH,HT_ICON_SF_NDB_LOGO);
  fprintf(fph,"<TD  VALIGN=BOTTOM NOWRAP COLSPAN=2>\n");

  ht_put_sf_navigator(fph,qfile,dbnm,dbvr,iflag1);

  fprintf(fph,"</TD></TR></TABLE>\n");
}

static const char *get_short_db_text_name(const char *dbnm, const char *dbvr)
{
  if (!strncmp(dbnm,"ndb",3)) {
    return("NDB");
  } else   if (!strncmp(dbnm,"pfnd",4)) {
    return("Proteins Plus");
  } else   if (!strncmp(dbnm,"dnabind",7)) {
    return("DNA-Binding Proteins");
  } else   if (!strncmp(dbnm,"nanmr",5)) {
    return("NMR");
  } else   if (!strncmp(dbnm,"ribo",4)) {
    return("Ribonuclease");
  } else {
    return("UNKNOWN");
  }
}

void  ht_put_sf_navigator(FILE *fph, const char *qfile, const char *dbnm, const char *dbvr, int iflag1) 
  /*
   *  iflag1 = TRUE then add <dbname> Selection and Report Options
   */
{
  char script1[HT_MAX_NAME_LENGTH];
  fprintf(fph,"<!---                    SF Navigator                          -->\n");
  fprintf(fph,"<h5 align=center>\n");
  fprintf(fph,"<a href=\"/NDB/index.html\">Biological Structure Resource</a> |\n");
  fprintf(fph,"<a href=\"/NDB/ndb.html\">NDB</a> <br>\n");
  fprintf(fph,"<a href=\"/NDB/structure-finder/index.html\">Structure Finder</a> |\n");
  fprintf(fph,"<a href=\"/NDB/structure-finder/%s-%s/index.html\">%s Search</a>\n",
	  dbnm,dbvr,get_short_db_text_name(dbnm,dbvr));
  if (iflag1) {
    sprintf(script1,"%s?%s=%s&%s=%s&%s=%s",
	    HT_SCRIPT_TOP_SF_SCREEN,
	    HT_ATTRIBUTE_QUERY_FILE,
	    qfile,
	    HT_ATTRIBUTE_DATABASE_NAME,
	    dbnm,
	    HT_ATTRIBUTE_DATABASE_VERSION,
	    dbvr);
    fprintf(fph,"<br>|<a href=\"%s%s%s\">Selection and Report Options for %s</a>|\n",
	    HT_SERVER_URL, HT_CGI_PATH,script1,get_short_db_text_name(dbnm,dbvr));
  }
  fprintf(fph,"</h5>\n");
}


void ht_put_ndb_address(FILE *fph)
{
  fprintf(fph,"<BR><BR><BR><BR>\n");
  ht_put_separator(fph);
  ht_put_open_center(fph);
  fprintf(fph,"<CENTER>\n");
  fprintf(fph,"<FONT SIZE=2\n");
  fprintf(fph,"<ADDRESS>\n");
  fprintf(fph,"<BR>\n");
  fprintf(fph,"Nucleic Acid Database Project <BR>\n");
  fprintf(fph,"Rutgers University, Department of Chemistry, \n");
  fprintf(fph,"New Brunswick, New Jersey\n");
  fprintf(fph,"</ADDRESS>\n");
  ht_put_close_center(fph);
}

void ht_put_table_copyright_notice(FILE *fph, char *date)
{
  fprintf(fph,"<BR>\n");
  ht_put_open_center(fph);
  fprintf(fph,"<FONT SIZE=2>\n");
  fprintf(fph,"HTML table created by Structure Finder on %s\n<BR>\n",date);
  fprintf(fph,"&copy; 1996-1998 Nucleic Acid Database Project\n");
  ht_put_close_center(fph);
}

void ht_put_table_copyright_notice_pf(FILE *fph, char *date)
{
  fprintf(fph,"<BR>\n");
  ht_put_open_center(fph);
  fprintf(fph,"<FONT SIZE=2>\n");
  fprintf(fph,"HTML table created by Structure Finder on %s\n<BR>\n",date);
  fprintf(fph,"&copy; 1996-1998 Nucleic Acid Database Project\n");
  ht_put_close_center(fph);
}


void ht_put_header1_text(FILE *fph, char *text)
{
  ht_put_open_center(fph);
  fprintf(fph,"<P><H1>%s</H1>\n",text);
  ht_put_close_center(fph);
}

void ht_put_paragraph_break(FILE *fph)
{
  fprintf(fph,"<P>\n");
}

void ht_put_line_break(FILE *fph)
{
  fprintf(fph,"<BR>\n");
}

void ht_put_text(FILE *fph, char *text)
{
  fprintf(fph,"%s\n",text);
}

void ht_put_centered_text(FILE *fph, char *text)
{
  ht_put_open_center(fph);
  fprintf(fph,"%s\n",text);
  ht_put_close_center(fph);
}

void ht_put_labeled_text(FILE *fph, char *label, char *text)
{
  ht_put_open_center(fph);
  fprintf(fph,"%s <FONT SIZE=%d>%s</FONT>\n",
	 label,
	 HT_FONT_SIZE_NAME,
	 text);
  ht_put_close_center(fph);
}

void ht_put_labeled_text_in_color(FILE *fph, char *label, char *text, char *color)
{
  ht_put_open_center(fph);
  fprintf(fph,"<b>%s</b> <FONT SIZE=%d COLOR=\"%s\">%s</FONT>\n",
	 label,
	 HT_FONT_SIZE_NAME,color,
	 text);
  ht_put_close_center(fph);
}


void ht_put_centered_menu_text(FILE *fph, char *name)
{
/*   fprintf(fph,"<BR>\n"); */
  fprintf(fph,"<CENTER><FONT SIZE=%d>%s</FONT></CENTER>",
	 HT_FONT_SIZE_MENU_NAME,name);
}

void ht_put_centered_menu_file_item(FILE *fph, char *file, char *item)
{
  ht_put_open_center(fph);
  fprintf(fph,"<P><A HREF=%c%s/%s%c><FONT SIZE=%d>%s</FONT></A>",
	 dq,
	 HT_SERVER_URL,
	 file,
	 dq,HT_FONT_SIZE_MENU_ITEM,item);
  ht_put_close_center(fph);
}

void ht_put_anchor_with_label(FILE *fph, char *location, char *item) 
{
 fprintf(fph,"<A HREF=\"%s%s%s\">%s</A>",
	 HT_SERVER_URL, HT_CGI_PATH, location,item);
}

void ht_put_centered_menu_script_item(FILE *fph, char *script, char *item)
{
  ht_put_open_center(fph);
  fprintf(fph,"<P> <A HREF=%c%s%s%s%c><FONT SIZE=%d>%s</FONT></A>",
	 dq,
	 HT_SERVER_URL,
	 HT_CGI_PATH,
	 script,
	 dq,HT_FONT_SIZE_MENU_ITEM,item);
  ht_put_close_center(fph);
}


void ht_put_table_menu_item(FILE *fph, char *qfile, char *dbnm, char *dbvr, char *option, char *name, char *description)
{
  fprintf(fph,"<LI><A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s%c><FONT SIZE=%d><b>%s</b></FONT></A> - %s",
	 dq,
	 HT_SERVER_URL,
	 HT_CGI_PATH,
	 HT_SCRIPT_COLUMN_MENU,
	 HT_ATTRIBUTE_QUERY_FILE,
	 qfile,
	 HT_ATTRIBUTE_DATABASE_NAME,
	 dbnm,
	 HT_ATTRIBUTE_DATABASE_VERSION,
	 dbvr,
	 HT_ATTRIBUTE_OPTION,
	 option,
	 HT_ATTRIBUTE_TABLE_NAME,
	 name,
	 dq,
	 HT_FONT_SIZE_MENU_ITEM,
	 name,
	 description);
}


void ht_put_column_menu_item(FILE *fph, 
			     char *qfile,
			     char *dbnm, 
			     char *dbvr, 
			     char *option,
			     char *table, 
			     char *column, 
			     char *description, 
			     char *examples, 
			     char *data_type)
{
  char *des, *exam;
  if (!strcmp(option,"report")){
    fprintf(fph,"<LI><A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s%c><FONT SIZE=%d><b>%s</b></FONT></A>\n - %s\n <FONT SIZE=%d>(<I>e.g.</I> %s )</FONT>\n",
	   dq,
	   HT_SERVER_URL,
	   HT_CGI_PATH,
	   HT_SCRIPT_ACCUM_REPORT_SELECT,
	   HT_ATTRIBUTE_QUERY_FILE,
	   qfile,
	   HT_ATTRIBUTE_DATABASE_NAME,
	   dbnm,
	   HT_ATTRIBUTE_DATABASE_VERSION,
	   dbvr,
	   HT_ATTRIBUTE_OPTION,
	   option,
	   HT_ATTRIBUTE_TABLE_NAME,
	   table,
	   HT_ATTRIBUTE_COLUMN_NAME,
	   column,
	   HT_ATTRIBUTE_DATA_TYPE,
	   data_type,
	   dq,
	   HT_FONT_SIZE_MENU_ITEM,
	   column,
	   description,
	   HT_FONT_SIZE_ITEM_EXAMPLE,
	   examples);
  } else if (!strcmp(option,"select") || !strcmp(option,"print") ){
    des = (char *) calloc(strlen(description)+1,sizeof(char));
    exam = (char *) calloc(strlen(examples)+1,sizeof(char));
    strcpy(des,description);
    strcpy(exam,examples);
    spacetoplus(des);
    spacetoplus(exam);
    fprintf(fph,"<LI><A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s%c><FONT SIZE=%d><b>%s</b></FONT></A>\n %s\n <FONT SIZE=%d>(<I>e.g.</I> %s)</FONT>\n",
	   dq,
	   HT_SERVER_URL,
	   HT_CGI_PATH,
	   HT_SCRIPT_CONDITION_FORM,
	   HT_ATTRIBUTE_QUERY_FILE,
	   qfile,
	   HT_ATTRIBUTE_DATABASE_NAME,
	   dbnm,
	   HT_ATTRIBUTE_DATABASE_VERSION,
	   dbvr,
	   HT_ATTRIBUTE_OPTION,
	   option,
	   HT_ATTRIBUTE_TABLE_NAME,
	   table,
	   HT_ATTRIBUTE_COLUMN_NAME,
	   column,
	   HT_ATTRIBUTE_DATA_TYPE,
	   data_type,
	   HT_ATTRIBUTE_COLUMN_DESC,
	   des,
	   HT_ATTRIBUTE_COLUMN_EXAM,
	   exam,
	   dq,
	   HT_FONT_SIZE_MENU_ITEM,
	   column,
	   description,
	   HT_FONT_SIZE_ITEM_EXAMPLE,
	   examples);
    free(des);
    free(exam);
  }
}

void ht_put_open_preformat(FILE *fph)
{
  fprintf(fph,"<PRE>\n");
}
void ht_put_close_preformat(FILE *fph)
{
  fprintf(fph,"</PRE>\n");
}

void ht_put_open_definition_list(FILE *fph)
{
  fprintf(fph,"<DL>\n");
}

void ht_put_definition_item(FILE *fph, char *term, char *definition)
{
  fprintf(fph,"<DT> %s <DD> %s\n",term,definition);
}

void ht_put_close_definition_list(FILE *fph)
{
  fprintf(fph,"</DL>\n");
}

void ht_put_open_unordered_list(FILE *fph)
{
  fprintf(fph,"<UL>\n");
}

void ht_put_list_item(FILE *fph, char *item)
{
  fprintf(fph,"<LI> %s\n",item);
}

void ht_put_close_unordered_list(FILE *fph)
{
  fprintf(fph,"</UL>\n");
}



void ht_put_pull_down_selection(FILE *fph, char *label, char *tag, char **items, int nitems)
{
  int i;
  if (nitems < 0 ) return;
  fprintf(fph,"%s  <SELECT name=%c%s%c> \n",
	 label,
	 dq,tag,dq);

  fprintf(fph,"<OPTION SELECTED> %s\n",items[0]);
  for (i = 1; i < nitems; i++) {
    fprintf(fph,"<OPTION> %s\n", items[i]);
  }
  fprintf(fph,"</SELECT> \n");
}

void ht_put_pull_down_ordered_selection(FILE *fph, 
					char *label, 
					char *tag, 
					char **items, 
					int *iorder,
					int nitems)
{
  int i;
  if (nitems < 0 ) return;
  fprintf(fph,"%s  <SELECT name=%c%s%c> \n",
	 label,
	 dq,tag,dq);

  fprintf(fph,"<OPTION SELECTED> %s\n",items[iorder[0]]);
  for (i = 1; i < nitems; i++) {
    fprintf(fph,"<OPTION> %s\n", items[iorder[i]]);
  }
  fprintf(fph,"</SELECT> \n");
}

void ht_put_scrolled_selection(FILE *fph, char *label, char *tag, char **items, 
			      int nitems, int ndisplay)
{
  int i;
  if (nitems < 0 ) return;
  fprintf(fph,"%s  <SELECT NAME=%c%s%c SIZE=%d> \n",
	 label,
	 dq,tag,dq,
	 ndisplay);
  fprintf(fph,"<OPTION SELECTED> %s\n",items[0]);
  for (i = 1; i < nitems; i++) {
    fprintf(fph,"<OPTION> %s\n", items[i]);
  }
  fprintf(fph,"</SELECT> \n");
}


void ht_put_selection_navigator(FILE *fph, 
				char *qfile,
				char *dbnm, 
				char *dbvr,
				char *option,
				char *table,
				int iflag1, 
				int iflag2, 
				int iflag3,
				int iflag4,
				int iflag5)
  /*
   * Navigation options:
   * 
   * Top Menu(qfile)                    -- iflag1
   * Table Menu(qfile,option)           -- iflag2
   * Column Menu(qfile,option,table)    -- iflag3
   * Reset Query(qfile,option)          -- iflag4
   * Execute Query(qfile,option)        -- iflag5
   *
   * These are the two possible navigation lines:
   *
   * <Full Search | Tables | Columns | Reset Selection | Make Selection>
   * <Full Search | Tables | Columns | Reset Report | Make Report>
   */
{
  char string[HT_MAX_LINE_LENGTH],url[HT_MAX_URL_LENGTH];
  if (qfile == NULL ) return;

  memset(string,'\0',HT_MAX_LINE_LENGTH);

  sprintf(string,"<CENTER><b><FONT SIZE=%d>| ",HT_FONT_SIZE_NAVIGATOR);


/*
 * Option: Main Menu 
 */
  if (iflag1) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s%c>Main Menu</A>",
	    dq,
	    HT_SERVER_URL,
	    HT_CGI_PATH,
	    HT_SCRIPT_TOP_QUERY_MENU,
	    HT_ATTRIBUTE_QUERY_FILE,
	    qfile,
	    HT_ATTRIBUTE_DATABASE_NAME,
	    dbnm,
	    HT_ATTRIBUTE_DATABASE_VERSION,
	    dbvr,
	    dq);
    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    strcat(string,url);
    strcat(string," | ");
  }

/*
 * Option: Table Menu 
 */
  if (iflag2) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s%c>Tables</A>",
	    dq,
	    HT_SERVER_URL,
	    HT_CGI_PATH,
	    HT_SCRIPT_TABLE_MENU,
	    HT_ATTRIBUTE_QUERY_FILE,
	    qfile,
	    HT_ATTRIBUTE_DATABASE_NAME,
	    dbnm,
	    HT_ATTRIBUTE_DATABASE_VERSION,
	    dbvr,
	    HT_ATTRIBUTE_OPTION,
	    option,
	    dq);
    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    strcat(string,url);
    strcat(string," | ");
  }

/*
 * Option: Column Menu 
 */
  if (iflag3)  {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s%c>Columns</A>",
	    dq,
	    HT_SERVER_URL,
	    HT_CGI_PATH,
	    HT_SCRIPT_COLUMN_MENU,
	    HT_ATTRIBUTE_QUERY_FILE,
	    qfile,
	    HT_ATTRIBUTE_DATABASE_NAME,
	    dbnm,
	    HT_ATTRIBUTE_DATABASE_VERSION,
	    dbvr,
	    HT_ATTRIBUTE_OPTION,
	    option,
	    HT_ATTRIBUTE_TABLE_NAME,
	    table,	  
	    dq);
    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    strcat(string,url);
    strcat(string," | ");
  }

/*
 * Option: Reset Selection/Report
 */
  if (iflag4) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    if (!strcmp(option,"report") ) {
      sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s%c>Reset Report</A>",
	      dq,
	      HT_SERVER_URL,
	      HT_CGI_PATH,
	      HT_SCRIPT_RESET_QUERY,
	      HT_ATTRIBUTE_QUERY_FILE,
	      qfile,
	      HT_ATTRIBUTE_DATABASE_NAME,
	      dbnm,
	      HT_ATTRIBUTE_DATABASE_VERSION,
	      dbvr,
	      HT_ATTRIBUTE_OPTION,
	      option,
	      dq);
    } else if ( !strcmp(option,"select") || !strcmp(option,"print") ) {
      sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s%c>Reset Selection</A>",
	      dq,
	      HT_SERVER_URL,
	      HT_CGI_PATH,
	      HT_SCRIPT_RESET_QUERY,
	      HT_ATTRIBUTE_QUERY_FILE,
	      qfile,
	      HT_ATTRIBUTE_DATABASE_NAME,
	      dbnm,
	      HT_ATTRIBUTE_DATABASE_VERSION,
	      dbvr,
	      HT_ATTRIBUTE_OPTION,
	      option,
	      dq);
    }
    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    strcat(string,url);
    strcat(string," | ");
  }
/*
 * Option: Make Structure Selection/Report
 */
  if (iflag5) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    if (!strcmp(option,"report")){
      sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s%c>Make Report</A>",
	      dq,
	      HT_SERVER_URL,
	      HT_CGI_PATH,
	      HT_SCRIPT_EXECUTE_QUERY,
	      HT_ATTRIBUTE_QUERY_FILE,
	      qfile,
	      HT_ATTRIBUTE_DATABASE_NAME,
	      dbnm,
	      HT_ATTRIBUTE_DATABASE_VERSION,
	      dbvr,
	      HT_ATTRIBUTE_OPTION,
	      option,
	      HT_ATTRIBUTE_BEGIN_LINE,
	      "1",
	      dq);
    } else if (!strcmp(option,"select") || !strcmp(option,"print") ){
      sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s%c>Make Selection</A>",
	      dq,
	      HT_SERVER_URL,
	      HT_CGI_PATH,
	      HT_SCRIPT_EXECUTE_QUERY,
	      HT_ATTRIBUTE_QUERY_FILE,
	      qfile,
	      HT_ATTRIBUTE_DATABASE_NAME,
	      dbnm,
	      HT_ATTRIBUTE_DATABASE_VERSION,
	      dbvr,
	      HT_ATTRIBUTE_OPTION,
	      option,
	      HT_ATTRIBUTE_BEGIN_LINE,
	      "1",
	      dq);
    }
    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    strcat(string,url);
    strcat(string," | ");
  }

  strcat(string," </FONT></b></CENTER>");
  fprintf(fph,"%s\n",string);
}  

void ht_put_sf_op_navigator(FILE *fph, 
			    const char *qfile,
			    const char *dbnm, 
			    const char *dbvr,
			    const char *option,
			    const char *table,
			    int iflag1, 
			    int iflag2, 
			    int iflag3,
			    int iflag4,
			    int iflag5,
			    int iflag6,
			    int iflag7, int iflag8, int iflag9, int iflag10)
  /*
   * Navigation options:
   * 
   * Full Search (qfile,dbnm,dbvr)                -- iflag1
   * Table Menu(qfile,option,dbnm,dbvr)           -- iflag2
   * Items Menu(qfile,option,table,dbnm,dbvr)     -- iflag3
   * Reset Query(qfile,option,dbnm,dbvr)          -- iflag4
   * Execute Query(qfile,option,dbnm,dbvr)        -- iflag5
   * Full Report (qfile,option,dbnm,dbvr)         -- iflag6
   *
   * Quick Query()                                -- iflag7
   * Quick Report(qfile,option,dbnm,dbvr)         -- iflag8
   * Status Query()                               -- iflag9
   * Update Query()                               -- iflag10
   *
   * These are the two possible navigation lines:
   *
   * <Full Search | Tables | Items | Reset Selection | Execute Search>
   * <Full Search | Tables | Items | Reset Report    | Full Report | Quick Report>
   */
{
  char string[HT_MAX_LINE_LENGTH],url[HT_MAX_URL_LENGTH];
  if (qfile == NULL ) return;

  
  if (!strncmp(dbnm,"nanmr",5)) {
    iflag1=0;
    iflag4=0;
    iflag6=0;
    iflag7 = 1;
  }

  memset(string,'\0',HT_MAX_LINE_LENGTH);

  sprintf(string,"<CENTER><b><FONT SIZE=%d>| ",HT_FONT_SIZE_NAVIGATOR);


/*
 * Option: Full Search  
 */
  if (iflag1) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s%c>Full Search</A>",
	    dq,
	    HT_SERVER_URL,
	    HT_CGI_PATH,
	    HT_SCRIPT_TOP_SF_SCREEN,
	    HT_ATTRIBUTE_QUERY_FILE,
	    qfile,
	    HT_ATTRIBUTE_DATABASE_NAME,
	    dbnm,
	    HT_ATTRIBUTE_DATABASE_VERSION,
	    dbvr,
	    dq);
    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    strcat(string,url);
    strcat(string," | ");
  }

  if (iflag7) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    sprintf(url,"<a href=\"/NDB/structure-finder/%s-%s/quick-query.html\">Quick Search</a>\n",dbnm,dbvr);
    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    strcat(string,url);
    strcat(string," | ");
  }


  if (iflag9) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    sprintf(url,"<a href=\"/NDB/structure-finder/%s-%s/status-query.html\">Status Search</a>\n",dbnm,dbvr);
    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    strcat(string,url);
    strcat(string," | ");
  }

  if (iflag10) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    sprintf(url,"<a href=\"/NDB/structure-finder/%s-%s/update.html\">Release Report</a>\n",dbnm,dbvr);
    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    strcat(string,url);
    strcat(string," | ");
  }



/*
 * Option: Table Menu 
 */
  if (iflag2) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s%c>Tables</A>",
	    dq,
	    HT_SERVER_URL,
	    HT_CGI_PATH,
	    HT_SCRIPT_TABLE_MENU,
	    HT_ATTRIBUTE_QUERY_FILE,
	    qfile,
	    HT_ATTRIBUTE_DATABASE_NAME,
	    dbnm,
	    HT_ATTRIBUTE_DATABASE_VERSION,
	    dbvr,
	    HT_ATTRIBUTE_OPTION,
	    option,
	    dq);
    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    strcat(string,url);
    strcat(string," | ");
  }

/*
 * Option: Item Menu 
 */
  if (iflag3)  {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s%c>Items</A>",
	    dq,
	    HT_SERVER_URL,
	    HT_CGI_PATH,
	    HT_SCRIPT_COLUMN_MENU,
	    HT_ATTRIBUTE_QUERY_FILE,
	    qfile,
	    HT_ATTRIBUTE_DATABASE_NAME,
	    dbnm,
	    HT_ATTRIBUTE_DATABASE_VERSION,
	    dbvr,
	    HT_ATTRIBUTE_OPTION,
	    option,
	    HT_ATTRIBUTE_TABLE_NAME,
	    table,	  
	    dq);
    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    strcat(string,url);
    strcat(string," | ");
  }

/*
 * Option: Reset Selection and Report
 */
  if (iflag4) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    if (!strcmp(option,"report") ) {
      sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s%c>Reset Report</A>",
	      dq,
	      HT_SERVER_URL,
	      HT_CGI_PATH,
	      HT_SCRIPT_RESET_QUERY,
	      HT_ATTRIBUTE_QUERY_FILE,
	      qfile,
	      HT_ATTRIBUTE_DATABASE_NAME,
	      dbnm,
	      HT_ATTRIBUTE_DATABASE_VERSION,
	      dbvr,
	      HT_ATTRIBUTE_OPTION,
	      option,
	      dq);
    } else if (!strcmp(option,"select") || !strcmp(option,"print")) {
      sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s%c>Reset Selection</A>",
	      dq,
	      HT_SERVER_URL,
	      HT_CGI_PATH,
	      HT_SCRIPT_RESET_QUERY,
	      HT_ATTRIBUTE_QUERY_FILE,
	      qfile,
	      HT_ATTRIBUTE_DATABASE_NAME,
	      dbnm,
	      HT_ATTRIBUTE_DATABASE_VERSION,
	      dbvr,
	      HT_ATTRIBUTE_OPTION,
	      option,
	      dq);
    }
    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    strcat(string,url);
    strcat(string," | ");
  }
/*
 * Option: Display Report
 */
  if (iflag5) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    if (!strcmp(option,"report")){
      sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s%c>Display Report</A>",
	      dq,
	      HT_SERVER_URL,
	      HT_CGI_PATH,
	      HT_SCRIPT_EXECUTE_QUERY,
	      HT_ATTRIBUTE_QUERY_FILE,
	      qfile,
	      HT_ATTRIBUTE_DATABASE_NAME,
	      dbnm,
	      HT_ATTRIBUTE_DATABASE_VERSION,
	      dbvr,
	      HT_ATTRIBUTE_OPTION,
	      option,
	      HT_ATTRIBUTE_BEGIN_LINE,
	      "1",
	      dq);
    } else if (!strcmp(option,"select") || !strcmp(option,"print")){
      if (iflag1) {
	sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s%c>Search Results</A>",
		dq,
		HT_SERVER_URL,
		HT_CGI_PATH,
		HT_SCRIPT_EXECUTE_QUERY,
		HT_ATTRIBUTE_QUERY_FILE,
		qfile,
		HT_ATTRIBUTE_DATABASE_NAME,
		dbnm,
		HT_ATTRIBUTE_DATABASE_VERSION,
		dbvr,
		HT_ATTRIBUTE_OPTION,
		option,
		HT_ATTRIBUTE_BEGIN_LINE,
		"1",
		dq);
      } else {
	sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s%c>Search Results</A>",
		dq,
		HT_SERVER_URL,
		HT_CGI_PATH,
		HT_SCRIPT_EXECUTE_QUERY,
		HT_ATTRIBUTE_QUERY_FILE,
		qfile,
		HT_ATTRIBUTE_DATABASE_NAME,
		dbnm,
		HT_ATTRIBUTE_DATABASE_VERSION,
		dbvr,
		HT_ATTRIBUTE_OPTION,
		option,
		HT_ATTRIBUTE_BEGIN_LINE,
		"1",
		HT_ATTRIBUTE_REPORT_NAME,
		"quick",
		dq);
      }
    }
    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    strcat(string,url);
    strcat(string," | ");
  }

/*
 * Option: Full Report
 */
  if (iflag6) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s%c>Full Report</A>",
	    dq,
	    HT_SERVER_URL,
	    HT_CGI_PATH,
	    HT_SCRIPT_TABLE_MENU,
	    HT_ATTRIBUTE_QUERY_FILE,
	    qfile,
	    HT_ATTRIBUTE_DATABASE_NAME,
	    dbnm,
	    HT_ATTRIBUTE_DATABASE_VERSION,
	    dbvr,
	    HT_ATTRIBUTE_OPTION,
	    "report",
	    dq);
    strcat(string,url);
    strcat(string," | ");
  }

/*
 * Option: Quick Report
 */
  if (iflag8) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s%c>Quick Report</A>",
	    dq,
	    HT_SERVER_URL,
	    HT_CGI_PATH,
	    HT_SCRIPT_REPORT_MENU,
	    HT_ATTRIBUTE_QUERY_FILE,
	    qfile,
	    HT_ATTRIBUTE_DATABASE_NAME,
	    dbnm,
	    HT_ATTRIBUTE_DATABASE_VERSION,
	    dbvr,
	    HT_ATTRIBUTE_OPTION,
	    "report",
	    dq);
    strcat(string,url);
    strcat(string," | ");
  }


  strcat(string," </FONT></b></CENTER>");
  fprintf(fph,"%s\n",string);
}  

void ht_init_htstate(HTSTATE *ht) {
  strcpy(ht->qfile,"");
  strcpy(ht->dbnm,"");
  strcpy(ht->dbvr,"");
  strcpy(ht->table,"");
  strcpy(ht->ppid,"");
  strcpy(ht->pdbid,"");
  strcpy(ht->page,"");
  ht->iflag1 = ht->iflag2 = ht->iflag3 = ht->iflag4 = ht->iflag5  = 0;
  ht->iflag6 = ht->iflag7 = ht->iflag8 = ht->iflag9 = ht->iflag10 = 0;
}

void ht_put_msd_op_navigator(FILE *fph,  HTSTATE ht)
  /*
   * Navigation options:
   * 
   * Full Search                   -- ht.iflag1
   * Table Menu                    -- ht.iflag2
   * Items Menu                    -- ht.iflag3
   * Reset Query                   -- ht.iflag4
   * Execute Query/Display report  -- ht.iflag5
   * Full Report                   -- ht.iflag6
   *
   * Quick Query()                 -- ht.iflag7
   * Quick Report()                -- ht.iflag8
   * Status Query()                -- ht.iflag9
   * Update Query()                -- ht.iflag10
   *
   * These are the two possible navigation lines:
   *
   * <Full Search | Tables | Items | Reset Selection | Execute Search>
   * <Full Search | Tables | Items | Reset Report    | Full Report | Quick Report>
   */
{
  char string[HT_MAX_LINE_LENGTH],url[HT_MAX_URL_LENGTH];
  char qppid[15];

  strcpy(qppid,"");
  if (ht.ppid !=NULL && strlen(ht.ppid) > 0 ) strcpy(qppid,ht.ppid);
  if (!strcmp(ht.qfile, "")) return;

  ht.iflag6 = 0;

  if (!strncmp(ht.dbnm,"nanmr",5)) {
    ht.iflag1=0;
    ht.iflag4=0;
    ht.iflag6=0;
    ht.iflag7 = 1;
  }

  memset(string,'\0',HT_MAX_LINE_LENGTH);

  sprintf(string,"<CENTER><b><FONT SIZE=%d>| ",HT_FONT_SIZE_NAVIGATOR);


/*
 * Option: Full Search  
 */
  if (ht.iflag1) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    //    sprintf(url,"<A HREF=\"http://www.rcsb.org/msd/cgi/queryForm.cgi?ndb=1\" target=\"bottomFrame\">MSD Search</A>");
    //    sprintf(url,"<A HREF=\"http://www.rcsb.org/docs/msd-search.html?%s\" target=\"bottomFrame\">MSD Search</A>",
    //	    qppid);

      
    //    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    //strcat(string,url);
    //strcat(string," | ");

    if (!strcmp(ht.option,"report")) {

      if ( strlen(ht.pdbid) > 0) {
	memset(url,'\0',HT_MAX_URL_LENGTH);
	sprintf(url,"<A HREF=\"http://www.rcsb.org/msd/explore.html?%s=%s&%s=%s&%s=%s\">MSD Results</A>",
		HT_ATTRIBUTE_MSD_PPID,
		qppid,
		HT_ATTRIBUTE_MSD_PAGE,
		ht.page,
		HT_ATTRIBUTE_MSD_PDBID,
		ht.pdbid);
      } else {
	memset(url,'\0',HT_MAX_URL_LENGTH);
	sprintf(url,"<A HREF=\"http://www.rcsb.org/msd/cgi/resultBrowser.cgi?%s=%s&%s=%s\">MSD Results</A>",
		HT_ATTRIBUTE_MSD_PPID,
		qppid,
		HT_ATTRIBUTE_MSD_PAGE,
		ht.page);
      }

      strcat(string,url);
      strcat(string," | ");
    }
  }



  if (ht.iflag7) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    sprintf(url,"<a href=\"/NDB/structure-finder/%s-%s/quick-query.html\">Quick Search</a>\n",ht.dbnm,ht.dbvr);
    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    strcat(string,url);
    strcat(string," | ");
  }


  if (ht.iflag9) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    sprintf(url,"<a href=\"/NDB/structure-finder/%s-%s/status-query.html\">Status Search</a>\n",ht.dbnm,ht.dbvr);
    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    strcat(string,url);
    strcat(string," | ");
  }

  if (ht.iflag10) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    sprintf(url,"<a href=\"/NDB/structure-finder/%s-%s/update.html\">Release Report</a>\n",ht.dbnm,ht.dbvr);
    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    strcat(string,url);
    strcat(string," | ");
  }



/*
 * Option: Table Menu 
 */
  if (ht.iflag2) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s%c>Tables</A>",
	    dq,
	    HT_SERVER_URL,
	    HT_CGI_PATH,
	    HT_SCRIPT_TABLE_MENU,
	    HT_ATTRIBUTE_QUERY_FILE,
	    ht.qfile,
	    HT_ATTRIBUTE_DATABASE_NAME,
	    ht.dbnm,
	    HT_ATTRIBUTE_DATABASE_VERSION,
	    ht.dbvr,
	    HT_ATTRIBUTE_OPTION,
	    ht.option,
	    dq);
    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    strcat(string,url);
    strcat(string," | ");
  }

/*
 * Option: Item Menu 
 */
  if (ht.iflag3)  {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s%c>Items</A>",
	    dq,
	    HT_SERVER_URL,
	    HT_CGI_PATH,
	    HT_SCRIPT_COLUMN_MENU,
	    HT_ATTRIBUTE_QUERY_FILE,
	    ht.qfile,
	    HT_ATTRIBUTE_DATABASE_NAME,
	    ht.dbnm,
	    HT_ATTRIBUTE_DATABASE_VERSION,
	    ht.dbvr,
	    HT_ATTRIBUTE_OPTION,
	    ht.option,
	    HT_ATTRIBUTE_TABLE_NAME,
	    ht.table,	  
	    dq);
    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    strcat(string,url);
    strcat(string," | ");
  }

/*
 * Option: Reset Selection and Report
 */
  if (ht.iflag4) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    if (!strcmp(ht.option,"report") ) {
      sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s%c>Reset Report</A>",
	      dq,
	      HT_SERVER_URL,
	      HT_CGI_PATH,
	      HT_SCRIPT_RESET_QUERY,
	      HT_ATTRIBUTE_QUERY_FILE,
	      ht.qfile,
	      HT_ATTRIBUTE_DATABASE_NAME,
	      ht.dbnm,
	      HT_ATTRIBUTE_DATABASE_VERSION,
	      ht.dbvr,
	      HT_ATTRIBUTE_OPTION,
	      ht.option,
	      dq);
    } else if (!strcmp(ht.option,"select") || !strcmp(ht.option,"print") ) {
      sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s%c>Reset Selection</A>",
	      dq,
	      HT_SERVER_URL,
	      HT_CGI_PATH,
	      HT_SCRIPT_RESET_QUERY,
	      HT_ATTRIBUTE_QUERY_FILE,
	      ht.qfile,
	      HT_ATTRIBUTE_DATABASE_NAME,
	      ht.dbnm,
	      HT_ATTRIBUTE_DATABASE_VERSION,
	      ht.dbvr,
	      HT_ATTRIBUTE_OPTION,
	      ht.option,
	      dq);
    }
    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    strcat(string,url);
    strcat(string," | ");
  }
/*
 * Option: Display Report
 */
  if (ht.iflag5) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    if (!strcmp(ht.option,"report")){
      sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s%c>Display Report</A>",
	      dq,
	      HT_SERVER_URL,
	      HT_CGI_PATH,
	      HT_SCRIPT_EXECUTE_QUERY,
	      HT_ATTRIBUTE_QUERY_FILE,
	      ht.qfile,
	      HT_ATTRIBUTE_DATABASE_NAME,
	      ht.dbnm,
	      HT_ATTRIBUTE_DATABASE_VERSION,
	      ht.dbvr,
	      HT_ATTRIBUTE_OPTION,
	      ht.option,
	      HT_ATTRIBUTE_BEGIN_LINE,
	      "1",
	      dq);
    } else if (!strcmp(ht.option,"select") ){
      if (ht.iflag1) {
	sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s%c>Search Results</A>",
		dq,
		HT_SERVER_URL,
		HT_CGI_PATH,
		HT_SCRIPT_EXECUTE_QUERY,
		HT_ATTRIBUTE_QUERY_FILE,
		ht.qfile,
		HT_ATTRIBUTE_DATABASE_NAME,
		ht.dbnm,
		HT_ATTRIBUTE_DATABASE_VERSION,
		ht.dbvr,
		HT_ATTRIBUTE_OPTION,
		ht.option,
		HT_ATTRIBUTE_BEGIN_LINE,
		"1",
		dq);
      } else {
	sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s%c>Search Results</A>",
		dq,
		HT_SERVER_URL,
		HT_CGI_PATH,
		HT_SCRIPT_EXECUTE_QUERY,
		HT_ATTRIBUTE_QUERY_FILE,
		ht.qfile,
		HT_ATTRIBUTE_DATABASE_NAME,
		ht.dbnm,
		HT_ATTRIBUTE_DATABASE_VERSION,
		ht.dbvr,
		HT_ATTRIBUTE_OPTION,
		ht.option,
		HT_ATTRIBUTE_BEGIN_LINE,
		"1",
		HT_ATTRIBUTE_REPORT_NAME,
		"quick",
		dq);
      }
    } else if (!strcmp(ht.option,"print") ){
      if (ht.iflag1) {
	sprintf(url,"<A HREF=%chttp://www.rcsb.org/msd/cgi/query.cgi?ndb=1&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s%c target=\"bottomFrame\">Search Results</A>",
		dq,
		HT_ATTRIBUTE_MSD_PPID,
		qppid,
		HT_ATTRIBUTE_MSD_PAGE,
		ht.page,
		HT_ATTRIBUTE_QUERY_FILE,
		ht.qfile,
		HT_ATTRIBUTE_DATABASE_NAME,
		ht.dbnm,
		HT_ATTRIBUTE_DATABASE_VERSION,
		ht.dbvr,
		HT_ATTRIBUTE_OPTION,
		ht.option,
		HT_ATTRIBUTE_BEGIN_LINE,
		"1",
		dq);
      } else {
	sprintf(url,"<A HREF=%chttp://www.rcsb.org/msd/cgi/query.cgi?ndb=1&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s%c target=\"bottomFrame\">Search Results</A>",
		dq,
		HT_ATTRIBUTE_MSD_PPID,
		qppid,
		HT_ATTRIBUTE_MSD_PAGE,
		ht.page,
		HT_ATTRIBUTE_QUERY_FILE,
		ht.qfile,
		HT_ATTRIBUTE_DATABASE_NAME,
		ht.dbnm,
		HT_ATTRIBUTE_DATABASE_VERSION,
		ht.dbvr,
		HT_ATTRIBUTE_OPTION,
		ht.option,
		HT_ATTRIBUTE_BEGIN_LINE,
		"1",
		HT_ATTRIBUTE_REPORT_NAME,
		"quick",
		dq);
      }
    }

    ndb_log_message(NDB_MSG_DEBUG,"URL %s",url);
    strcat(string,url);
    strcat(string," | ");
  }

/*
 * Option: Full Report
 */
  if (ht.iflag6) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s%c>Full Report</A>",
	    dq,
	    HT_SERVER_URL,
	    HT_CGI_PATH,
	    HT_SCRIPT_TABLE_MENU,
	    HT_ATTRIBUTE_QUERY_FILE,
	    ht.qfile,
	    HT_ATTRIBUTE_DATABASE_NAME,
	    ht.dbnm,
	    HT_ATTRIBUTE_DATABASE_VERSION,
	    ht.dbvr,
	    HT_ATTRIBUTE_OPTION,
	    "report",
	    dq);
    strcat(string,url);
    strcat(string," | ");
  }

/*
 * Option: Quick Report
 */
  if (ht.iflag8) {
    memset(url,'\0',HT_MAX_URL_LENGTH);
    sprintf(url,"<A HREF=%c%s%s%s?%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s&%s=%s%c>Quick Report</A>",
	    dq,
	    HT_SERVER_URL,
	    HT_CGI_PATH,
	    HT_SCRIPT_REPORT_MENU,
	    HT_ATTRIBUTE_QUERY_FILE,
	    ht.qfile,
	    HT_ATTRIBUTE_DATABASE_NAME,
	    ht.dbnm,
	    HT_ATTRIBUTE_DATABASE_VERSION,
	    ht.dbvr,
	    HT_ATTRIBUTE_OPTION,
	    "report",
		HT_ATTRIBUTE_MSD_PPID,
		qppid,
		HT_ATTRIBUTE_MSD_PAGE,
		ht.page,
		HT_ATTRIBUTE_MSD_PDBID,
		ht.pdbid,

	    dq);
    strcat(string,url);
    strcat(string," | ");
  }


  strcat(string," </FONT></b></CENTER>");
  fprintf(fph,"%s\n",string);
}  


void ht_put_home_page_navigator(FILE *fph, char *home_page_path)
/*
 */
{
  char string[HT_MAX_LINE_LENGTH],url[HT_MAX_URL_LENGTH];

  memset(string,'\0',HT_MAX_LINE_LENGTH);

  sprintf(string,"<CENTER><FONT SIZE=%d>| ",HT_FONT_SIZE_NAVIGATOR);

  memset(url,'\0',HT_MAX_URL_LENGTH);
  sprintf(url,"<A HREF=%c%s/%s%c>Nucleic Acid Database Home Page</A>",
	  dq,
	  HT_SERVER_URL,
	  home_page_path,
	  dq);
  strcat(string,url);
  strcat(string," | ");

  strcat(string," </FONT></b></CENTER>");
  fprintf(fph,"%s\n",string);
}  


void ht_put_open_center(FILE *fph )
{
  fprintf(fph,"<CENTER>\n");
}

void ht_put_close_center(FILE *fph)
{
  fprintf(fph,"</CENTER>\n");
}

void ht_put_hidden_form_item(FILE *fph, char *name, char *value)
{
  fprintf(fph,"<INPUT type=%chidden%c name=%c%s%c     value=%c%s%c>\n",
	 dq,dq,dq,name,dq,dq,value,dq);
}

void ht_put_visible_form_item(FILE *fph, char *label, char *name, int size)
{
  fprintf(fph,"%s  <INPUT size=%c%d%c     name=%c%s%c>\n",label,dq,size,dq,dq,name,dq); 
}

void ht_put_visible_form_item_default(FILE *fph, char *label, char *name, int size, char *value)
{
  fprintf(fph,"%s  <INPUT size=%c%d%c name=%c%s%c value=%c%s%c>\n",
	 label,dq,size,dq,dq,name,dq,dq,value,dq); 
}

void ht_put_open_table(FILE *fph)
{
  fprintf(fph,"<TABLE BORDER CELLPADDING=3>\n");
}

void ht_put_close_table(FILE *fph)
{
  fprintf(fph,"</TABLE>\n");
}

void ht_put_open_row(FILE *fph)
{
  fprintf(fph,"<TR>\n");
}

void ht_put_close_row(FILE *fph)
{
  fprintf(fph,"</TR>\n");
}

void ht_put_begin_font(FILE *fph, int font_size)
{
  fprintf(fph,"<FONT SIZE=%d>\n",font_size);
}

void ht_put_end_font(FILE *fph)
{
  fprintf(fph,"</FONT>\n");
}

void ht_put_table_column_header_cj(FILE *fph, char *text)
{
  fprintf(fph,"<TH ALIGN=CENTER VALIGN=MIDDLE><FONT SIZE=%d>%s</FONT></TH>\n",
	 HT_FONT_SIZE_TABLE_HEADER,text);
}

void ht_put_table_column_header_lj(FILE *fph, char *text)
{
  fprintf(fph,"<TH ALIGN=LEFT VALIGN=MIDDLE><FONT SIZE=%d>%s</FONT></TH>\n",
	 HT_FONT_SIZE_TABLE_HEADER,text);
}

void ht_put_table_column_data_cj(FILE *fph, char *data)
{
  fprintf(fph,"<TD ALIGN=CENTER VALIGN=MIDDLE><FONT SIZE=%d>%s</FONT></TD>\n",
	 HT_FONT_SIZE_TABLE_DATA,data);
}

void ht_put_table_column_data_lj(FILE *fph, char *data)
{
  fprintf(fph,"<TD ALIGN=LEFT VALIGN=MIDDLE><FONT SIZE=%d>%s</FONT></TD>\n",
	 HT_FONT_SIZE_TABLE_DATA,data);
}


void getword(char *word, char *line, char stop) 
{
    int x = 0,y;

    for(x=0;((line[x]) && (line[x] != stop));x++)
        word[x] = line[x];

    word[x] = '\0';
    if(line[x]) ++x;
    y=0;

    while((line[y++] = line[x++]));
}

char *makeword(char *line, char stop) 
{
    int x = 0,y;
    char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));

    for(x=0;((line[x]) && (line[x] != stop));x++)
        word[x] = line[x];

    word[x] = '\0';
    if(line[x]) ++x;
    y=0;

    while((line[y++] = line[x++]));
    return word;
}

char *fmakeword(FILE *f, char stop, int *cl) 
{
    int wsize;
    char *word;
    int ll;

    wsize = 102400;
    ll=0;
    word = (char *) malloc(sizeof(char) * (wsize + 1));

    while(1) {
        word[ll] = (char)fgetc(f);
        if(ll==wsize) {
            word[ll+1] = '\0';
            wsize+=102400;
            word = (char *)realloc(word,sizeof(char)*(wsize+1));
        }
        --(*cl);
        if((word[ll] == stop) || (feof(f)) || (!(*cl))) {
            if(word[ll] != stop) ll++;
            word[ll] = '\0';
            return word;
        }
        ++ll;
    }
}

char x2c(char *what) 
{
    register char digit;

    digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
    digit *= 16;
    digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
    return(digit);
}

void unescape_url(char *url) 
{
    register int x,y;

    for(x=0,y=0;url[y];++x,++y) {
        if((url[x] = url[y]) == '%') {
            url[x] = x2c(&url[y+1]);
            y+=2;
        }
    }
    url[x] = '\0';
}

void plustospace(char *str) 
{
    register int x;

    for(x=0;str[x];x++) if(str[x] == '+') str[x] = ' ';
}

void spacetoplus(char *str) 
{
    register int x;

    for(x=0;str[x];x++) if(str[x] == ' ') str[x] = '+';
}

void controltospace(char *str) 
{
    register int x;
    for(x=0;str[x];x++) {
      if (str[x] > 31 || str[x] == 10) continue;
      str[x] = ' ';
    }
}

int rind(char *s, char c) 
{
    register int x;
    for(x=strlen(s) - 1;x != -1; x--)
        if(s[x] == c) return x;
    return -1;
}

int getline(char *s, int n, FILE *f) 
{
    register int i=0;

    while(1) {
        s[i] = (char)fgetc(f);

        if(s[i] == CR)
            s[i] = fgetc(f);

        if((s[i] == 0x4) || (s[i] == LF) || (i == (n-1))) {
            s[i] = '\0';
            return (feof(f) ? 1 : 0);
        }
        ++i;
    }
}

void send_fd(FILE *f, FILE *fd)
{
    char c;

    while (1) {
        c = fgetc(f);
        if(feof(f))
            return;
        fputc(c,fd);
    }
}

int ind(char *s, char c) 
{
    register int x;

    for(x=0;s[x];x++)
        if(s[x] == c) return x;

    return -1;
}

void escape_shell_cmd(char *cmd) 
{
    register int x,y,l;
    char buffer[20];

    strcpy(buffer, "&;`'\"|*?~<>^()[]{}$\\");
    l=strlen(cmd);
    for(x=0;cmd[x];x++) {
        if(ind(buffer, cmd[x]) != -1){
            for(y=l+1;y>x;y--)
                cmd[y] = cmd[y-1];
            l++; /* length has been increased */
            cmd[x] = '\\';
            x++; /* skip the character */
        }
    }
}


void ht_strip_nl(char *string)
{
   int i;
   i = strlen(string);
   if (string[i-1] == '\n') string[i-1] = '\0';
}


char *ht_get_unique_fid(void)
{
   char *rhost=NULL, *fid=NULL, unk[] = "Session", *clean=NULL;
   pid_t pid;
   int i,j,len;

   rhost = getenv("REMOTE_HOST");
   pid = getpid();
   if (rhost != NULL ) 
     ndb_log_message(NDB_MSG_INFO,"Remote host is %s\n",rhost);
   else
     ndb_log_message(NDB_MSG_INFO,"Cannot get remote host name.");

   if (rhost != NULL) {
     fid = (char *) calloc(strlen(rhost)+50,sizeof(char));
     sprintf(fid,"%s%s.%d",HT_TMP_DIR,rhost,pid);
   } else {
     fid = (char *) calloc(strlen(unk)+50,sizeof(char));
     sprintf(fid,"%s%s.%d",HT_TMP_DIR,unk,pid);
   }
   
   clean = (char *) calloc(strlen(fid)+1,sizeof(char));
   j=0;
   len = strlen(fid); 
   for (i=0; i < len; i++ ) {
     if (isprint(fid[i]) && !isspace(fid[i])) {
       clean[j] = fid[i]; 
       j++;
     }
   }
   clean[j]='\0';
   return(clean);
}


char *ht_get_unique_name(void)
{
   char *rhost=NULL, *fid, unk[] = "Session";
   pid_t pid;

   rhost = getenv("REMOTE_HOST");
   pid = getpid();
   if (rhost != NULL ) 
     ndb_log_message(NDB_MSG_INFO,"Remote host is %s\n",rhost);
   else
     ndb_log_message(NDB_MSG_INFO,"Cannot get remote host name.");

   if (rhost != NULL) {
     fid = (char *) calloc(strlen(rhost)+10,sizeof(char));
     sprintf(fid,"%s.%d",rhost,pid);
   } else {
     fid = (char *) calloc(strlen(unk)+10,sizeof(char));
     sprintf(fid,"%s.%d",unk,pid);
   }
   return(fid);

}


char *ht_get_unique_name_cluster(void)
{
   char *rhost=NULL, *fid, unk[] = "Session";
   char *srv=NULL, *port=NULL;
   char uSrv[] = "localhost", uPort[]="80";
   pid_t pid;

   rhost = getenv("REMOTE_HOST");
   srv   = getenv("SERVER_NAME");
   port  = getenv("SERVER_PORT");

   pid = getpid();
   if (rhost != NULL ) 
     ndb_log_message(NDB_MSG_INFO,"Remote host is %s\n",rhost);
   else
     ndb_log_message(NDB_MSG_INFO,"Cannot get remote host name.");



   if (rhost != NULL) {

     if (srv != NULL && port != NULL) {
       fid = (char *) calloc(strlen(rhost)+strlen(srv)+strlen(port)+10,sizeof(char));
       sprintf(fid,"%s.%s.%s.%d",srv,port,rhost,pid);
     } else {
       fid = (char *) calloc(strlen(rhost)+strlen(uSrv)+strlen(uPort)+10,sizeof(char));
       sprintf(fid,"%s.%s.%s.%d",uSrv,uPort,rhost,pid);
     }

   } else {
     fid = (char *) calloc(strlen(unk)+strlen(uSrv)+strlen(uPort)+10,sizeof(char));
     sprintf(fid,"%s.%s.%s.%d",uSrv,uPort,unk,pid);
   }


   return(fid);

}

int ht_decode_multipart_form_data(entry *entries, const char *path)
{
  int  c,  i, j, ibeg;
  char *contentType=NULL, *sp;
  char boundary[50];
  int lenCT, lenData=0;

  int numEntries = 0;

  FILE *fp=NULL;
  char tfile[HT_MAX_NAME_LENGTH];

  int bufLen, isCompressed;
  char *bufp, *buf, *cp0, *cp1, *cp2, *cpN, *datap=NULL;
  char contDisp[HT_MAX_LINE_LENGTH], contType[HT_MAX_LINE_LENGTH];
  char     name[HT_MAX_NAME_LENGTH],  fileName[HT_MAX_NAME_LENGTH];

  ndb_log_message_text(NDB_MSG_DEBUG,"Entering ht_post_multipart_form_data");
  ht_check_post_request();
  /*
   *  Verify "content_type"  and get MIME "boundary" string.
   */
  if (strncmp(getenv("CONTENT_TYPE"),"multipart/form-data",19)) {
    ndb_log_message_text(NDB_MSG_ERR,"ht_decode_multipart_form_data: Wrong CONTENT_TYPE %s",
		    getenv("CONTENT_TYPE"));
    return(0);
  }
  isCompressed = 0;
  lenCT = strlen(getenv("CONTENT_TYPE"));
  contentType=(char *) calloc(lenCT+1,sizeof(char));
  strcpy(contentType,getenv("CONTENT_TYPE"));
  ndb_log_message_text(NDB_MSG_DEBUG,"Content Type[%d] is %s\n", lenCT,contentType);


  for (i=0, sp = &contentType[0], ibeg=-1; i < lenCT; i++) {
    if (!strncmp(sp,"boundary=",9)) {
      ibeg = i; break;
    }
    sp++;
  }
  ndb_log_message_text(NDB_MSG_DEBUG,"ht_decode_multipart_form_data: ibeg= %d boundary[Len=%d] (%s)",
		       ibeg, strlen(sp), sp);

  if (ibeg > 0 && ibeg < ((int) strlen(contentType) - 9)) {
    sp+=9;
    memset(boundary,0,50);
    strcpy(boundary,"--");  /* prefix boundary string with "--"  */
    strncat(boundary, sp , 49);
    ndb_log_message_text(NDB_MSG_DEBUG,"ht_decode_multipart_form_data: Using boundary[Len=%d] %s",
		    strlen(boundary),boundary);
  } else {
    ndb_log_message_text(NDB_MSG_ERR,"ht_decode_multipart_form_data: no boundary string");
    return(0);
  }

  bufLen = atoi(getenv("CONTENT_LENGTH"));
  ndb_log_message_text(NDB_MSG_DEBUG,"ht_decode_multipart_form_data: CONTENT LENGTH %d\n",bufLen); 
  if (bufLen > HT_MAX_UPLOAD_BYTES) {
    ndb_log_message_text(NDB_MSG_DEBUG,"ht_decode_multipart_form_data: Upload %d exceeds %d byte limit",
		    bufLen,HT_MAX_UPLOAD_BYTES); 
    return(0);
  }

  i=0;
  //  fp=fopen("/var/tmp/tmp-UPLOAD.dat","w");
  buf = (char *) calloc(bufLen+1, sizeof(char));
  while ((c=fgetc(stdin)) != EOF  && i < bufLen) {
    buf[i] = c;
    //    fputc(c,fp);
    i++;
  }
  //  fclose(fp);

  ndb_log_message_text(NDB_MSG_DEBUG,"ht_decode_multipart_form_data: Uploaded %d bytes of %d",i,bufLen); 
  if (i !=  bufLen ) {
    ndb_log_message_text(NDB_MSG_ERR,"ht_decode_multipart_form_data: Uploaded failed.");
  }






#if 0
  fp=fopen("/var/tmp/tmp-UPLOAD.dat","w");
  for (i=0; i < bufLen; i++) {
    fputc(buf[i],fp);
  }
  fclose(fp);
#endif

  numEntries = -1;
  for (bufp = &buf[0];  bufp;  bufp++) {
    //    ndb_log_message_text(NDB_MSG_DEBUG,"ht_decode_multipart_form_data: %s", bufp);
    if (!strncmp(bufp,boundary,strlen(boundary))) {
      //      ndb_log_message_text(NDB_MSG_DEBUG,"ht_decode_multipart_form_data: Got here numEntries %d",numEntries);
      if (numEntries != -1 && lenData) {
	if (entries[numEntries].isFile) { 
	  i = strlen(fileName);

	  isCompressed = 0;
	  if (i > 0) { 
	    if ( ( (i > 2 && fileName[i-2] == '.' && fileName[i-1] == 'Z') ) ||
		 ((i > 3 && fileName[i-3] == '.' && fileName[i-2] == 'g' && fileName[i-1] == 'z') )) isCompressed = 1;
	    cp0 = ht_strip_leading_path(fileName);
	    strcpy(tfile,path);
	    strcat(tfile,cp0);
	    ndb_log_message_text(NDB_MSG_DEBUG,"ht_decode_multipart_form_data: copying file to %s",tfile);
	    fp = fopen(tfile,"w");
	    if (fp == NULL) {
	      ndb_log_message_text(NDB_MSG_ERR,"ht_decode_multipart_form_data: Unable to open upload file %s",tfile);
      //	    return(numEntries);
	    }

	    if (isCompressed) {
	      for (cp1 = datap, i=0; i < lenData-2; i++) {
		fputc(*cp1,fp);  
		cp1++;
	      }

	    } else { 
	      for (cp1 = datap, i=0; i < lenData-2; i++) {
		cpN=cp1; cpN++; 
		if ((*cp1 == 13) && (*cpN != 10)) *cp1 = 10;  // convert isolated cr to nl.
		if (*cp1 > 31 || *cp1 == 10 ) {// filter ascii control characters.
		  fputc(*cp1,fp);  
		} else if (*cp1 == 9 || *cp1 > 126) {// filter ascii control characters.
		  fputc(' ',fp);  
		}
		cp1++;
	      }
	    }

	    fclose(fp);
	  }
	} else {
	  entries[numEntries].val = (char *)calloc(lenData+2,sizeof(char));
	  strncpy(entries[numEntries].val, datap,lenData-2);
	  ndb_log_message_text(NDB_MSG_DEBUG,"ht_decode_multipart_form_data: entry=%d name=%s value=%s\n",
			  numEntries,
			  entries[numEntries].name,
			  entries[numEntries].val); 
	}
      }
      lenData = 0;
      numEntries++;
      entries[numEntries].isFile = 0;
      entries[numEntries].name   = (char *)NULL;
      entries[numEntries].val    = (char *)NULL;
      entries[numEntries].file   = (char *)NULL;

      bufp += strlen(boundary); bufp++; bufp++;
      
      for (i = 0, cp1 = bufp; *cp1 && (*cp1 != '\r') ; cp1++) {
	contDisp[i] = *cp1; i++;
      }
      contDisp[i]='\0';
      ndb_log_message_text(NDB_MSG_DEBUG,"ht_decode_multipart_form_data: Content string = %s",contDisp);

      if (strlen(contDisp) == 0) {
	break;
      }

      for (i = 0, cp1 = contDisp; *cp1; cp1++) {
	if ( !strncmp(cp1,"name=",5) ) {
	  cp1+=6;
	  for (j=0, cp2 = cp1; cp2 && *cp2 != '"'; cp2++) {
	    name[j] = *cp2; j++;
	  }
	  name[j]= '\0';
	  entries[numEntries].name = (char *)calloc(strlen(name)+1, sizeof(char));
	  strcpy(entries[numEntries].name,name);
	  ndb_log_message_text(NDB_MSG_DEBUG,"ht_decode_multipart_form_data: extracted NAME = %s",
			  entries[numEntries].name);
	}
	if ( !strncmp(cp1,"filename=",9) ) {
	  cp1+=10;
	  for (j=0, cp2 = cp1; cp2 && *cp2 != '"'; cp2++) {
	    fileName[j] = *cp2; j++;
	  }
	  fileName[j]= '\0';
	  if ( strlen(fileName) > 0) {
	    cp1 = ht_strip_leading_path(fileName);
	    entries[numEntries].file = (char *)calloc(strlen(cp1)+strlen(path)+1, sizeof(char));
	    strcat(entries[numEntries].file,path);
	    strcat(entries[numEntries].file,cp1);
	  } else {
	    entries[numEntries].file=NULL;
	  }
	  entries[numEntries].isFile = 1;
	  ndb_log_message_text(NDB_MSG_INFO,"ht_decode_multipart_form_data: storing FILENAME = %s in file %s",
			  cp1, entries[numEntries].file);
	}
      }
      bufp += strlen(contDisp) + 2;
      for (i = 0, cp1 = bufp; *cp1 && (*cp1 != '\r') ; cp1++) {
	contType[i] = *cp1; i++;
      }
      contType[i]='\0';
      ndb_log_message_text(NDB_MSG_DEBUG,"ht_decode_multipart_form_data: Content Type = %s",contType);
      if (strlen(contType)) bufp+=2;
      bufp += strlen(contType) + 2;
      datap = bufp;
    }
    lenData++;
  }
  for (i=0; i < numEntries; i++) {
    if (entries[i].isFile && entries[i].file != NULL ) {
      entries[i].val = (char *) calloc(strlen(entries[i].file)+1,sizeof(char));
      strcpy(entries[i].val,entries[i].file);
    }  else if (!entries[i].isFile && entries[i].val != NULL ) {
      entries[i].file = (char *) calloc(strlen(entries[i].val)+1,sizeof(char));
      strcpy(entries[i].file,entries[i].val);
    }
    ndb_log_message_text(NDB_MSG_DEBUG,"ht_decode_multipart_form_data: entry=%d name=%s value=%s file=%s isFile=%d\n",
			 i,
			 entries[i].name,
			 entries[i].val,
			 entries[i].file,
			 entries[i].isFile); 
  }

  return(numEntries);
}  

char *ht_strip_leading_path(char *s)
{
  char *p,*u;
  /*
   *  For PC filesystems...
   */
  if ((p = strrchr(s, '\\')) == (char *)NULL)
        p = s;
  else
        p++;

  /*
   *  For Unix filesystems...
   */
  if ((u = strrchr(p, '/')) == (char *)NULL)
        u = p;
  else
        u++;

  return(u);
}

void ht_check_get_request(void)
{
  if(strcmp(getenv("REQUEST_METHOD"),"GET")) {
    ndb_log_message_text(NDB_MSG_ERR,"ht_check_get_request: Wrong REQUEST_METHOD %s\n",
		    getenv("REQUEST_METHOD"));
    exit(1);
  }
}

void ht_check_post_request(void)
{
  if(strcmp(getenv("REQUEST_METHOD"),"POST")) {
    ndb_log_message_text(NDB_MSG_ERR,"ht_check_post_request: Wrong REQUEST_METHOD %s\n",
		    getenv("REQUEST_METHOD"));
    exit(1);
  }
#if 0
  if(strcmp(getenv("CONTENT_TYPE"),"application/x-www-form-urlencoded")) {
    ndb_log_message_text(NDB_MSG_ERR,"ht_check_post_request: Wrong CONTENT_TYPE %s\n",
		    getenv("CONTENT_TYPE"));
    exit(1);
  }
#endif
}

#if 0
int  ht_decode_post_query(entry *entries)
{
  int cl, n=0, i;
  ht_check_post_request();
  cl = atoi(getenv("CONTENT_LENGTH"));

  ndb_log_message_text(NDB_MSG_INFO,"ht_decode_post_query: CONTENT LENGTH %d\n",cl); 

  for(i=0; cl && (!feof(stdin)); i++) {
    n=i+1;
    entries[i].isFile = 0;
    entries[i].val = fmakeword(stdin,'&',&cl);
    plustospace(entries[i].val);
    unescape_url(entries[i].val);
    controltospace(entries[i].val); // jdw
    entries[i].name = makeword(entries[i].val,'=');
    ndb_log_message_text(NDB_MSG_DEBUG,"ht_decode_post_query: name %s value %s\n",
		    entries[i].name,
		    entries[i].val); 
  }
  return(n);
}  
#endif

#if 1

int  ht_decode_cgi_query(entry entries[HT_MAX_ENTRIES])
{
  if (!strcmp(getenv("REQUEST_METHOD"),"POST")) {
    return(ht_decode_post_query(entries));
  } else   if (!strcmp(getenv("REQUEST_METHOD"),"GET")) {
    return(ht_decode_get_query(entries));
  }
  return(0);
}

int  ht_decode_post_query(entry entries[HT_MAX_ENTRIES])
{
  int cl, n=0, i, j;
  char *name, *value, *tval;
  int onList;

  ht_check_post_request();
  cl = atoi(getenv("CONTENT_LENGTH"));

  ndb_log_message_text(NDB_MSG_INFO,"ht_decode_post_query: CONTENT LENGTH %d\n",cl); 

  n=0;
  for (i=0;  cl && (!feof(stdin)); i++) {

    value = fmakeword(stdin,'&',&cl);
    plustospace(value);
    unescape_url(value);
    controltospace(value); // jdw
    name = makeword(value,'=');
    if (!name  || strlen(name) == 0) continue;
    /*  
     *  If this is on the list then  ...
     */
    //    ndb_log_message_text(NDB_MSG_DEBUG,"ht_decode_post_query: name %s value %s\n",
    //		   name, value); 
    if (n == 0) {
      entries[n].isFile = 0;
      entries[n].val = value;
      entries[n].name = name;
      n++;
    } else {
      onList = 0;
      for (j=0; j < n; j++) {
	if (!strcmp(name,entries[j].name)) {
	  onList = 1; break; 
	}
      }
      //      ndb_log_message_text(NDB_MSG_DEBUG,"ht_decode_post_query: n %d onList %d name %s value %s\n",
      //		   n, onList, name, value); 
      if (onList) { /*  concatenate */
	tval = (char *) calloc(strlen(entries[j].val) + strlen(value) + 2, sizeof(char));
	strcpy(tval, entries[j].val);
	strcat(tval, ",");
	strcat(tval, value);
	free(entries[j].val);
	entries[j].val = tval;
      } else {
	entries[n].isFile = 0;
	entries[n].val = value;
	entries[n].name = name;
	n++;
      }
    }
    if (n >= HT_MAX_ENTRIES-1) break;
  }

  for (i = 0; i < n; i++) {
    ndb_log_message_text(NDB_MSG_DEBUG,"ht_decode_post_query: name %s value %s\n",
		    entries[i].name, entries[i].val); 
  }

  return(n);
}  
#endif

int ht_decode_post_query1(entry entries[HT_MAX_ENTRIES])
{
  int cl, n=0, i;
  char *name, *value;

  ht_check_post_request();
  cl = atoi(getenv("CONTENT_LENGTH"));

  ndb_log_message_text(NDB_MSG_INFO,"ht_decode_post_query: CONTENT LENGTH %d\n",cl); 

  n=0;
  for (i=0;  cl && (!feof(stdin)); i++) {

    value = fmakeword(stdin,'&',&cl);
    plustospace(value);
    unescape_url(value);
    controltospace(value); // jdw
    name = makeword(value,'=');
    if (!name  || strlen(name) == 0) continue;

    entries[n].isFile = 0;
    entries[n].val = value;
    entries[n].name = name;
    n++;
    if (n >= HT_MAX_ENTRIES-1) break;
  }

  for (i = 0; i < n; i++) {
    ndb_log_message_text(NDB_MSG_DEBUG,"ht_decode_post_query: name %s value %s\n",
		    entries[i].name, entries[i].val); 
  }

  return(n);
}  

void ht_dump_entries(entry *entries, int num)
{
  int i,j,len;
  FILE *fp=NULL;
  fp = fopen("/var/tmp/entry_dump.dat","w");
  if (fp == NULL) return;

  for (i=0; i < num; i++) {
    if ((entries[i].name != NULL) && (strlen(entries[i].name) > 0)) {
      fprintf(fp,"[%2d] Name:",i+1);
      len = strlen(entries[i].name);
      for (j=0; j<len; j++) {
	if (isalnum(entries[i].name[j])) 
	  fprintf(fp,"%c",entries[i].name[j]);
	else
	  fprintf(fp,"*");
      }
      fprintf(fp,"\n");
    }

    if ((entries[i].val != NULL) && (strlen(entries[i].val) > 0)) {
      fprintf(fp,"[%2d] Value:",i+1);
      len = strlen(entries[i].val);
      for (j=0; j<len; j++) {
	if (isalnum(entries[i].val[j])) 
	  fprintf(fp,"%c",entries[i].val[j]);
	else
	  fprintf(fp,"*");
      }
      fprintf(fp,"\n");
    }

  }
  fclose(fp);

}

int  ht_decode_get_query(entry *entries)
{
  char *cl;
  int n=0, i, maxlen;
  ht_check_get_request();
  cl = getenv("QUERY_STRING");
  ndb_log_message_text(NDB_MSG_DEBUG,"Query String %s",cl);
  if(cl == NULL) {
    return(0);
  }
  maxlen = strlen(cl);
  for(i=0; cl[0] != '\0'; i++) {
    n=i+1;
    entries[i].isFile = 0;
    entries[i].val  = (char *)calloc(maxlen+1,sizeof(char));
    entries[i].name = (char *)calloc(128,sizeof(char));
    getword(entries[i].val,cl,'&');
    plustospace(entries[i].val);
    unescape_url(entries[i].val);
    controltospace(entries[i].val); // jdw
    getword(entries[i].name,entries[i].val,'=');
  }
  return (n);
}  

char *ht_add_script_path(char *script)
{
  char *url;
  url = (char *)calloc(HT_MAX_NAME_LENGTH,sizeof(char));
  sprintf(url,"%s%s%s",HT_SERVER_URL,
	          HT_CGI_PATH,
	          script);
  return(url);
}

char *ht_get_keyword_value(const char *keyword, entry *entries, int nentries)
{
  char *val = NULL;
  int i;
  for (i = 0; i < nentries; i++ ) {
    if ((entries[i].val != NULL) && (strlen(entries[i].val) > 0 )) {
      if (strcmp(entries[i].name,keyword) == 0 ) {
	val = (char *) calloc(strlen(entries[i].val) + 1, sizeof(char));
	strcpy(val,entries[i].val);
	return(val);
      }
    }
  }
  return(val);
}

char *ht_get_keyword_file(const char *file, entry *entries, int nentries)
{
  char *val = NULL;
  int i;
  for (i = 0; i < nentries; i++ ) {
    if (entries[i].isFile && (entries[i].file != NULL) && (strlen(entries[i].file) > 0) ) {
      if (strcmp(entries[i].name,file) == 0 ) {
	val = (char *) calloc(strlen(entries[i].file) + 1, sizeof(char));
	strcpy(val,entries[i].file);
	return(val);
      }
    }
  }
  return(val);
}

void ht_set_server_url(char *url)
{
 int len;
 if ((len=strlen(url)) <= 0) return;
 if (HT_SERVER_URL != NULL) free(HT_SERVER_URL);
 HT_SERVER_URL = (char *)calloc(len+1, sizeof(char));
 strcpy(HT_SERVER_URL,url);
}

char *ht_get_server_url(void)
{
  char *url=NULL;
  if (HT_SERVER_URL !=NULL ) {
    url = (char *)calloc(strlen(HT_SERVER_URL)+1, sizeof(char));
    strcpy(url,HT_SERVER_URL);
  }
  return(url);
}

void ht_set_server_cgi_path(char *path)
{
 int len;
 if ((len=strlen(path)) <= 0) return;
 if (HT_CGI_PATH != NULL) free(HT_CGI_PATH);
 HT_CGI_PATH = (char *)calloc(len+1, sizeof(char));
 strcpy(HT_CGI_PATH,path);
}

char *ht_get_server_cgi_path(void)
{
  char *path=NULL;
  if (HT_CGI_PATH !=NULL ) {
    path = (char *)calloc(strlen(HT_CGI_PATH)+1, sizeof(char));
    strcpy(path,HT_CGI_PATH);
  }
  return(path);
}
