1 /* $Id: mmdbsrv.c,v 6.29 2005/01/12 22:49:13 vakatov Exp $
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *               National Center for Biotechnology Information
6 *
7 *  This software/database is a "United States Government Work" under the
8 *  terms of the United States Copyright Act.  It was written as part of
9 *  the author's official duties as a United States Government employee and
10 *  thus cannot be copyrighted.  This software/database is freely available
11 *  to the public for use. The National Library of Medicine and the U.S.
12 *  Government have not placed any restriction on its use or reproduction.
13 *
14 *  Although all reasonable efforts have been taken to ensure the accuracy
15 *  and reliability of the software and data, the NLM and the U.S.
16 *  Government do not and cannot warrant the performance or results that
17 *  may be obtained by using this software or data. The NLM and the U.S.
18 *  Government disclaim all warranties, express or implied, including
19 *  warranties of performance, merchantability or fitness for any particular
20 *  purpose.
21 *
22 *  Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * File Name:  $RCSfile: mmdbsrv.c,v $
27 *
28 * Author:  Christopher Hogue
29 *
30 * Version Creation Date: 6 January 1997
31 *
32 * $Revision: 6.29 $
33 *
34 * File Description:
35 *        MMDB WWW-server
36 *
37 * $Log: mmdbsrv.c,v $
38 * Revision 6.29  2005/01/12 22:49:13  vakatov
39 * /htbin-post/Taxonomy/wgetorg -> /Taxonomy/Browser/wwwtax.cgi
40 *
41 * Revision 6.28  2001/12/12 20:43:38  beloslyu
42 * change the name of ftp site to ftp.ncbi.nih.gov
43 *
44 * Revision 6.27  2001/01/25 23:02:56  lewisg
45 * get rid of content-disp, add mdlLvl and maxModels args
46 *
47 * Revision 6.26  2000/08/21 16:12:42  lewisg
48 * add save=asntext option
49 *
50 * Revision 6.25  2000/06/26 18:05:26  lewisg
51 * fix another hardcoded url
52 *
53 * Revision 6.24  2000/06/23 22:35:58  lewisg
54 * get rid of hardcoded urls
55 *
56 * Revision 6.23  2000/01/31 19:59:12  lewisg
57 * fix output of date in pdb header
58 *
59 * Revision 6.22  1999/10/13 20:13:18  zimmerma
60 * DZ: Removed use of temporary files - html ouput redirected to stdout
61 *
62 * Revision 6.21  1999/06/17 14:44:09  zimmerma
63 * Added static char variable for cvsId in order to use unix "what"
64 *
65 * Revision 6.20  1999/06/15 18:15:34  addess
66 * Initialized this_uid to 0 on line 1286
67 *
68 * Revision 6.19  1999/05/13 15:51:33  kimelman
69 * bugfix: memory deallocation fixed
70 *
71 * Revision 6.19  1999/05/13 15:51:33  kimelman
72 * bugfix: memory deallocation fixed
73 *
74 * Revision 6.18  1999/05/11 23:36:34  kimelman
75 * make StrToInt4 static
76 *
77 * Revision 6.17  1999/05/11 17:50:23  kimelman
78 * style
79 *
80 * Revision 6.16  1999/04/28 21:08:30  lewisg
81 * fixed double freeing of Biostruc
82 *
83 * Revision 6.15  1999/04/28 18:26:15  kimelman
84 * exit codes changed to 0
85 *
86 * Revision 6.14  1999/04/22 01:56:44  kimelman
87 * 1. pdb reference read completely from configurstion files
88 * 2. indentaiton
89 * 3. NcbiMimeAsn1Free(mime) commented out <-- lead to core
90 *    dump AFTER sending MIME (quick & dirty fix)
91 *
92 * Revision 6.13  1999/04/19 16:52:57  kimelman
93 * spelling fix
94 *
95 * Revision 6.12  1999/03/05 19:18:47  addess
96 * changed URL to link to RCSB structure explorer
97 *
98 * Revision 6.11  1998/11/06 16:25:31  addess
99 * added features for layer-1 and PDB TITLE records
100 *
101  * Revision 6.10  1998/07/17  18:45:53  madej
102  * Got rid of some unused URLs.
103  *
104  * Revision 6.9  1998/06/11  19:12:53  madej
105  * Changes in a message type for Cn3D by Yanli.
106  *
107  * Revision 6.8  1998/04/16  17:51:38  madej
108  * Tweak to print out author names in new/old format.
109  *
110  * Revision 6.7  1998/04/15  14:54:05  kimelman
111  * 1. Make retrieval unifirm from open server and sql server.
112  * 2. mmdbsrv retrival performance tuning:
113  * 	- size of read-in buffers
114  * 	- direct pdb2mmdb DB lookup instead of full loading pdb to mmdb translataion
115  * 	  table
116  * 3. cleaning mmdblocl.* and make.mmdbsrv in order to remove obsolete code
117  *
118 * Revision 6.6  1998/04/03 20:25:24  kimelman
119 * PubStruct access code added to mmdbsrv
120 *
121 * Revision 6.5  1998/02/20 18:25:26  madej
122 * Fix using unlink to stop file dumps into /var/tmp.
123 *
124  * Revision 6.4  1997/11/25  18:27:45  madej
125  * Fix to save asn.1 files in binary.
126  *
127  * Revision 6.3  1997/11/05  19:05:16  madej
128  * Updated comments for config file.
129  *
130  * Revision 6.2  1997/11/05  15:58:57  madej
131  * Bug fix for tax names in multiple listings
132  *
133  * Revision 6.1  1997/10/31  15:29:57  madej
134  * Major reformat of structure summary page, including taxonomy links.
135  *
136  * Revision 6.0  1997/08/25  18:11:28  madden
137  * Revision changed to 6.0
138  *
139 * Revision 1.2  1997/05/16 21:25:41  hogue
140 * Added checks with vast database entries before showing vast links.
141 *
142  * Revision 1.1  1997/02/18  18:03:30  hogue
143  * Initial revision
144  *
145 *
146 * ==========================================================================
147 */
148 
149 /**************
150 *mmdbsrv GET Useage:
151 *
152 *db=t&form=6&uid=1OMD&dopt=s  - PDB or MMDB-ids allowed
153 *db=t&form=6&uid=1OMD&Dopt=i  - launch Cn3D Mime-type - first UID only.
154 *db=t&uid=1234,2345,1254,1232&dopt=s - multiple structure summaries
155 *db=t&uid=3INS,1234,1OMD&dopt=s  - mixed id types OK
156 *
157 *Optional,  but if wrong,  error:
158 *        db=t    any other is an error message
159 *        form=6  4 is an error message - any other ignored
160 *
161 *Required
162 *	uid=(list of MMDB ids or PDB ids)
163 *
164 *Optional dopt=
165 *     's' Structure summary
166 *     'r' PDB file
167 *     'k' Kinemage file
168 *     'i' ASN.1 file
169 *     Others - error; None assumes 's'
170 *
171 *Optional - Interpreted in Context:
172 *        complexity="Cn3D+Subset"  ONECOORDATOM,  1
173 *                   "Virtual+Bond+Model" ONECOORDRES,  1
174 *                   "Up+to+5+Models" ALLMDL,  5
175 *                   "Up+to+10+Models" ALLMDL,  10
176 *	            "All+Models" ALLMDL,  100
177 *
178 *        KinemageColor="Molecule+Number" KIN_COLOR_NUMBER
179 *                      "Secondary+Structure"  KIN_COLOR_TYPE
180 *                      "Thermal+Factor" KIN_COLOR_TEMP
181 *                      "Element" KIN_COLOR_ATOM
182 *        KinemageRender=(integer)  - not seen on Struc Summary
183 *        save="See"
184 *             "s" - saves
185 *             "m" MacSave format
186 *        header="no" same as save="s"
187 *        title="no" - omit title bar and bottom options
188 *        html="no"
189 */
190 
191 
192 /*******************************************
193 MMDBSRV MIRROR installation:
194 
195 This describes what you need to run MMDBSRV:
196 
197 1] YOUR MMDB DATA DIRECTORIES, e.g.:
198 ...mmdb/mmdbdata/
199 ...mmdb/vastdata/
200 
201 These contain the MMDB data on your local filesystem,
202 as obtained from ftp://ftp.ncbi.nih.gov/mmdb/mmdbdata
203 and updated regularly by MIRROR.  You can
204 put them in the CGI-BIN or HTTP (HTML) directories
205 if you prefer. If you wish to implement a local
206 decompression/compression scheme see the source code mmdblocl.c.
207 
208 2] YOUR CGI-BIN directory & URL, e.g.:
209 ...cgi-bin/mmdb/
210 ...cgi-bin/mmdb/logs/
211 ...cgi-bin/mmdb/data/
212 http://123.456.789.10/cgi-bin/mmdb/
213 
214 The first contains the compiled mmdbsrv program and the
215 config file, obtained from
216 ftp://ftp.ncbi.nih.gov/mmdb/www/mmdbsrv
217 The second will contain the log files written out.
218 The third needs sshead.txt, sscode.txt, sstail.txt
219 NOTE - you must edit "sstail.txt"
220 in order to get the proper links to your local
221 copy of help documentation & server.
222 
223 3] YOUR HTTP (HTML) directory & URL, e.g.:
224 ...html/mmdb
225 ...html/mmdb/mmdbgifs
226 http://123.456.789.10/mmdb/
227 
228 The first contains the html files to launch mmdbsrv,
229 arrow.gif, strucsum.gif and any other gif files, and the
230 associated MMDB help files struchelp.html, cn3d.html,
231 strucinstall.html, vast.html, etc.  Master copies are kept
232 at ftp://ftp.ncbi.nih.gov/mmdb/www/http
233 You must hand edit or use scripts or SED to change links from
234 NCBI's to your own in all these HTML files.
235 
236 The second contains the GIF library as obtained from
237 the NCBI ftp site ftp://ftp.ncbi.nih.gov/mmdb/mmdbgifs
238 
239 6] Your WWW-Server - make it aware of the following
240 new MIME-types:
241 chemical/ncbi-asn1-binary  *.val
242 chemical/x-pdb  *.ent; *.pdb
243 chemical/x-kinemage *.kin
244 
245 
246 -----------------------------
247 7]
248 MMDBSRV gets its directory structure; link URLS and CGI call names
249 from a config file.
250 Change these as required and make a config file.
251 Unix ".mmdbrc" or Win "mmdb.ini" from this example:
252 
253 Don't change:
254 URLHelp, ENTREZurl, MMDBurl, PDBurl, 3DBurl
255 unless there are broken external links to these.
256 
257 -------------------- cut here --------------------
258 [MMDB]
259 ;Database and Index required when local MMDB database is used.
260 ; Database = ./Junk/
261 Database = /net/dorothy/cbb3/mmdb/data/
262 Index    = mmdb.idx
263 
264 [MMDBSRV]
265 ; File for configuring the MMDB server.
266 ; Base Directory & URLs for HTML documents.
267 HTMLPath  = /net/vaster/usr/attic/httpd.local/htdocs/Structure/
268 URLBase   = http://inhouse.ncbi.nlm.nih.gov:6224/Structure/
269 URLHelp   = http://www.ncbi.nlm.nih.gov/Entrez/
270 ;
271 
272 ; Base Directory for CGI-BIN code, data (gifs, html text) and logs.
273 CGIPath   = /net/vaster/usr/attic/httpd.local/cgi-bin/Structure/
274 URLcgi    = http://inhouse.ncbi.nlm.nih.gov:6224/cgi-bin/Structure/
275 CGIname   = mmdbsrv
276 DATApath  = ./data/
277 LOGpath   = ./logs/
278 ;
279 
280 ; Base Directory for MMDB-gif set
281 GIFpath  = /net/vaster/usr/attic/httpd.public/htdocs/Structure/mmdbgifs/
282 GIFurl   = http://www.ncbi.nlm.nih.gov/Structure/mmdbgifs/
283 ;
284 
285 ; URL's for links to Entrez, VAST.
286 ENTREZurl = http://www.ncbi.nlm.nih.gov/htbin-post/Entrez/query
287 VASTurl = http://inhouse.ncbi.nlm.nih.gov:6224/cgi-bin/Structure/vastsrv
288 MMDBurl = http://www.ncbi.nlm.nih.gov/Structure/
289 PDBurl = http://www.pdb.bnl.gov/index.html
290 TDBurl = http://www.pdb.bnl.gov/cgi-bin/opdbshort
291 
292 ; Location of gunzip function.
293 Gunzip = /usr/sbin/gunzip
294 
295 ;
296 MAILto   = info@ncbi.nlm.nih.gov
297 ;
298 [VAST]
299 ;Database required for local VAST fetches.
300 ;Database = /net/vaster/usr/people6/madej/vastdata.binary/
301 Database = /net/dorothy/cbb3/vast/data/
302 
303 ; URL for link to taxonomy database (wgetorg for retrieval)
304 [TAXLINK]
305 TAXurl = http://www.ncbi.nlm.nih.gov/Taxonomy/Browser/wwwtax.cgi
306 
307 -------------------- cut here --------------------
308 ********************************************/
309 
310 #include <ncbi.h>
311 #include <ncbiwww.h>
312 #include <accentr.h>
313 #include <ncbistr.h>
314 #include <miscutils.h>
315 #include <sys/resource.h>
316 #include <mmdbapi.h>
317 #include <mmdbdata.h>
318 #include <taxinc.h>
319 #include <sys/resource.h>
320 
321 #include <lsqfetch.h>
322 #include <netentr.h>
323 #include <asnmime.h>
324 #include <objmime.h>
325 
326 #ifdef OS_UNIX
327 #include <signal.h>
328 #include <unistd.h>
329 #define CPUTIME_MAX 120
330 #endif
331 
332 
333 
334 #define NUM_COMPLEXITY_TYPES 6
335 static char *ComplexityDescriptions[] =
336 {"Virtual Bond Model","All Atom Model","Up to 5 Models",
337    "Up to 10 Models","All Models","Cn3D Subset"};
338 
339 #define NUM_COLOR_TYPES 5
340 static char *ColorDescriptions[] =
341 {"","Molecule Number","Secondary Structure","Thermal Factor","Element"};
342 
343 /* the config file DATApath is used for the location of these files */
344 
345 #define HEADFILE "sshead.txt"
346 /* Structure Summary Header File */
347 
348 #define TAILFILE "sstail.txt"
349 /* Structure Summary Tail File  */
350 
351 #define CODEFILE "sscode.txt"
352 /* Structure Summary View Code */
353 
354 #define CHAIN_CHOICE_NUM	1
355 #define ORG_CHOICE_NUM		6
356 
357 /* some defines needed for the taxonomy code */
358 
359 #define TAX_ID_CHOICE_NUM	0
360 #define MAX_CHAINS		128
361 #define MAX_TBUFF		8192
362 
363 WWWInfoPtr 		info = NULL;
364 
365 static Boolean GlobalTitles = TRUE;
366 static Boolean GlobalNonHtmlOutput = FALSE;
367 
368 static Char HTMLPath[PATH_MAX];
369 static Char URLBase[PATH_MAX];
370 static Char URLHelp[PATH_MAX];
371 
372 static Char CGIPath[PATH_MAX];
373 static Char URLcgi[PATH_MAX];
374 static Char CGIName[256];
375 static Char DATApath[PATH_MAX];
376 static Char LOGpath[PATH_MAX];
377 
378 static Char ENTREZurl[PATH_MAX];
379 static Char VASTurl[PATH_MAX];
380 static Char MMDBurl[PATH_MAX];
381 static Char PDBurl[PATH_MAX];
382 static Char TDBurl[PATH_MAX];
383 static Char TAXurl[PATH_MAX];
384 static Char MAILto[256];
385 static Char MAILTO[PATH_MAX];
386 static Char ARROW[PATH_MAX];
387 
388 static char* cvsId_ = "@(#)$Id: mmdbsrv.c,v 6.29 2005/01/12 22:49:13 vakatov Exp $";
389 
390 /*****************************************************
391  * WWWPrintFileData looks in the current CGI-BIN directory
392  *  or the "data" subdirectory for the data file.
393  *  and prints it out to pFile
394  */
395 
WWWPrintFileData(CharPtr FName,FILE * pFile)396 static void WWWPrintFileData(CharPtr FName,  FILE *pFile)
397 {
398 
399    FILE *f = NULL;
400    Char fullpath [PATH_MAX];
401    CharPtr ptr;
402    Char pcBuf[1024];
403 
404    fullpath[0] = '\0';
405    StringCpy(fullpath,  DATApath); /* look in DATApath */
406    StringCat(fullpath,  FName);
407    f = FileOpen (fullpath, "r");
408    if (f == NULL) {
409        f = FileOpen (FName, "r");  /* look in curent */
410        if (f == NULL)  {  /* look in ./data/ */
411          ProgramPath (fullpath, sizeof (fullpath) - 1);
412          ptr = StringRChr (fullpath, DIRDELIMCHR);
413          if (ptr != NULL) {
414 	  *ptr = '\0';
415          }
416          FileBuildPath (fullpath, "data", FName);
417          f = FileOpen (fullpath, "r");
418          if (f == NULL)  {
419            return;
420          }
421        }
422    }
423 
424    do {
425      pcBuf[0] = '\0';
426      ptr = fgets(pcBuf, (size_t)1024, f);
427      if (ptr) fprintf(pFile, ptr);
428    } while (ptr);
429 
430    FileClose(f);
431    return;
432 }
433 
434 
435 static Boolean
StrToInt4(CharPtr str,Int4Ptr longval)436 StrToInt4 (CharPtr str, Int4Ptr longval)
437 {
438   Nlm_Int2     i;
439   Nlm_Int2     len;
440   Nlm_Char     local [64];
441   Nlm_Boolean  nodigits;
442   long int     val;
443 
444   if (longval != NULL) {
445     *longval = (Nlm_Int4) 0;
446   }
447   len = (Nlm_Int2) Nlm_StringLen (str);
448   if (len == 0)
449     return FALSE;
450 
451   nodigits = TRUE;
452   for (i = 0; i < len; i++)
453     {
454       Nlm_Char     ch;
455 
456       ch = str [i];
457       if ('0' <= ch && ch <= '9')
458         nodigits = FALSE;
459       else if ( !/*!!*/  (ch == ' ' || ch == '+' || ch == '-') || nodigits==FALSE)
460         return FALSE;
461     }
462   if (nodigits)
463     return FALSE;
464   if (longval != NULL)
465     {
466       Nlm_StringNCpy (local, str, sizeof (local));
467       if (sscanf (local, "%ld", &val) == 1)
468         *longval = val;
469     }
470   return TRUE;
471 }
472 
473 
CountUIDs(char * String)474 static Int4 CountUIDs(char *String)
475 {
476   Int4 count = 0;
477 
478   for (;;)
479     {
480       String = SkipSet(String,", ");
481       if (*String == NULLB)
482 	break;
483       count++;
484       String = SkipToSet(String,", ");
485     }
486 
487   return(count);
488 }
489 
ConvertMMDBUID(CharPtr pcString)490 static Int4 ConvertMMDBUID(CharPtr pcString)
491 {
492     Int4 iUID;
493     CharPtr pcTemp = NULL;
494 
495     if (pcString == NULL)
496     return 0;
497 
498     iUID = 0;
499     pcTemp = StringSave(pcString);
500     CleanSpaces(pcTemp);
501     if (!StrToInt4(pcTemp, &iUID))
502       {
503 	   iUID = MMDBEvalPDB(pcTemp);
504       }
505     MemFree(pcTemp);
506     return iUID;
507 }
508 
509 
510 
511 
MakeUIDList(CharPtr pcString,ValNodePtr PNTR ppvnUIDS)512 static void MakeUIDList(CharPtr pcString,  ValNodePtr PNTR ppvnUIDS)
513 {
514   CharPtr Ptr = NULL;
515   CharPtr Ptr2 = NULL;
516   Char SavedChar = NULL;
517   Int4 Uid = 0,  i;
518   Int4Ptr Uids = NULL;
519 
520 
521   Ptr = SkipSpaces(pcString);
522   if (*Ptr == NULLB)
523     return;
524 
525   while (*Ptr)
526     {
527       Ptr2 = SkipToSet(Ptr," ,");
528       SavedChar = *Ptr2;
529       *Ptr2 = NULLB;
530       Uid = 0;
531       Uid = ConvertMMDBUID(Ptr);
532 /* printf("{%s}[%ld]\n", Ptr,  Uid); */
533       if (Uid != 0)
534 	{
535           ValNodeAddInt(ppvnUIDS, 0, Uid);
536         }
537       *Ptr2 = SavedChar;
538       Ptr = SkipSet(Ptr2," ,");
539     }
540 
541   return;
542 }
543 
544 
GetOptionValue(CharPtr Value,Int4 NumElements,CharPtr * ElementText)545 static Int4 GetOptionValue(CharPtr Value, Int4 NumElements, CharPtr *ElementText)
546 {
547   Int4 count, Len;
548   Int4 valnum;
549 
550   if (StrToInt4(Value,  &valnum))
551     return(valnum);
552 
553   Len = StringLen(Value);
554   for (count = 0; count < NumElements; count++)
555     if (StrNICmp(ElementText[count],Value, Len) == 0)
556       break;
557 
558   if (count == NumElements)
559     return -1;
560 
561   return(count);
562 }
563 
564 
565 
566 /* Output links from the protein and nucleotide chains to GenPept reports. */
567 
568 #define EntrezLink	"<A HREF=\"%s?uid=%ld&form=6&db=%c&dopt=%c\">%s</A>"
569 
570 /************ Added by Ken for Layer One PDB releases ************/
571 
My_StringNCpy(CharPtr str1,CharPtr str2,Int4 len)572 static void My_StringNCpy(CharPtr str1, CharPtr str2, Int4 len)
573 {
574   StringNCpy(str1,str2,len);
575   str1[len] = '\0';
576 }
577 
IsLayerOne(ValNodePtr pvn)578 static Boolean IsLayerOne(ValNodePtr pvn)
579 {
580   Boolean Layer = FALSE;
581   CharPtr comment_txt;
582   CharPtr LayerOne = {"This is Layer 1 Release"};
583   CharPtr temp_string;
584   Int4 len;
585 
586   while (pvn)
587   {
588      if (pvn->choice == BiostrucDescr_pdb_comment)
589      {
590         comment_txt = (CharPtr)pvn->data.ptrvalue;
591         temp_string = StringSave(LayerOne);
592         len = StringLen(LayerOne);
593         My_StringNCpy(temp_string, &comment_txt[18], len);
594         if (!StringICmp(temp_string, LayerOne))
595         {
596           Layer = TRUE;
597           break;
598         }
599      }
600      pvn = pvn->next;
601    }
602 
603    return Layer;
604 }
605 /***** End of functions added by Ken ********************/
606 static void
PrintMolecularContents(PDNMS ModelStruc,FILE * gdf)607 PrintMolecularContents(PDNMS ModelStruc, FILE *gdf)
608 {
609 	PMSD pmsd;
610 	PDNMM pdnmm;
611 	PMMD pmmd;
612 	Int2 cnt;
613 
614 
615 
616 	if (ModelStruc == NULL)
617 		return;
618 
619 	/* protein chains */
620 	pmsd = (PMSD) ModelStruc->data.ptrvalue;
621 
622 	for (pdnmm = pmsd->pdnmmHead, cnt = 0; pdnmm != NULL; pdnmm = pdnmm->next) {
623 		pmmd = (PMMD) pdnmm->data.ptrvalue;
624 
625 		if ((pmmd->bWhat) & AM_PROT) {
626 			if (cnt++ == 0) {
627 				fprintf(gdf, "<TR>\n<TD VALIGN=TOP NOWRAP>");
628 				fprintf(gdf, "<strong>Protein Chains:</strong></TD>\n<TD>");
629 
630 				if (pmmd->pcMolName[0] == ' ')
631 					fprintf(gdf, EntrezLink, ENTREZurl, (long) pmmd->iGi, 'p', 'g',
632 						"(single chain)");
633 				else
634 					fprintf(gdf, EntrezLink, ENTREZurl, (long) pmmd->iGi, 'p', 'g',
635 						pmmd->pcMolName);
636 			}
637 			else {
638 				fprintf(gdf, ", ");
639 				fprintf(gdf, EntrezLink, ENTREZurl, (long) pmmd->iGi, 'p', 'g',
640 					pmmd->pcMolName);
641 			}
642 		}
643 	}
644 
645 	if (cnt > 0)
646 		fprintf(gdf, "</TD>\n</TR>\n");
647 
648 	/* nucleotide chains */
649 	for (pdnmm = pmsd->pdnmmHead, cnt = 0; pdnmm != NULL; pdnmm = pdnmm->next) {
650 		pmmd = (PMMD) pdnmm->data.ptrvalue;
651 
652 		if ((pmmd->bWhat) & (AM_DNA | AM_RNA)) {
653 			if (cnt++ == 0) {
654 				fprintf(gdf, "<TR>\n<TD VALIGN=TOP NOWRAP>");
655 				fprintf(gdf, "<strong>Nucleotide chains:</strong></TD>\n<TD>");
656 
657 				if (pmmd->pcMolName[0] == ' ')
658 					fprintf(gdf, EntrezLink, ENTREZurl, (long) pmmd->iGi, 'n', 'g',
659 						"(single chain)");
660 				else
661 					fprintf(gdf, EntrezLink, ENTREZurl, (long) pmmd->iGi, 'n', 'g',
662 						pmmd->pcMolName);
663 			}
664 			else {
665 				fprintf(gdf, ", ");
666 				fprintf(gdf, EntrezLink, ENTREZurl, (long) pmmd->iGi, 'n', 'g',
667 					pmmd->pcMolName);
668 			}
669 		}
670 	}
671 
672 	if (cnt > 0)
673 		fprintf(gdf, "</TD>\n</TR>\n");
674 
675 } /* end PrintMolecularContents */
676 
677 
678 
679 static void
PrintStructureInfo(PDNMS ModelStruc,FILE * File,CharPtr tax_save)680 PrintStructureInfo(PDNMS ModelStruc,  FILE *File, CharPtr tax_save)
681 {
682    char Name[200];
683    Int4 depyear, depday;
684    PMSD pmsdThis = NULL;
685    BiostrucSourcePtr pbssThis = NULL;
686    ValNodePtr pvnThis = NULL;
687    BiostrucHistoryPtr pbshThis = NULL;
688    CharPtr pcAuthors = NULL;
689    char Paragraph[10];
690 
691    if (!ModelStruc)
692      return;
693 
694    pmsdThis = (PMSD) ModelStruc->data.ptrvalue;
695    pvnThis = ValNodeFindNext(pmsdThis->pbsBS->descr,NULL,BiostrucDescr_history);
696 
697    if (pvnThis) {
698       pbshThis = (BiostrucHistoryPtr) pvnThis->data.ptrvalue;
699       pbssThis = pbshThis->data_source;
700    }
701 
702   /*****
703   fprintf(File, "<font size=+2>MMDB Id: %ld&nbsp ", (long) pmsdThis->iMMDBid);
704   *****/
705   fprintf(File, "<font size=+2>");
706   fprintf(File, "MMDB Id: <A HREF=\"%s%s?uid=%ld&form=6&db=t&Dopt=s\">%ld</A>&nbsp ",
707 	URLcgi, CGIName, (long) pmsdThis->iMMDBid, (long) pmsdThis->iMMDBid);
708   fprintf(File, "PDB Id: <A HREF=\"%s=%s\">%s</a>\n", TDBurl,pmsdThis->pcPDBName, pmsdThis->pcPDBName);
709   if (IsLayerOne(pmsdThis->pbsBS->descr))
710     fprintf(File, " - Warning: <A HREF=\"http://www.pdb.bnl.gov/pdb-docs/what_is_LR.html\">Not validated!</A>\n");
711   fprintf(File, "</font>");
712   fprintf(File, "<BR>\n<BR>\n");
713   fprintf(File, "<TABLE>\n");
714   PrintMolecularContents(ModelStruc, File);
715   fprintf(File, "<TR>\n<TD VALIGN=TOP NOWRAP>");
716   fprintf(File, "<strong>MEDLINE</strong>:</TD>\n<TD><A HREF=\"%s?db=t&form=6&uid=", ENTREZurl);
717   fprintf(File, "%ld&Dopt=m\">PubMed</A></TD>\n</TR>\n", (long) pmsdThis->iMMDBid );
718 
719   if (tax_save != NULL)
720 	fprintf(File, "%s\n", tax_save);
721   else if (pmsdThis->pcPdbSource) {
722   	fprintf(File, "<TR>\n<TD VALIGN=TOP NOWRAP>");
723 	fprintf(File, "<strong>Source</strong>:</TD>\n<TD>%s</TD>\n</TR>\n", pmsdThis->pcPdbSource);
724   }
725 
726   /* insert a blank row in the table, for spacing */
727   fprintf(File, "<TR>\n<TD VALIGN=TOP NOWRAP> </TD>\n<TD><BR></TD>\n</TR>\n");
728   pcAuthors =  AuthorListPDB(pmsdThis->pbsBS);
729 
730   if (pcAuthors) {
731   	fprintf(File, "<TR>\n<TD VALIGN=TOP NOWRAP>");
732 	fprintf(File, "<strong>PDB Authors</strong>:</TD>\n<TD>%s</TD>\n</TR>\n", pcAuthors);
733 	fflush(File);
734 	MemFree(pcAuthors);
735   }
736 
737   if (pbssThis) {
738    	depyear = pbssThis->database_entry_date->data[1];
739    	depday = pbssThis->database_entry_date->data[3];
740   	fprintf(File, "<TR>\n<TD VALIGN=TOP NOWRAP>");
741 	fprintf(File, "<strong>PDB Deposition</strong>:</TD>\n<TD>%2d-%3s-%02d</TD>\n</TR>\n",
742 		(int) depday, NCBI_months[pbssThis->database_entry_date->data[2] - 1], (int) depyear%100);
743   }
744 
745   if (pmsdThis->pcPdbClass) {
746   	fprintf(File, "<TR>\n<TD VALIGN=TOP NOWRAP>");
747 	fprintf(File, "<strong>PDB Class</strong>:</TD>\n<TD>%s</TD>\n</TR>\n", pmsdThis->pcPdbClass);
748   }
749 
750   fprintf(File, "<TR>\n<TD VALIGN=TOP NOWRAP>");
751   pvnThis = ValNodeFindNext(pmsdThis->pGraphDescr,NULL,BiomolDescr_pdb_comment);
752   if (pvnThis)
753     fprintf(File, "<strong>PDB Title</strong>:</TD>\n<TD>%s</TD>\n</TR>\n", pmsdThis->pcChemName);
754   else
755     fprintf(File, "<strong>PDB Compound</strong>:</TD>\n<TD>%s</TD>\n</TR>\n", pmsdThis->pcChemName);
756   /* insert a blank row in the table, for spacing */
757   fprintf(File, "<TR>\n<TD VALIGN=TOP NOWRAP> </TD>\n<TD><BR></TD>\n</TR>\n");
758 
759   /* Note: The table continues with "Sequence Neighbors" and "Structure Neighbors". */
760   return;
761 
762 }
763 
764 
765 
766 static void
PrintStructureView(PDNMS ModelStruc,FILE * File)767 PrintStructureView(PDNMS ModelStruc, FILE *File)
768 {
769 	PMSD pmsd;
770 
771         if (ModelStruc == NULL) return;
772 
773 	pmsd = (PMSD) ModelStruc->data.ptrvalue;
774 	fprintf(File, "<FORM METHOD=POST ACTION=\"%s%s\">\n", URLcgi, CGIName);
775 	fprintf(File, "<INPUT TYPE=HIDDEN NAME=uid VALUE=%ld>\n", (long) pmsd->iMMDBid);
776 	WWWPrintFileData(CODEFILE, File);
777 }
778 
779 
780 
781 /* This routine creates the last two rows of the table started by PrintStructureInfo.
782  * These last two rows contain the links for the "Sequence Neighbors" of the chains of
783  * the structure, and for "Structure Neighbors" of the chains and domains of the
784  * structure.  The first part of the code is very similar to PrintMolecularContents.
785  * The 2nd part creates the links for the VAST structure neighbors.
786  *
787  * Note there are 3 different formats for Vast neighbor links, purely for cosmetics.
788  */
789 
790 #define VastLink1	"<A HREF=\"%s?uid=%ld&chaindom=%ld\">%s</A>"
791 #define VastLink2	"<A HREF=\"%s?uid=%ld&chaindom=%ld\">%s.%d</A>"
792 #define VastLink3	"<A HREF=\"%s?uid=%ld&chaindom=%ld\">%d</A>"
793 
794 static void
PrintStructureLinks(PDNMS ModelStruc,FILE * gdf)795 PrintStructureLinks(PDNMS ModelStruc, FILE *gdf)
796 {
797 	PMSD pmsd;
798 	PDNMM pdnmm;
799 	PMMD pmmd;
800 	PDNMG pdnmg;
801 	PMGD pmgd;
802 	Int2 cnt, pflg;
803 	Int4 uid, ichn, idom, chndom, chndom0;
804 
805 
806 
807 	if (ModelStruc == NULL)
808 		return;
809 
810 	/* insert a blank row in the table, for spacing */
811 	fprintf(gdf, "<TR>\n<TD VALIGN=TOP NOWRAP> </TD>\n<TD> </TD>\n</TR>\n");
812 
813 	/* protein chains */
814 	pmsd = (PMSD) ModelStruc->data.ptrvalue;
815 
816 	for (pdnmm = pmsd->pdnmmHead, cnt = pflg = 0; pdnmm != NULL; pdnmm = pdnmm->next) {
817 		pmmd = (PMMD) pdnmm->data.ptrvalue;
818 
819 		if ((pmmd->bWhat) & AM_PROT) {
820 			if ((pmmd->iResCount <= 1) || (pmmd->iGi <= 0))
821 				continue;
822 
823 			if (cnt++ == 0) {
824 				pflg = 1;
825 				fprintf(gdf, "<TR>\n<TD VALIGN=TOP NOWRAP>");
826 				fprintf(gdf, "<strong>Sequence Neighbors:</strong></TD>\n<TD>");
827 
828 				if (pmmd->pcMolName[0] == ' ')
829 					fprintf(gdf, EntrezLink, ENTREZurl, (long) pmmd->iGi, 'p', 'p',
830 						"(single chain)");
831 				else
832 					fprintf(gdf, EntrezLink, ENTREZurl, (long) pmmd->iGi, 'p', 'p',
833 						pmmd->pcMolName);
834 			}
835 			else {
836 				fprintf(gdf, ", ");
837 				fprintf(gdf, EntrezLink, ENTREZurl, (long) pmmd->iGi, 'p', 'p',
838 					pmmd->pcMolName);
839 			}
840 		}
841 	}
842 
843 	/* nucleotide chains */
844 	for (pdnmm = pmsd->pdnmmHead; pdnmm != NULL; pdnmm = pdnmm->next) {
845 		pmmd = (PMMD) pdnmm->data.ptrvalue;
846 
847 		if ((pmmd->bWhat) & (AM_DNA | AM_RNA)) {
848 			if ((pmmd->iResCount <= 1) || (pmmd->iGi <= 0))
849 				continue;
850 
851 			if (cnt++ == 0) {
852 				fprintf(gdf, "<TR>\n<TD VALIGN=TOP NOWRAP>");
853 				fprintf(gdf, "<strong>Sequence Neighbors:</strong></TD>\n<TD>");
854 
855 				if (pmmd->pcMolName[0] == ' ')
856 					fprintf(gdf, EntrezLink, ENTREZurl, (long) pmmd->iGi, 'n', 'n',
857 						"(single chain)");
858 				else
859 					fprintf(gdf, EntrezLink, ENTREZurl, (long) pmmd->iGi, 'n', 'n',
860 						pmmd->pcMolName);
861 			}
862 			else {
863 				fprintf(gdf, ", ");
864 				fprintf(gdf, EntrezLink, ENTREZurl, (long) pmmd->iGi, 'n', 'n',
865 					pmmd->pcMolName);
866 			}
867 		}
868 	}
869 
870 	if (pflg)
871 		fprintf(gdf, "</TD>\n</TR>\n");
872 
873 	if (pmsd->pdnmlModels == NULL) {
874 		/* end the table */
875 		fprintf(gdf, "</TABLE>\n<BR>\n");
876 		return;
877 	}
878 
879 	/* VAST neighbors: loop over protein chains */
880 	uid = (Int4) pmsd->iMMDBid;
881 
882 	for (pdnmm = pmsd->pdnmmHead, cnt = ichn = 0; pdnmm != NULL; pdnmm = pdnmm->next) {
883 		pmmd = (PMMD) pdnmm->data.ptrvalue;
884 		ichn++;
885 
886 		if ((pmmd->bWhat) & AM_PROT) {
887 			if ((pmmd->iResCount <= 1) || (pmmd->iGi <= 0))
888 				continue;
889 
890 			chndom0 = 10000*uid + 100*(Int4) ichn;
891 
892 			if (cnt++ == 0) {
893 				fprintf(gdf, "<TR>\n<TD VALIGN=TOP NOWRAP>");
894 				fprintf(gdf, "<strong>Structure Neighbors:</strong></TD>\n<TD>");
895 
896 				if (pmmd->pcMolName[0] == ' ')
897 					fprintf(gdf, VastLink1, VASTurl, (long) uid, (long) chndom0,
898 						"(single chain)");
899 				else
900 					fprintf(gdf, VastLink1, VASTurl, (long) uid, (long) chndom0,
901 						pmmd->pcMolName);
902 			}
903 			else {
904 				fprintf(gdf, ", ");
905 				fprintf(gdf, VastLink1, VASTurl, (long) uid, (long) chndom0,
906 					pmmd->pcMolName);
907 			}
908 
909 			/* now loop over domains */
910 			idom = 0;
911 
912 			for (pdnmg = pmmd->pdnmgHead; pdnmg != NULL; pdnmg = pdnmg->next) {
913 				pmgd = (PMGD) pdnmg->data.ptrvalue;
914 
915 				if (pmgd->iDomain > idom) {
916 					idom = (Int4) pmgd->iDomain;
917 					chndom = chndom0 + idom;
918 					fprintf(gdf, ", ");
919 
920 					if (pmmd->pcMolName[0] == ' ')
921 						fprintf(gdf, VastLink3, VASTurl, (long) uid,
922 							(long) chndom, (int) idom);
923 					else
924 						fprintf(gdf, VastLink2, VASTurl, (long) uid,
925 							(long) chndom, pmmd->pcMolName, (int) idom);
926 				}
927 			}
928 		}
929 	}
930 
931 	/* end the table */
932 	fprintf(gdf, "</TD>\n</TR>\n</TABLE>\n");
933 
934 } /* end PrintStructureLinks */
935 
936 
937 
938 /* Utility routine needed below.  Return a vector marking the distinct integers
939  * appearing in the input array.  A naive algorithm is used since we never expect
940  * the array size 'n' to be large.  If an entry vec[i] is 0, this means it is
941  * a duplicate.  If vec[i] > 0 then this is the first occurrence of the number,
942  * and the value vec[i] is the number of times the corresponding number nums[i]
943  * appears.
944  */
945 
946 static void
mark_distinct(Int4Ptr nums,Int2Ptr vec,Int2 n)947 mark_distinct(Int4Ptr nums, Int2Ptr vec, Int2 n)
948 {
949 	Int2 i, j, found;
950 
951 	if (n == 0)
952 		return;
953 
954 	/* initialize the vector */
955 	for (i = 0; i < n; i++)
956 		vec[i] = 1;
957 
958 	for (i = 1; i < n; i++) {
959 		for (j = 0; j < i; j++) {
960 			if (nums[i] == nums[j]) {
961 				vec[i] = 0;
962 				vec[j]++;
963 				break;
964 			}
965 		}
966 	}
967 
968 } /* end mark_distinct */
969 
970 
971 
972 /* Output the taxonomy data, per chain, and also links to the taxonomy database.
973  * Return '1' in case there was a non-trivial taxonomy assignment, '0' if there
974  * was no taxonomy data found.  The success or failure is passed ultimately to
975  * PrintStructureInfo, where the PDB source is displayed in case no taxonomy data
976  * was found.
977  */
978 
979 static Int2
SaveTaxonomyInfo(BiostrucPtr bsp,CharPtr save,Int2 n,CharPtr pname)980 SaveTaxonomyInfo(BiostrucPtr bsp, CharPtr save, Int2 n, CharPtr pname)
981 {
982 	MoleculeGraphPtr mgp;
983 	Int4 i, j, k, cnt, txcnt, uacnt;
984 	ValNodePtr descr, db;
985 	CharPtr chainp, name, names[MAX_CHAINS];
986 	Char chn, chns[MAX_CHAINS], org_names[MAX_TBUFF];
987 	Int2 flg, name_here, cnt_vec[MAX_CHAINS];
988 	BioSourcePtr bios;
989 	OrgRefPtr org;
990 	Int4 molecule_type, tax_id, tax_ids[MAX_CHAINS];
991 
992 
993 
994 	if ((bsp == NULL) || (save == NULL))
995 		return 0;
996 
997 	for (i = 0; i < MAX_TBUFF; i++)
998 		org_names[i] = '\0';
999 
1000 	name_here = 0;
1001 	mgp = bsp->chemical_graph->molecule_graphs;
1002 
1003 	for (cnt = uacnt = 0; (mgp != NULL) && (cnt < MAX_CHAINS); mgp = mgp->next) {
1004 		/* zap the OrgRefPtr, there may be no taxonomy for this chain! */
1005 		org = NULL;
1006 
1007 		for (descr = mgp->descr; descr != NULL; descr = descr->next) {
1008 			if (descr->choice == BiomolDescr_molecule_type)
1009 				molecule_type = descr->data.intvalue;
1010 
1011 			if (descr->choice == BiomolDescr_name) {
1012 				chainp = descr->data.ptrvalue;
1013 				chn = *chainp;
1014 			}
1015 
1016 			if (descr->choice == BiomolDescr_organism) {
1017 				bios = descr->data.ptrvalue;
1018 				org = (OrgRefPtr) bios->org;
1019 			}
1020 		}
1021 
1022 		if ((molecule_type == Molecule_type_protein) ||
1023 			(molecule_type == Molecule_type_dna) ||
1024 			(molecule_type == Molecule_type_rna)) {
1025 
1026 			/* save the chain and get the taxonomy data */
1027 			chns[cnt] = (chn == ' ') ? '\n' : chn;
1028 
1029 			if (org != NULL) {
1030 				DbtagPtr dbtag;
1031 				ObjectIdPtr object_id;
1032 
1033 				for (db = org->db, tax_id = -1; db != NULL; db = db->next) {
1034 					if (db->choice == TAX_ID_CHOICE_NUM) {
1035 						dbtag = db->data.ptrvalue;
1036 						tax_id = dbtag->tag->id;
1037 						break;
1038 					}
1039 				}
1040 
1041 				names[cnt] = &org_names[name_here];
1042 
1043 				if (org->taxname != NULL) {
1044 					StringCat(names[cnt], org->taxname);
1045 					name_here += StrLen(org->taxname) + 1;
1046 				}
1047 				else if (org->common != NULL) {
1048 					StringCat(names[cnt], org->common);
1049 					name_here += StrLen(org->common) + 1;
1050 				}
1051 				else {
1052 					StringCat(names[cnt], "(unassigned)");
1053 					name_here += 13;
1054 				}
1055 
1056 				tax_ids[cnt++] = tax_id;
1057 			}
1058 			else {
1059 				/* track the number of unassigned chains */
1060 				uacnt++;
1061 				names[cnt] = &org_names[name_here];
1062 				StringCat(names[cnt], "(unassigned)");
1063 				name_here += 13;
1064 				tax_ids[cnt++] = -1;
1065 			}
1066 		}
1067 	}
1068 
1069 	/* zap the save area */
1070 	for (i = 0; i < n; i++)
1071 		save[i] = '\0';
1072 
1073 	/* flag the taxonomy section */
1074 	sprintf(save, "<TR>\n<TD VALIGN=TOP NOWRAP><strong>Taxonomy</strong>:</TD>\n");
1075 
1076 	if (cnt == 0) {
1077 		k = StrLen(save);
1078 		sprintf(&save[k], "<TD>(unassigned)</TD>\n");
1079 		return 1;
1080 	}
1081 
1082 	/* group chains by organism type, i.e. tax id */
1083 	mark_distinct(tax_ids, cnt_vec, cnt);
1084 
1085 	for (i = flg = 0; i < cnt; i++) {
1086 		if (cnt_vec[i] == 0)
1087 			continue;
1088 
1089 		tax_id = tax_ids[i];
1090 		k = StrLen(save);
1091 
1092 		if (flg)
1093 			sprintf(&save[k], "; ");
1094 		else {
1095 			sprintf(&save[k], "<TD>");
1096 			flg = 1;
1097 		}
1098 
1099 		/* collect chains with the same tax id */
1100 		txcnt = cnt_vec[i];
1101 		k = StrLen(save);
1102 
1103 		/*****
1104 		if (txcnt > 1)
1105 			sprintf(&save[k], "chains ");
1106 		else if (chns[i] != '\n')
1107 			sprintf(&save[k], "chain ");
1108 		*****/
1109 
1110 		for (j = i; (j < cnt) && (txcnt > 0); j++) {
1111 			if (tax_ids[j] != tax_id)
1112 				continue;
1113 
1114 			k = StrLen(save);
1115 
1116 			if (txcnt-- > 1)
1117 				sprintf(&save[k], "%c, ", chns[j]);
1118 			else
1119 				sprintf(&save[k], "%c", chns[j]);
1120 		}
1121 
1122 		k = StrLen(save);
1123 
1124 		if (tax_id > 0) {
1125 			if (chns[i] != '\n')
1126 				sprintf(&save[k], "&nbsp <A HREF=\"");
1127 			else
1128 				sprintf(&save[k], "<A HREF=\"");
1129 
1130 			k = StrLen(save);
1131 			sprintf(&save[k], TAXurl, tax_id);
1132 			k = StrLen(save);
1133 			sprintf(&save[k], "\">%s</A> ", names[i]);
1134 		}
1135 		else
1136 			sprintf(&save[k], " (unassigned)");
1137 	}
1138 
1139 	k = StrLen(save);
1140 	sprintf(&save[k], "</TD>\n</TR>\n");
1141 	return 1;
1142 
1143 } /* end SaveTaxonomyInfo */
1144 
1145 
1146 
1147 /* Old version of DumpMime, preserved for compatibility with Cn3D v1.0. */
1148 
DumpMime_v1(AsnIoPtr aip,CharPtr title,Int2 style,Int2 choice,VoidPtr datum)1149 static void DumpMime_v1(AsnIoPtr aip, CharPtr title, Int2 style, Int2 choice, VoidPtr datum)
1150 {
1151   NcbiMimeAsn1Ptr mime;
1152   EntrezGeneralPtr egp;
1153 
1154   mime = (NcbiMimeAsn1Ptr) ValNodeNew(NULL);
1155   mime->choice = NcbiMimeAsn1_entrez;
1156   egp = EntrezGeneralNew();
1157   mime->data.ptrvalue = (VoidPtr) egp;
1158   egp->Data_data = ValNodeNew(NULL);
1159   egp->title = StringSave(title);
1160   egp->style = style;
1161   egp->Data_data->choice = choice;
1162   egp->Data_data->data.ptrvalue = datum;
1163 
1164   NcbiMimeAsn1AsnWrite(mime, aip, NULL);
1165   AsnIoFlush(aip);
1166 
1167   egp->Data_data->data.ptrvalue = NULL; /* for clean free */
1168   NcbiMimeAsn1Free(mime);
1169 
1170 } /* end DumpMime_v1 */
1171 
1172 
1173 
1174                                    /* yanli */
DumpMime(AsnIoPtr aip,CharPtr title,VoidPtr datum)1175 static void DumpMime(AsnIoPtr aip, CharPtr title, VoidPtr datum)
1176 {
1177   NcbiMimeAsn1Ptr mime;
1178   EntrezGeneralPtr egp;
1179 
1180   mime = (NcbiMimeAsn1Ptr) ValNodeNew(NULL);
1181   mime->choice = NcbiMimeAsn1_strucseq;
1182   mime->data.ptrvalue= datum;
1183 
1184   NcbiMimeAsn1AsnWrite(mime, aip, NULL);
1185   AsnIoFlush(aip);
1186 
1187   mime->data.ptrvalue=NULL ; /* for clean free */
1188   NcbiMimeAsn1Free(mime);
1189 }
1190 
1191 
1192 
1193 #define LAUNCH_VIEWER	0
1194 #define SEE_FILE	1
1195 #define SAVE_FILE	2
1196 #define SEND_FILE   4
1197 
1198 /* Handle the various View/See/Save file options. */
1199 
1200 static Int4
SendStructureMIME(Char Filetype,Int4 uid,Int4 Mime,Int4 Complexity,Int4 Models,Int4 Color,Int4 Render)1201 SendStructureMIME(Char Filetype, Int4 uid, Int4 Mime, Int4 Complexity,
1202 		  Int4 Models, Int4 Color, Int4 Render)
1203 {
1204   BiostrucPtr bsp;
1205   PDNMS ModelStruc;
1206   Int4 count, i4Sent = 0, error_flag = 0;
1207   AsnIoPtr aip;
1208 
1209   /* yanli start */
1210   NcbiMimeAsn1Ptr mime;
1211   BiostrucSeqPtr bssp;
1212   BiostrucGraphPtr bsgp;
1213   MoleculeGraphPtr mgp;
1214   SeqIdPtr sip;
1215   SeqEntryPtr sep;
1216   Int2 retcode = 3;
1217   Int4 This_uid = 0;
1218 
1219   if ((bsp = MMDBBiostrucGet((DocUid) uid, Complexity, Models)) == NULL) {
1220     printf("Content-type: text/html\r\n\r\n");
1221     printf("<h2>Error</h2>\n");
1222     printf("Structure with UID = %ld failed to fetch on Server<p>\n", (long) uid);
1223     printf("No such structure available on this MMDB server.\n");
1224     return 0;
1225   }
1226 
1227   /*yanli*/
1228   bsgp = bsp->chemical_graph;
1229   mgp = bsgp->molecule_graphs;
1230   sip = mgp->seq_id;
1231   /*  This_uid =  EntrezFindSeqId(sip);    */
1232   while(sip != NULL){
1233     if(sip->choice == 12) This_uid = sip->data.intvalue;
1234     sip = sip->next;
1235   }
1236   sep = EntrezSeqEntryGet(This_uid, retcode);
1237 
1238   bssp = BiostrucSeqNew();
1239   bssp->structure = bsp;
1240   ValNodeLink(&(bssp->sequences), sep);
1241 
1242   mime = (NcbiMimeAsn1Ptr) ValNodeNew(NULL);    /* yanli */
1243   mime->choice = NcbiMimeAsn1_strucseq;
1244   mime->data.ptrvalue = bssp;
1245   /*---yanli*/
1246 
1247   /* the following headers are format-independent */
1248   switch (Mime) {
1249   case SAVE_FILE:
1250     printf("Content-type: application/octet-stream\r\n\r\n");
1251     break;
1252   case SEE_FILE:
1253     printf ("Content-type: text/html\r\n\r\n");
1254     printf ("<HTML><PRE>\r\n");
1255     break;
1256   case SEND_FILE:
1257     printf ("Content-type: text/html\r\n\r\n");
1258     break;
1259   }
1260 
1261   if (Filetype == 'j') {
1262     /* Cn3D v2.0 asn.1 format */
1263     switch (Mime) {
1264     case LAUNCH_VIEWER:
1265       printf ("Content-type: chemical/ncbi-asn1-binary\r\n\r\n");
1266       aip = AsnIoNew(ASNIO_BIN_OUT, stdout, NULL, NULL, NULL);
1267       DumpMime(aip, "MIME", bssp);
1268       break;
1269     case SAVE_FILE:
1270       aip = AsnIoNew(ASNIO_BIN_OUT, stdout, NULL, NULL, NULL);
1271       NcbiMimeAsn1AsnWrite(mime, aip, NULL);
1272       break;
1273     case SEE_FILE:
1274       aip = AsnIoNew(ASNIO_TEXT_OUT, stdout, NULL, NULL, NULL);
1275       NcbiMimeAsn1AsnWrite(mime, aip, NULL);
1276       break;
1277     case SEND_FILE:
1278       aip = AsnIoNew(ASNIO_TEXT_OUT, stdout, NULL, NULL, NULL);
1279       NcbiMimeAsn1AsnWrite(mime, aip, NULL);
1280       break;
1281     }
1282 
1283     AsnIoReset(aip);
1284     AsnIoClose(aip);
1285   }
1286   else if (Filetype == 'i') {
1287     /* Cn3D v1.0 asn.1 format.  Included for backwards compatibility, in case users
1288      * want to stick with their old Cn3D for some reason.
1289      */
1290     switch (Mime) {
1291     case LAUNCH_VIEWER:
1292       printf ("Content-type: chemical/ncbi-asn1-binary\r\n\r\n");
1293       /* printf ("Content-disposition: filename=\"%d.val\"\r\n\r\n", uid);*/
1294       aip = AsnIoNew(ASNIO_BIN_OUT, stdout, NULL, NULL, NULL);
1295       DumpMime_v1(aip, "MIME", Entrez_style_report, Data_data_structure, bsp);
1296       break;
1297     case SAVE_FILE:
1298       aip = AsnIoNew(ASNIO_BIN_OUT, stdout, NULL, NULL, NULL);
1299       BiostrucAsnWrite(bsp, aip, NULL);
1300       break;
1301     case SEE_FILE:
1302       aip = AsnIoNew(ASNIO_TEXT_OUT, stdout, NULL, NULL, NULL);
1303       BiostrucAsnWrite(bsp, aip, NULL);
1304       break;
1305     case SEND_FILE:
1306       aip = AsnIoNew(ASNIO_TEXT_OUT, stdout, NULL, NULL, NULL);
1307       BiostrucAsnWrite(bsp, aip, NULL);
1308       break;
1309     }
1310 
1311     AsnIoReset(aip);
1312     AsnIoClose(aip);
1313   }
1314   else if (Filetype == 'r') {
1315     /* RasMol format */
1316     if (Mime == LAUNCH_VIEWER)
1317       printf ("Content-type: chemical/x-pdb\r\n\r\n");
1318     /*      printf ("Content-disposition: filename=\"%d.pdb\"\r\n\r\n", uid);*/
1319 
1320     ModelStruc = MakeAModelstruc(bsp);
1321     bssp->structure = NULL;  /* already linked into modelstruc */
1322     WritePDBAllModel(ModelStruc, stdout);
1323     ClearStructures();
1324   }
1325   else if (Filetype == 'k') {
1326     /* Mage format */
1327     if (Mime == LAUNCH_VIEWER)
1328       printf ("Content-type: chemical/x-kinemage\r\n\r\n");
1329     /* printf ("Content-disposition: filename=\"%d.kin\"\r\n\r\n", uid);*/
1330 
1331     ModelStruc = MakeAModelstruc(bsp);
1332     bssp->structure = NULL;  /* already linked into modelstruc */
1333     WriteKinAllModel(ModelStruc, stdout, Color, Render);
1334     ClearStructures();
1335   }
1336   else {
1337     error_flag = 1;
1338     printf("Content-type: text/html\r\n\r\n");
1339     printf("<h2>Error</h2>\n");
1340     printf("Unknown file type on structure fetch.<p>\n");
1341     printf("Contact %s\n", MAILTO);
1342   }
1343 
1344   if ((Mime == SEE_FILE) && (!error_flag))
1345     printf ("</PRE></HTML>\r\n");
1346 
1347   NcbiMimeAsn1Free(mime);           /* yanli */
1348   return 1;
1349 
1350 } /* end SendStructureMIME */
1351 
1352 
SendSummaryPage(Int4Ptr Uids,Int4 NumToDisplay,Int4 Save)1353 static Int4  SendSummaryPage(Int4Ptr Uids, Int4 NumToDisplay, Int4 Save)
1354 {
1355   BiostrucPtr bsp;
1356   ValNodePtr descr;
1357   PDNMS ModelStruc;
1358   Int4 uid, count, i4Sent = 0;
1359   Int2 taxret;
1360   Char tax_save[MAX_TBUFF];
1361   FILE *sendfile;
1362 
1363   if (Save == 2)
1364     printf ("Content-type: application/octet-stream\n\n");
1365   else
1366     printf ("Content-type: text/html\n\n");
1367 
1368   if (!GlobalNonHtmlOutput) {
1369     if (GlobalTitles)
1370       WWWPrintFileData(HEADFILE,  stdout);
1371     else
1372       printf ( "<html>\n<title>MMDB Structure Summary</title><body>");
1373   }
1374   for (count = 0; count < NumToDisplay; count++)
1375     {
1376       uid = Uids[count];
1377       bsp = MMDBBiostrucGet((DocUid) uid,3,0);
1378       if (bsp == NULL)
1379 	{
1380 	  printf ("%sNo structure found for UID %ld.%s\n",
1381 		  GlobalNonHtmlOutput ? "\n" : "<P><h4>",uid,
1382 		  GlobalNonHtmlOutput ? "\n" : "</h4><P>");
1383 	  if (!GlobalNonHtmlOutput)
1384 	    printf ("<HR SIZE=5 NOSHADE><BR>\n");
1385 	  continue;
1386 	}
1387 
1388       if (!GlobalNonHtmlOutput) {
1389 	CharPtr name;
1390 
1391 	for (descr = bsp->descr, name = NULL; descr != NULL; descr = descr->next) {
1392 	  if (descr->choice == BiomolDescr_name) {
1393 	    name = descr->data.ptrvalue;
1394 	    break;
1395 	  }
1396 	}
1397 	taxret = SaveTaxonomyInfo(bsp, tax_save, MAX_TBUFF, name);
1398       }
1399 
1400       ModelStruc = MakeAModelstruc(bsp);
1401       PrintStructureInfo(ModelStruc, stdout, (taxret) ? tax_save : NULL);
1402 
1403       if (!GlobalNonHtmlOutput) /* Rest of View/Save stuff */
1404 	{
1405 	  PrintStructureLinks(ModelStruc, stdout);
1406 	  PrintStructureView(ModelStruc,  stdout);
1407 	  printf ("<HR SIZE=5 NOSHADE><BR>\n");
1408 	}
1409 
1410       ClearStructures();
1411     }
1412   if (!GlobalNonHtmlOutput)
1413     if (GlobalTitles)
1414       WWWPrintFileData(TAILFILE, stdout);
1415     else
1416       printf ("</html>");
1417 
1418   return 1;
1419 } /* SendSummaryPage() */
1420 
1421 
SendGetNetscape(void)1422 static void SendGetNetscape(void) {
1423 
1424   printf("HTTP/1.0 200 OK\r\n");
1425   printf("MIME-Version: 1.0\r\n");
1426   printf("Content-type: text/html\r\n\r\n");
1427   printf("<BR><BR><B>Sorry, you need a <a href=\"http://home.netscape.com/\">",
1428          "Netscape</a> version 2 or higher WWW-browser "
1429          "to be able to enter this page</B><BR>\n\n");
1430 }  /* SendGetNetscape */
1431 
1432 
1433 
1434 
InitMMDBSrv(void)1435 static Boolean InitMMDBSrv(void)
1436 {
1437   Int2 i;
1438 
1439   HTMLPath[0] = '\0';
1440   URLBase[0] = '\0';
1441   URLHelp[0] = '\0';
1442   CGIPath[0] = '\0';
1443   URLcgi[0] = '\0';
1444   CGIName[0] = '\0';
1445   DATApath[0] = '\0';
1446   LOGpath[0] = '\0';
1447   ENTREZurl[0] = '\0';
1448   VASTurl[0] = '\0';
1449   MMDBurl[0] = '\0';
1450   PDBurl[0] = '\0';
1451   TDBurl[0] = '\0';
1452   MAILto[0] = '\0';
1453 
1454   for (i = 0; i < PATH_MAX; i++)
1455     TAXurl[i] = '\0';
1456 
1457   FindPath("mmdb", "MMDBSRV", "HTMLPath", HTMLPath, PATH_MAX);
1458   if (HTMLPath[0] == '\0')
1459     {
1460       	ErrPostEx(SEV_FATAL,0,0, "MMDB config file \nMMDBSRV section no HTMLPath...\n");
1461 	return FALSE;
1462     }
1463   GetAppParam("mmdb", "MMDBSRV", "URLBase", "", URLBase, PATH_MAX);
1464   if (URLBase[0] == '\0')
1465     {
1466       	ErrPostEx(SEV_FATAL,0,0, "MMDB config file \nMMDBSRV section no URLBase...\n");
1467 	return FALSE;
1468     }
1469   GetAppParam("mmdb", "MMDBSRV", "URLHelp", "", URLHelp, PATH_MAX);
1470   if (URLHelp[0] == '\0')
1471     {
1472       	ErrPostEx(SEV_FATAL,0,0, "MMDB config file \nMMDBSRV section no URLHelp...\n");
1473 	return FALSE;
1474     }
1475   FindPath("mmdb", "MMDBSRV", "CGIPath", CGIPath, PATH_MAX);
1476   if (CGIPath[0] == '\0')
1477     {
1478       	ErrPostEx(SEV_FATAL,0,0, "MMDB config file \nMMDBSRV section no CGIPath...\n");
1479 	return FALSE;
1480     }
1481 
1482   GetAppParam("mmdb", "MMDBSRV", "URLcgi", "", URLcgi, PATH_MAX);
1483   if (URLcgi[0] == '\0')
1484     {
1485       	ErrPostEx(SEV_FATAL,0,0, "MMDB config file \nMMDBSRV section no URLcgi...\n");
1486 	return FALSE;
1487     }
1488   GetAppParam("mmdb", "MMDBSRV", "CGIName", "", CGIName, (size_t) 256 *  sizeof(char));
1489   if (CGIName[0] == '\0')
1490     {
1491       	ErrPostEx(SEV_FATAL,0,0, "MMDB config file \nMMDBSRV section no CGIName...\n");
1492 	return FALSE;
1493     }
1494   FindPath("mmdb", "MMDBSRV", "DATApath", DATApath, PATH_MAX);
1495   if (DATApath[0] == '\0')
1496     {
1497       	ErrPostEx(SEV_FATAL,0,0, "MMDB config file \nMMDBSRV section no DATApath...\n");
1498 	return FALSE;
1499     }
1500   ARROW[0] = '\0';
1501   sprintf(ARROW, "<IMG alt=\"o\" SRC=\"%sarrow.gif\" ALT=\"o\" BORDER=0>\n", URLBase);
1502 
1503   FindPath("mmdb", "MMDBSRV", "LOGpath", LOGpath, PATH_MAX);
1504   if (LOGpath[0] == '\0')
1505     {
1506       	ErrPostEx(SEV_FATAL,0,0, "MMDB config file \nMMDBSRV section no LOGpath...\n");
1507 	return FALSE;
1508     }
1509   GetAppParam("mmdb", "MMDBSRV", "ENTREZurl", "", ENTREZurl, PATH_MAX);
1510   if (ENTREZurl[0] == '\0')
1511     {
1512       	ErrPostEx(SEV_FATAL,0,0, "MMDB config file \nMMDBSRV section no ENTREZurl...\n");
1513 	return FALSE;
1514     }
1515   GetAppParam("mmdb", "MMDBSRV", "VASTurl", "", VASTurl, PATH_MAX);
1516   if (VASTurl[0] == '\0')
1517     {
1518       	ErrPostEx(SEV_FATAL,0,0, "MMDB config file \nMMDBSRV section no VASTurl...\n");
1519 	return FALSE;
1520     }
1521   GetAppParam("mmdb", "MMDBSRV", "MMDBurl", "", MMDBurl, PATH_MAX);
1522   if (MMDBurl[0] == '\0')
1523     {
1524       	ErrPostEx(SEV_FATAL,0,0, "MMDB config file \nMMDBSRV section no MMDBurl...\n");
1525 	return FALSE;
1526     }
1527   GetAppParam("mmdb", "MMDBSRV", "PDBurl", "", PDBurl, PATH_MAX);
1528   if (PDBurl[0] == '\0')
1529     {
1530       	ErrPostEx(SEV_FATAL,0,0, "MMDB config file \nMMDBSRV section no PDBurl...\n");
1531 	return FALSE;
1532     }
1533   GetAppParam("mmdb", "MMDBSRV", "TDBurl", "", TDBurl, PATH_MAX);
1534   if (TDBurl[0] == '\0')
1535     {
1536       	ErrPostEx(SEV_FATAL,0,0, "MMDB config file \nMMDBSRV section no TDBurl...\n");
1537 	return FALSE;
1538     }
1539   GetAppParam("mmdb", "TAXLINK", "TAXurl", "", TAXurl, PATH_MAX);
1540   if (TAXurl[0] == '\0')
1541     {
1542       	ErrPostEx(SEV_FATAL,0,0, "MMDB config file \nTAXLINK section no TAXurl...\n");
1543 	return FALSE;
1544     }
1545   StringCat(TAXurl, "?id=%d&lvl=0");
1546   GetAppParam("mmdb", "MMDBSRV", "MAILto", "", MAILto, PATH_MAX);
1547   if (MAILto[0] == '\0')
1548     {
1549       	ErrPostEx(SEV_FATAL,0,0, "MMDB config file \nMMDBSRV section no Mailto...\n");
1550 	return FALSE;
1551     }
1552 
1553   MAILTO[0] = '\0';
1554   sprintf(MAILTO, "&lt <a href=\"%s\">%s</a> &gt",  MAILto,  MAILto);
1555 
1556   return TRUE;
1557 }
1558 
1559 
1560 
1561 /************************************************************************
1562  *
1563  *  Int2 Main() - main function
1564  *
1565  ***********************************************************************/
1566 
1567 
1568 
Main()1569 Int2 Main ()
1570 {
1571   Boolean 		Netscape2_OK = FALSE;
1572   time_t 		time_now;
1573   CharPtr 		TimeNowStr = NULL;
1574   WWWErrorCode 		error;
1575   Int4                  IndexArgs = -1;
1576   Int4 			Complex = 0;
1577   Int4 			MaxModels = 1;
1578   Int4 			KinColor = 0;
1579   Int4 			KinRender = 0;
1580   Int4 			Save = 0;
1581   Char 			DispOpt = '\0';
1582   Int4                  Form = 0;
1583   CharPtr 		pcThis = NULL,  pcName = NULL;
1584   CharPtr 		Uids;  /* (list of MMDB ids or PDB ids) */
1585   Int4Ptr 		MMDBids = NULL; /* (list of MMDB ids ) */
1586   Int4                  iMMDBids = 0;
1587   Int4			iCount = 0;
1588   Int4			iBytes = 0;
1589   Int4			NumEntries = 0;
1590   ValNodePtr		pvnUIDS = NULL, pvnThis = NULL;
1591 
1592 /* this sets up the unix time limit */
1593 
1594 #ifdef OS_UNIX
1595  {
1596   struct rlimit		rl;
1597   getrlimit(RLIMIT_CPU, &rl);
1598   rl.rlim_max = rl.rlim_cur = CPUTIME_MAX;
1599   setrlimit(RLIMIT_CPU, &rl);
1600  }
1601 #endif
1602 
1603   if (!InitMMDBSrv()) {
1604        printf("Content-type: text/html\r\n\r\n");
1605        printf("<H2>MMDBSRV Error</H2>\n - Unable to Open Server Configuration File.<p>\n");
1606        printf("Contact the MMDBSRV administrator for this site.<p>\n");
1607 	exit(1);
1608   }
1609 
1610   StringCat(LOGpath, "mmdbsrv.log");
1611   if( !ErrSetLogfile (LOGpath, ELOG_APPEND) ) {
1612       printf("Content-type: text/html\r\n\r\n");
1613       printf("<H2>MMDBSRV Error</H2>\n - Unable to Open Log.<p>\n");
1614       printf("Contact MMDBSRV administrator for this site: %s<p>\n",  MAILTO);
1615 	exit(1);
1616   }
1617 
1618   ErrSetLogLevel(SEV_MAX);
1619   ErrSetOpts (ERR_CONTINUE, ERR_LOG_ON);
1620 
1621 
1622 
1623   if((error = WWWGetArgs(&info)) != WWWErrOk) {
1624       printf("Content-type: text/html\r\n\r\n");
1625       printf("<H2>MMDBSRV Error</H2>\n Failed to Process Posting - Check your GET/POST syntax\n");
1626     goto earlyout;
1627   }
1628 
1629 
1630  /* if(WWWGetBrowser(info) != NETSCAPE) {
1631        SendGetNetscape();
1632        exit(1);
1633   } */
1634 
1635   if ((!OpenMMDBAPI(0, NULL)) || (!MMDBInit()))
1636     {
1637        ErrLogPrintf("#MMDB Database Access Failed to Initialize.\n");
1638        printf("Content-type: text/html\r\n\r\n");
1639        printf("<H2>MMDBSRV Error</H2>\n - Unable to Open MMDB Database on Server.<p>");
1640        printf("Contact MMDBSRV administrator for this site: %s<p>\n",  MAILTO);
1641 	exit(1);
1642     }
1643                                                    /* yanli */
1644    if (EntrezInit("mmdbsrv", NULL, FALSE) == FALSE)
1645      {
1646        printf("Content-type: text/html\n\n");
1647        printf("<h2>Error</h2>\n");
1648        printf("MMDBSERV: EntrezInit Failed.<p>\n");
1649        return;
1650      }
1651                                                    /* yanli */
1652 /*if( !BioseqFetchInit(TRUE))
1653     {
1654       ErrLogPrintf("BioseqFetchInit failed! \n");
1655       printf("Content-type: text/html\r\n\r\n");
1656       printf("<H2>MMDBSRV Error</H2>\n - BioseqFetchInit failed! <p>");
1657       printf("Contact MMDBSRV administrator for this site: %s<p>\n",  MAILTO);
1658     exit(1);
1659     }   */
1660 
1661     SeqAsnLoad();
1662     objmimeAsnLoad();
1663 
1664   IndexArgs = -1;
1665   if ((IndexArgs = WWWFindName(info,"db")) >= 0)
1666     {
1667       pcThis = WWWGetValueByIndex(info,IndexArgs);
1668       DispOpt = pcThis[0];
1669       if ((DispOpt != 't') && (DispOpt != 'T'))
1670         {
1671           printf("Content-type: text/html\r\n\r\n");
1672           printf("<H2>MMDBSRV Error</H2>\n - Wrong Database Type db=%c.<p>\n",  DispOpt );
1673           printf("Try <a href=\"%s\">WWW-Entrez</a> for this<p>\n",  URLHelp);
1674 	  goto cleanout;
1675         }
1676     }
1677 
1678   IndexArgs = -1;
1679   if ((IndexArgs = WWWFindName(info, "form")) >= 0)
1680     {
1681       pcThis = WWWGetValueByIndex(info,IndexArgs);
1682       if ((!StrToInt4(pcThis,&Form)) || (Form != 6))
1683         {
1684           printf("Content-type: text/html\r\n\r\n");
1685           printf("<H2>MMDBSRV Error</H2>\n - Wrong Form Type form=%s.<p>\n",  pcThis );
1686           printf("<pre>Only supports form=6</pre><p>\n");
1687           printf("Try <a href=\"%s\">WWW-Entrez</a> for this<p>\n",  URLHelp);
1688 	  goto cleanout;
1689         }
1690     }
1691 
1692 
1693 
1694 
1695  IndexArgs = -1;
1696  if ((IndexArgs = WWWFindName(info, "uid")) < 0)
1697    {
1698        printf("Content-type: text/html\r\n\r\n");
1699        printf("<H2>MMDBSRV Error</H2>\n - No Identifier specified:<p>\n<pre>Missing uid=</pre><p>\n");
1700        goto cleanout;
1701    }
1702  else
1703    {
1704      /* loop over entire set of tag=value entries and add all the UID's found together */
1705      /* must handle uid=1234&uid=1OMD&uid=1234,2345,2134&dopt=s&uid=3INS              */
1706       NumEntries = WWWGetNumEntries(info);
1707       for (IndexArgs = 0; IndexArgs < NumEntries; IndexArgs++)
1708         {
1709 	    pcName = WWWGetNameByIndex(info,  IndexArgs);
1710 	    pcThis = WWWGetValueByIndex(info,  IndexArgs);
1711 
1712 	    if (StrICmp(pcName, "uid") == 0)
1713 	      {
1714 	 /*         printf("[%s][%s]\n", pcThis, pcName);  */
1715                   MakeUIDList(pcThis, &pvnUIDS);
1716 	      }
1717 	}
1718      if (pvnUIDS == NULL)
1719          {
1720 	    printf("Content-type: text/html\r\n\r\n");
1721             printf("<H2>MMDBSRV Error</H2>\n - UID specified does not match an MMDB-ID or PDB-Code:<p>\n");
1722             goto cleanout;
1723 	 }
1724      pvnThis = pvnUIDS;
1725      while (pvnThis)
1726        {
1727           iMMDBids++;
1728           pvnThis = pvnThis->next;
1729        }
1730      MMDBids = (Int4Ptr) MemNew((size_t) (sizeof(Int4) * iMMDBids));
1731      pvnThis = pvnUIDS;
1732      iCount = 0;
1733      while (pvnThis)
1734      {
1735           MMDBids[iCount] =  (Int4) pvnThis->data.intvalue;
1736 /* printf("%ld \n",(long) MMDBids[iCount]); */
1737           pvnThis = pvnThis->next;
1738 	  iCount++;
1739      }
1740    }
1741 
1742   DispOpt = ' ';
1743   IndexArgs = -1;
1744   if ((IndexArgs = WWWFindName(info, "dopt")) >= 0)
1745     {
1746       pcThis = WWWGetValueByIndex(info,IndexArgs);
1747       switch (pcThis[0])
1748       {
1749 	 case 's':
1750 	 case 'S':
1751 	    DispOpt = 's';
1752 	   break;
1753 	 case 'r':
1754 	 case 'R':
1755 	    DispOpt = 'r';
1756 	   break;
1757 	 case 'i':
1758 	 case 'I':
1759 	    DispOpt = 'i';
1760 	   break;
1761 	 case 'j':
1762 	 case 'J':
1763 		DispOpt = 'j';
1764 		break;
1765 	 case 'k':
1766 	 case 'K':
1767 	     DispOpt = 'k';
1768 	   break;
1769          case 'a':
1770          case 'A':
1771              DispOpt = 'a';
1772              Save = 1;
1773           break;
1774          default:
1775 	    {
1776 	    printf("Content-type: text/html\r\n\r\n");
1777 	    printf("<H2>MMDBSRV Error</H2>\n - Wrong Display Option Type: dopt=%s.<p>\n",  pcThis);
1778 	    printf("<pre>dopt supports:\n's' Structure summary\n");
1779 	    printf("'r' RasMol(PDB) format\n'k' Kinemage format\n'i', 'j', or 'a' ASN.1</pre><p>\n");
1780 	    goto cleanout2;
1781 	    }
1782       }
1783     }
1784   else
1785     {
1786 	DispOpt = 's';  /* structure summary is default when no dopt supplied */
1787     }
1788 
1789 
1790   IndexArgs = -1;
1791   if ((IndexArgs = WWWFindName(info, "Complexity")) >= 0)
1792     {
1793       pcThis = WWWGetValueByIndex(info,IndexArgs);
1794 
1795 
1796 	  for (iCount = 0; iCount < NUM_COMPLEXITY_TYPES; iCount++)
1797 	    if (StrICmp(pcThis,ComplexityDescriptions[iCount]) == 0)
1798 	      break;
1799 
1800 	  Complex = ALLMDL;
1801 	  MaxModels = 1;
1802 
1803 	  switch (iCount)
1804 	    {
1805 	    case 0 :
1806 	     Complex = ONECOORDRES;
1807 	     break;
1808 	    case 1:
1809 	     Complex = ONECOORDATOM;
1810 	     break;
1811 	    case 2:
1812 	     MaxModels = 5;
1813 	     break;
1814 	    case 3 :
1815 	     MaxModels = 10;
1816 	     break;
1817 	    case 4 :
1818 	     MaxModels = INT2_MAX;
1819 	     break;
1820 	    case 5:
1821 	     Complex = ONECOORDATOM;
1822 	      break;
1823 	    default:
1824 	       {
1825 		printf("Content-type: text/html\r\n\r\n");
1826 		printf("<H2>MMDBSRV Error</H2>\n - Wrong Complexity Type: Complexity=%s.<p>\n", pcThis );
1827 		goto cleanout2;
1828 	       }
1829 	    }
1830     }
1831 
1832   IndexArgs = -1;
1833   if ((IndexArgs = WWWFindName(info, "mdlLvl")) >= 0)
1834     {
1835       pcThis = WWWGetValueByIndex(info, IndexArgs);
1836       Complex = atoi(pcThis);
1837     }
1838 
1839   IndexArgs = -1;
1840   if ((IndexArgs = WWWFindName(info, "maxModels")) >= 0)
1841     {
1842       pcThis = WWWGetValueByIndex(info, IndexArgs);
1843       MaxModels = atoi(pcThis);
1844     }
1845 
1846   IndexArgs = -1;
1847   if ((IndexArgs = WWWFindName(info, "KinemageColor")) >= 0)
1848     {
1849       pcThis = WWWGetValueByIndex(info, IndexArgs);
1850       KinColor = GetOptionValue(pcThis, NUM_COLOR_TYPES, ColorDescriptions);
1851     }
1852 
1853 
1854 
1855   IndexArgs = -1;
1856   if ((IndexArgs = WWWFindName(info, "KinemageRender")) >= 0)
1857     {
1858       pcThis = WWWGetValueByIndex(info,IndexArgs);
1859       StrToInt4(pcThis, &KinRender);
1860     }
1861 
1862   IndexArgs = -1;
1863   if ((IndexArgs = WWWFindName(info, "save")) >= 0)
1864     {  /* these don't affect structure summaries */
1865       pcThis = WWWGetValueByIndex(info,IndexArgs);
1866       if (StrICmp(pcThis, "See") == 0)
1867         {
1868 	    Save = 1;  /* sends MIMED-type files to view in ascii-readable form */
1869 	}
1870       else if (StrICmp(pcThis, "Save") == 0)
1871         {
1872 	    Save = 2;  /* sends MIMED-type files in raw save form */
1873 	}
1874       else if (StrICmp(pcThis, "M") == 0)
1875         {
1876 	    Save = 3;  /* MacSave - not implemented */
1877 	}
1878       else if (StrICmp(pcThis, "asntext") == 0)
1879         {
1880 	    Save = SEND_FILE;  /* writes out asn text without the html header */
1881 	}
1882     }
1883 
1884   IndexArgs = -1;
1885   if ((IndexArgs = WWWFindName(info, "header")) >= 0)
1886     {
1887       pcThis = WWWGetValueByIndex(info,IndexArgs);
1888       if (StrICmp(pcThis, "no") == 0)
1889         {
1890 	    Save = 2;
1891 	}
1892     }
1893 
1894 
1895   IndexArgs = -1;
1896   if ((IndexArgs = WWWFindName(info, "title")) >= 0)
1897     {
1898       pcThis = WWWGetValueByIndex(info,IndexArgs);
1899       if (StrICmp(pcThis, "no") == 0)
1900         {
1901 
1902           GlobalTitles = FALSE;
1903 	}
1904     }
1905 
1906   IndexArgs = -1;
1907   if ((IndexArgs = WWWFindName(info, "html")) >= 0)
1908     {
1909       pcThis = WWWGetValueByIndex(info,IndexArgs);
1910       if (StrICmp(pcThis, "no") == 0)
1911         {
1912           GlobalNonHtmlOutput = TRUE;
1913 	  GlobalTitles = FALSE;
1914 	}
1915     }
1916 
1917 
1918 
1919 /* call the pertinent Page Sender */
1920 
1921  if  (DispOpt == 's')
1922    {
1923        iBytes = SendSummaryPage(MMDBids, iMMDBids,  Save);
1924    }
1925  else
1926    {
1927         iBytes = SendStructureMIME(DispOpt,  MMDBids[0], Save  ,
1928                          Complex, MaxModels,  KinColor, KinRender);
1929    }
1930 
1931 
1932    MemFree(MMDBids);
1933 
1934    /* log first MMDB-id, number of id's asked for, number of bytes sent */
1935    time_now = GetSecs();
1936    TimeNowStr = ctime(&time_now);
1937    TimeNowStr[24] = '\0';
1938    ErrLogPrintf("\n%s|%s|%s|%s|Do %c|Id %ld|No %ld|By %ld|Sv %ld|Cp %ld|Md %ld|Kc %ld|Kr %ld",
1939                 WWWGetAddress(info), WWWGetHost(info), WWWGetAgent(info), TimeNowStr,
1940                 (char) DispOpt,
1941                 (long) MMDBids[0], (long) iMMDBids, (long)iBytes, (long) Save,
1942                 (long) Complex, (long) MaxModels, (long) KinColor, (long) KinRender);
1943 
1944 
1945   CloseMMDBAPI();
1946   MMDBFini();
1947   fflush(stdout);
1948   exit(0);
1949 
1950 cleanout2:
1951   MemFree(MMDBids);
1952   CloseMMDBAPI();
1953   MMDBFini();
1954   /* log first MMDB-id, number of id's asked for, number of bytes sent */
1955    time_now = GetSecs();
1956    TimeNowStr = ctime(&time_now);
1957    TimeNowStr[24] = '\0';
1958    ErrLogPrintf("\n#Syntax Error %s|%s|%s|%s|%ld",
1959                 WWWGetAddress(info), WWWGetHost(info), WWWGetAgent(info), TimeNowStr,
1960                 (long)iBytes);
1961    fflush(stdout);
1962    exit(0);
1963 
1964 cleanout:
1965   CloseMMDBAPI();
1966   MMDBFini();
1967   /* log first MMDB-id, number of id's asked for, number of bytes sent */
1968    time_now = GetSecs();
1969    TimeNowStr = ctime(&time_now);
1970    TimeNowStr[24] = '\0';
1971    ErrLogPrintf("\n#Query Not Supported %s|%s|%s|%s|%ld",
1972                 WWWGetAddress(info), WWWGetHost(info), WWWGetAgent(info), TimeNowStr,
1973                 (long)iBytes);
1974    fflush(stdout);
1975    exit(0);
1976 
1977 earlyout:
1978    time_now = GetSecs();
1979    TimeNowStr = ctime(&time_now);
1980    TimeNowStr[24] = '\0';
1981    ErrLogPrintf("\n#Get/Post Error %s|%s|%s|%s|%ld",
1982                 WWWGetAddress(info), WWWGetHost(info), WWWGetAgent(info), TimeNowStr,
1983                  (long)iBytes);
1984 
1985 
1986   fflush(stdout);
1987   exit(0);
1988 }
1989 
1990