1 /* $Id: wwwutils.c,v 6.18 2003/05/05 12:17:32 rsmith 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: wwwutils.c,v $
27 *
28 * Author:  Sergei Shavirin
29 *
30 * Version Creation Date: 11/03/1996
31 *
32 * $Revision: 6.18 $
33 *
34 * File Description:
35 *   This file contains functions to read and process HTTP
36 *   protocols input for WWW CGI programs
37 *   Currently it works for all ncbi supported platforms.
38 *
39 *---------------------------------------------------------------------------
40 * $Log: wwwutils.c,v $
41 * Revision 6.18  2003/05/05 12:17:32  rsmith
42 * Codewarrior compiling for Win32 does not know about setmode
43 *
44 * Revision 6.17  2002/02/07 14:48:22  ivanov
45 * Added WWWGetEntriesEx(), WWWGetEntriesFormDataEx(), WWWReadFileInMemoryEx(),
46 * WWWGetValueSizeByIndex() -- support binary files in the multipart form-data.
47 *
48 * Revision 6.16  2002/02/01 18:05:42  ivanov
49 * Little changes in WWWGetArgsInternal()
50 *
51 * Revision 6.15  2002/01/29 20:22:24  ivanov
52 * Added missed realization WWWGetArgsEx()
53 *
54 * Revision 6.14  2002/01/29 15:28:48  ivanov
55 * Typo fixed
56 *
57 * Revision 6.13  2002/01/28 21:27:00  ivanov
58 * Added WWWGetArgsEx() and WWWGetArgsAttr_...() functions.
59 * Added structure SWWWGetArgsAttr definition.
60 *
61 * Revision 6.12  2001/05/10 14:58:34  shavirin
62 * Fixed typo.
63 *
64 * Revision 6.11  2001/05/09 19:25:35  shavirin
65 * Added function WWWGetProxiedIP() to get 'real' address of the client
66 * using PROXIED_IP environment set by proxy server.
67 *
68 * Revision 6.10  2000/03/16 16:34:47  shavirin
69 * Removed check for NetscapeOK in case of mutipart/form-data protocol.
70 *
71 * Revision 6.9  1999/09/29 19:08:29  shavirin
72 * Added new functions: WWWGetLastValueByName and WWWFindNameEx
73 *
74 * Revision 6.8  1999/01/26 19:43:28  vakatov
75 * Adopted for 32-bit MS-Windows DLLs
76 *
77 * Revision 6.7  1998/06/11 19:00:04  shavirin
78 * Fixed some compiler warnings.
79 *
80 * Revision 6.6  1998/05/21 14:41:46  shavirin
81 * Made more user- freandly to Microsoft Internet Explorer.
82 *
83 * Revision 6.5  1998/05/21 14:21:18  shavirin
84 * Increased buffer size for boundary string in Form-data parser.
85 *
86 * Revision 6.4  1997/11/26 21:26:35  vakatov
87 * Fixed errors and warnings issued by C and C++ (GNU and Sun) compilers
88 *
89 * Revision 6.3  1997/11/06 23:04:40  vakatov
90 * WWWInfoFree(), WWWGetValueBy...() -- check for "info->entries" != NULL
91 * for the special case -- first cmd.-line arg exists AND is ""(empty string)
92 *
93 * Revision 6.2  1997/10/29 02:45:53  vakatov
94 * Type castings to pass through the C++ compiler
95 *
96 * Revision 6.1  1997/10/28 23:57:32  vakatov
97 * WWWInfoFree() -- fixed mem.leak(free num_entries+1 items)
98 *
99 * Revision 5.4  1997/06/23 15:10:33  shavirin
100 * Added new functions WWWSubstututeValue() and WWWSubstituteValueByName()
101 *
102 * Revision 5.3  1997/06/10 18:52:35  shavirin
103 * Added StringSave(info->query) in WWWReadPosting()
104 *
105 * Revision 5.2  1997/05/23 15:18:43  shavirin
106 * Fixed few warnings detected by Windows NT C++ compiler
107 *
108 * Revision 5.1  1997/05/09 16:01:27  vakatov
109 * "ncbicoll.[ch]" is not being used anywhere anymore -- remove it!
110 * Move "ncbiwww.h" and "wwwutils.c" from /network/www2(ncbiwww2.lib)
111 * to /corelib(ncbi.lib)
112 *
113 * Revision 1.12  1997/04/04  21:28:36  savchuk
114 * WWWInfoNew() is static now.
115 * Fixed "Out of bounds write" problem in the function WWWGetEntries()
116 *
117 * Revision 1.11  1997/04/03  17:31:09  shavirin
118 * Fixed memory leakage in WWWGetEntries()
119 *
120 * Revision 1.10  1997/03/06  19:06:31  shavirin
121 * Fixed bug with function WWWGetAddress()
122 *
123 * Revision 1.9  1997/02/26  15:20:26  shavirin
124 * Added function WWWGetDocRoot()
125 *
126 * Revision 1.8  1997/02/21  02:26:38  shavirin
127 * Added check for NULL buffer in post method
128 *
129 * Revision 1.7  1996/12/19  19:37:25  shavirin
130 * Fixed problem with form-data protocol handling.
131 *
132 * Revision 1.6  1996/12/13  22:54:16  shavirin
133 * Added new functions WWWGetServer(), WWWGetQuery(). removed bug
134 * in function WWWGetArgs()
135 *
136 * Revision 1.5  1996/12/13  16:46:17  shavirin
137 * WWWGetArgsInternal changed to "static"
138 *
139 * Revision 1.4  1996/12/12  19:25:34  shavirin
140 * Added new functions WWWGetArgs() and static function WWWGetArgsInternal()
141 *
142 * Revision 1.3  1996/12/11  18:14:35  shavirin
143 * Main WWWInfoPtr changed to Void Pointer to hide real structure,
144 * that called now WWWInfoDataPtr
145 * Added set of new function to get specific information from
146 * WWWInfoPtr.
147 * ==========================================================================
148 */
149 
150 #include <ncbiwww.h>
151 
152 #ifdef WIN32          /* for setmode() */
153 #  include <fcntl.h>
154 #  include <io.h>
155 #endif
156 
157 
158 /****************************************************************************/
159 /* INTERNAL STRUCTURES DEFINITIONS */
160 /****************************************************************************/
161 
162 typedef struct SWWWGetArgsAttr_tag
163 {
164     Boolean filter_non_print;       /* filtering non-printable characters */
165     Boolean read_argv;              /* read arguments from command line   */
166 } SWWWGetArgsAttrData;
167 
168 
169 /****************************************************************************/
170 /* STATIC FINCTION DEFINITIONS */
171 /****************************************************************************/
172 
173 static void WWWGetWord(CharPtr word, CharPtr line, Char stop);
174 static void PlusToSpace(CharPtr str);
175 static void WWWUnescapeUrl(CharPtr url);
176 static Char WWWx2c(CharPtr what);
177 static Boolean WWWReadEnvironment(WWWInfoDataPtr info);
178 static WWWErrorCode WWWGetArgsInternal(WWWInfoPtr PNTR info,
179                                        SWWWGetArgsAttr attr);
180 static WWWInfoPtr WWWInfoNew(void);
181 
182 /****************************************************************************/
183 /* EXTERNAL FINCTION */
184 /****************************************************************************/
185 
WWWInfoFree(WWWInfoPtr info_in)186 NLM_EXTERN void WWWInfoFree(WWWInfoPtr info_in)
187 {
188     WWWInfoDataPtr info = (WWWInfoDataPtr)info_in;
189 
190     if( !info )
191         return;
192 
193     info->server_name = (CharPtr) MemFree(info->server_name);
194     info->script_name = (CharPtr) MemFree(info->script_name);
195     info->host        = (CharPtr) MemFree(info->host);
196     info->address     = (CharPtr) MemFree(info->address);
197     info->proxied_ip  = (CharPtr) MemFree(info->proxied_ip);
198     info->agent       = (CharPtr) MemFree(info->agent);
199     info->doc_root    = (CharPtr) MemFree(info->doc_root);
200     info->query       = (CharPtr) MemFree(info->query);
201     if ( info->entries ) {
202         Int4 i;
203         for (i=0;  i <= info->num_entries;  i++) {
204             info->entries[i]->name = (CharPtr) MemFree(info->entries[i]->name);
205             info->entries[i]->val  = (CharPtr) MemFree(info->entries[i]->val);
206             info->entries[i]       = (WWWEntryPtr) MemFree(info->entries[i]);
207         }
208         info->entries = (WWWEntryPtr PNTR) MemFree(info->entries);
209     }
210     info = (WWWInfoDataPtr) MemFree(info);
211 }
212 
213 
214 /* ----------------------  WWWInfoNew  -------------------------
215    Purpose:     Allocates WWWInfo structure
216    Parameters:  None
217    Returns:     WWWInfo structure
218   ------------------------------------------------------------------*/
219 
WWWInfoNew(void)220 static WWWInfoPtr WWWInfoNew(void)
221 {
222     return (WWWInfoPtr) MemNew(sizeof(WWWInfoData));
223 }
224 
225 
WWWGetWWWEntries(WWWInfoPtr info_in)226 NLM_EXTERN WWWEntryPtr PNTR WWWGetWWWEntries(WWWInfoPtr info_in)
227 {
228     WWWInfoDataPtr info;
229 
230     if((info = (WWWInfoDataPtr) info_in) == NULL)
231         return NULL;
232 
233     return(info->entries);
234 }
235 
236 
WWWGetMethod(WWWInfoPtr info_in)237 NLM_EXTERN Int4 WWWGetMethod(WWWInfoPtr info_in)
238 {
239     WWWInfoDataPtr info;
240 
241     if ((info = (WWWInfoDataPtr) info_in) == NULL)
242         return -1;
243 
244     return info->method;
245 }
246 
247 
WWWGetBrowser(WWWInfoPtr info_in)248 NLM_EXTERN Int4 WWWGetBrowser(WWWInfoPtr info_in)
249 {
250     WWWInfoDataPtr info;
251 
252     if ((info = (WWWInfoDataPtr) info_in) == NULL)
253         return -1;
254 
255     return info->browser;
256 }
257 
258 
WWWGetNumEntries(WWWInfoPtr info_in)259 NLM_EXTERN Int4 WWWGetNumEntries(WWWInfoPtr info_in)
260 {
261     WWWInfoDataPtr info;
262 
263     if ((info = (WWWInfoDataPtr) info_in) == NULL)
264         return -1;
265 
266     return info->num_entries;
267 }
268 
269 
WWWGetAgent(WWWInfoPtr info_in)270 NLM_EXTERN CharPtr WWWGetAgent(WWWInfoPtr info_in)
271 {
272     WWWInfoDataPtr info;
273 
274     if ((info = (WWWInfoDataPtr) info_in) == NULL)
275         return NULL;
276 
277     return info->agent;
278 }
279 
280 
WWWGetAddress(WWWInfoPtr info_in)281 NLM_EXTERN CharPtr WWWGetAddress(WWWInfoPtr info_in)
282 {
283     WWWInfoDataPtr info;
284 
285     if ((info = (WWWInfoDataPtr) info_in) == NULL)
286         return NULL;
287 
288     return info->address;
289 }
290 
291 
WWWGetServer(WWWInfoPtr info_in)292 NLM_EXTERN CharPtr WWWGetServer(WWWInfoPtr info_in)
293 {
294     WWWInfoDataPtr info;
295 
296     if ((info = (WWWInfoDataPtr) info_in) == NULL)
297         return NULL;
298 
299     return info->server_name;
300 }
301 
302 
WWWGetDocRoot(WWWInfoPtr info_in)303 NLM_EXTERN CharPtr WWWGetDocRoot(WWWInfoPtr info_in)
304 {
305     WWWInfoDataPtr info;
306 
307     if ((info = (WWWInfoDataPtr) info_in) == NULL)
308         return NULL;
309 
310     return info->doc_root;
311 }
312 
313 
WWWGetHost(WWWInfoPtr info_in)314 NLM_EXTERN CharPtr WWWGetHost(WWWInfoPtr info_in)
315 {
316     WWWInfoDataPtr info;
317 
318     if ((info = (WWWInfoDataPtr) info_in) == NULL)
319         return NULL;
320 
321     return info->host;
322 }
323 
324 
WWWGetProxiedIP(WWWInfoPtr info_in)325 NLM_EXTERN CharPtr WWWGetProxiedIP(WWWInfoPtr info_in)
326 {
327     WWWInfoDataPtr info;
328 
329     if ((info = (WWWInfoDataPtr) info_in) == NULL)
330         return NULL;
331 
332     return info->proxied_ip;
333 }
334 
335 
WWWGetQuery(WWWInfoPtr info_in)336 NLM_EXTERN CharPtr WWWGetQuery(WWWInfoPtr info_in)
337 {
338     WWWInfoDataPtr info;
339 
340     if ((info = (WWWInfoDataPtr) info_in) == NULL)
341         return NULL;
342 
343     return info->query;
344 }
345 
346 
WWWGetPort(WWWInfoPtr info_in)347 NLM_EXTERN Int4 WWWGetPort(WWWInfoPtr info_in)
348 {
349     WWWInfoDataPtr info;
350 
351     if ((info = (WWWInfoDataPtr) info_in) == NULL)
352         return -1;
353 
354     return info->port;
355 }
356 
357 
WWWReadPosting(WWWInfoPtr PNTR info)358 NLM_EXTERN WWWErrorCode WWWReadPosting(WWWInfoPtr PNTR info)
359 {
360     WWWErrorCode result;
361     SWWWGetArgsAttr attr = WWWGetArgsAttr_Create();
362     if (attr == NULL) {
363         return WWWErrNoMem;
364     }
365     WWWGetArgsAttr_SetReadArgv(attr, FALSE);
366     result = WWWGetArgsInternal(info, attr);
367     WWWGetArgsAttr_Destroy(attr);
368     return result;
369 }
370 
371 
WWWGetArgs(WWWInfoPtr PNTR info)372 NLM_EXTERN WWWErrorCode WWWGetArgs(WWWInfoPtr PNTR info)
373 {
374     WWWErrorCode result;
375     SWWWGetArgsAttr attr = WWWGetArgsAttr_Create();
376     if (attr == NULL) {
377         return WWWErrNoMem;
378     }
379     WWWGetArgsAttr_SetReadArgv(attr, TRUE);
380     result = WWWGetArgsInternal(info, attr);
381     WWWGetArgsAttr_Destroy(attr);
382     return result;
383 }
384 
385 
WWWGetArgsEx(WWWInfoPtr PNTR info,SWWWGetArgsAttr attr)386 NLM_EXTERN WWWErrorCode WWWGetArgsEx(WWWInfoPtr PNTR info,
387                                      SWWWGetArgsAttr attr)
388 {
389     return WWWGetArgsInternal(info, attr);
390 }
391 
392 
393 
WWWSubstituteValue(WWWInfoPtr info_in,CharPtr old,CharPtr new_value)394 NLM_EXTERN Boolean WWWSubstituteValue(WWWInfoPtr info_in,
395                                       CharPtr old, CharPtr new_value)
396 {
397     Int4 i;
398     WWWInfoDataPtr info = (WWWInfoDataPtr) info_in;
399 
400     if (info_in == NULL || old == NULL)
401         return FALSE;
402 
403     for (i = 0; i < info->num_entries; i++) {
404         if (!StringICmp(info->entries[i]->val, old)) {
405             MemFree(info->entries[i]->val);
406             info->entries[i]->val = StringSave(new_value);
407             info->entries[i]->size = StringLen(info->entries[i]->val);
408             return TRUE;
409         }
410     }
411     return FALSE;
412 }
413 
414 
WWWSubstituteValueByName(WWWInfoPtr info_in,CharPtr new_value,CharPtr name)415 NLM_EXTERN Boolean WWWSubstituteValueByName(WWWInfoPtr info_in,
416                                             CharPtr new_value, CharPtr name)
417 {
418     Int4 i;
419     WWWInfoDataPtr info = (WWWInfoDataPtr) info_in;
420 
421     if (info_in == NULL || name == NULL)
422         return FALSE;
423 
424     for (i = 0; i < info->num_entries; i++) {
425         if (!StringICmp(info->entries[i]->name, name)) {
426             MemFree(info->entries[i]->val);
427             info->entries[i]->val = StringSave(new_value);
428             info->entries[i]->size = StringLen(info->entries[i]->val);
429             return TRUE;
430         }
431     }
432     return FALSE;
433 }
434 
435 
WWWGetArgsInternal(WWWInfoPtr PNTR info_out,SWWWGetArgsAttr attr)436 static WWWErrorCode WWWGetArgsInternal(WWWInfoPtr PNTR info_out,
437                                        SWWWGetArgsAttr attr)
438 {
439     Int4  WWWLen;
440     WWWInfoDataPtr info;
441     CharPtr PNTR WWWargv;
442     Int4  WWWargc;
443     Int4  rsize;
444 
445 #if defined(WIN32)  &&  ! defined(COMP_METRO)
446     setmode(fileno(stdin), _O_BINARY);
447 #endif
448 
449     if ((info = (WWWInfoDataPtr) WWWInfoNew()) == NULL)
450         return WWWErrNoMem;
451 
452     /* Reading environment from HTTPD */
453     if (!WWWReadEnvironment(info)) {
454         info->method = COMMAND_LINE;
455 
456         if (attr->read_argv == TRUE) {
457             WWWargc = GetArgc();
458             WWWargv = GetArgv();
459             /* Now try to initilalize WWWInfo from STDIN or command line */
460             if (WWWargc == 1) { /* reading STDIN */
461                 if((info->query = WWWReadFileInMemoryEx(stdin, 0,
462                                                         attr->filter_non_print,
463                                                         &rsize)) != NULL) {
464                     info->query_len = rsize;
465                     info->entries = WWWGetEntriesEx(&info->num_entries,
466                                                     info->query,
467                                                     info->query_len);
468                 }
469             } else { /* treat 1st parameter as input buffer */
470                 if ((info->query = StringSave(WWWargv[1])) != NULL) {
471                     info->query_len = StringLen(info->query);
472                     info->entries = WWWGetEntriesEx(&info->num_entries,
473                                                     info->query,
474                                                     info->query_len);
475                 }
476             }
477         }
478         *info_out = (VoidPtr) info;
479         return WWWErrOk;
480     } /* COMMAND_LINE */
481 
482     if (info->method == WWW_GET) { /* Getting GET data */
483         info->query = StringSave(getenv("QUERY_STRING"));
484         info->query_len = StringLen(info->query);
485     } else if (info->method == WWW_POST) { /* Getting POST data */
486         if ((getenv("CONTENT_LENGTH") != NULL) &&
487            (WWWLen = atol(getenv("CONTENT_LENGTH"))) > 0) {
488             if ((info->query = WWWReadFileInMemoryEx(stdin, WWWLen,
489                                                     attr->filter_non_print,
490                                                      &rsize)) == NULL) {
491                 return WWWErrNetwork;
492             }
493             info->query_len = rsize;
494         }
495     } /* Method == POST */
496 
497     if (info->query != NULL)
498         info->entries = WWWGetEntriesEx(&info->num_entries, info->query,
499                                         info->query_len);
500     *info_out = (VoidPtr) info;
501     return WWWErrOk;
502 }
503 
504 
WWWFindName(WWWInfoPtr info_in,CharPtr find)505 NLM_EXTERN Int4 WWWFindName(WWWInfoPtr info_in, CharPtr find)
506 {
507 
508     Int4 i;
509     WWWInfoDataPtr info = (WWWInfoDataPtr) info_in;
510 
511     if (!info || !find)
512         return -1;
513 
514     for (i = 0; i < info->num_entries; i++) {
515         if (!StringICmp(info->entries[i]->name, find)) {
516             return i;
517         }
518     }
519 
520     return -1;
521 }
522 
523 
WWWFindNameEx(WWWInfoPtr info_in,CharPtr find,Int4 index)524 NLM_EXTERN Int4 WWWFindNameEx(WWWInfoPtr info_in, CharPtr find, Int4 index)
525 {
526 
527     Int4 i;
528     WWWInfoDataPtr info = (WWWInfoDataPtr) info_in;
529 
530     if (!info || !find)
531         return -1;
532 
533     if (index >= info->num_entries)
534         return -1;
535 
536     for (i = index; i < info->num_entries; i++) {
537         if (!StringICmp(info->entries[i]->name, find)) {
538             return i;
539         }
540     }
541 
542     return -1;
543 }
544 
545 
WWWGetNameByIndex(WWWInfoPtr info_in,Int4 index)546 NLM_EXTERN CharPtr WWWGetNameByIndex(WWWInfoPtr info_in, Int4 index)
547 {
548     WWWInfoDataPtr info = (WWWInfoDataPtr) info_in;
549 
550     if (!info || !info->entries || index < 0 || index > info->num_entries)
551         return NULL;
552 
553     return info->entries[index]->name;
554 }
555 
556 
WWWGetValueByIndex(WWWInfoPtr info_in,Int4 index)557 NLM_EXTERN CharPtr WWWGetValueByIndex(WWWInfoPtr info_in, Int4 index)
558 {
559     WWWInfoDataPtr info = (WWWInfoDataPtr) info_in;
560 
561     if (!info || !info->entries || index < 0 || index > info->num_entries)
562         return NULL;
563 
564     return info->entries[index]->val;
565 }
566 
567 
WWWGetValueSizeByIndex(WWWInfoPtr info_in,Int4 index)568 NLM_EXTERN Int4 WWWGetValueSizeByIndex(WWWInfoPtr info_in, Int4 index)
569 {
570     WWWInfoDataPtr info = (WWWInfoDataPtr) info_in;
571 
572     if (!info || !info->entries || index < 0 || index > info->num_entries)
573         return -1;
574 
575     return info->entries[index]->size;
576 }
577 
578 
WWWGetValueByName(WWWInfoPtr info_in,CharPtr find)579 NLM_EXTERN CharPtr WWWGetValueByName(WWWInfoPtr info_in, CharPtr find)
580 {
581     Int4 index;
582     WWWInfoDataPtr info = (WWWInfoDataPtr) info_in;
583 
584     if (!info || !info->entries || !find)
585         return NULL;
586 
587     if ((index = WWWFindName(info_in, find)) < 0)
588         return NULL;
589 
590     return info->entries[index]->val;
591 }
592 
593 
WWWGetLastValueByName(WWWInfoPtr info_in,CharPtr find)594 NLM_EXTERN CharPtr WWWGetLastValueByName(WWWInfoPtr info_in, CharPtr find)
595 {
596     Int4 index;
597     WWWInfoDataPtr info = (WWWInfoDataPtr) info_in;
598     CharPtr retvalue = NULL;
599 
600     if (!info || !info->entries || !find)
601         return NULL;
602 
603     index = 0;
604 
605     while ((index = WWWFindNameEx(info_in, find, index)) >= 0)
606         retvalue = info->entries[index]->val;
607 
608     return retvalue;
609 }
610 
611 
WWWGetEntries(Int4Ptr num_entries,CharPtr WWWBuffer_in,Boolean NetscapeOK)612 NLM_EXTERN WWWEntryPtr PNTR WWWGetEntries(Int4Ptr num_entries,
613                                           CharPtr WWWBuffer_in,
614                                           Boolean NetscapeOK)
615 {
616     register Int4 i;
617     Int4 size;
618     CharPtr WWWBuffer;
619     WWWEntryPtr PNTR entries;
620 
621     if (WWWBuffer_in == NULL || WWWBuffer_in[0] == NULLB)
622         return NULL;
623 
624     NetscapeOK = TRUE; /* Forget it... all browsers should handle it */
625 
626     if ((entries = (WWWEntryPtr*)MemNew(sizeof(WWWEntryPtr) *
627                                         MAX_WWW_ENTRIES)) == NULL)
628         return NULL;
629 
630     if (NetscapeOK && StringStr(WWWBuffer_in,
631                                "Content-Disposition: form-data;") != NULL) {
632         *num_entries = WWWGetEntriesFormData(entries, WWWBuffer_in);
633         return entries;
634     }
635 
636     WWWBuffer = StringSave(WWWBuffer_in); /* this copy may be used for logs */
637     size = StringLen(WWWBuffer) + 1;
638 
639     for (i=0; WWWBuffer[0] != NULLB; i++) {
640         entries[i] = (WWWEntryPtr) MemNew(sizeof(WWWEntry));
641         entries[i]->name = (CharPtr) MemNew(WWW_MAX_NAME_LEN);
642         entries[i]->val  = (CharPtr) MemNew(size);
643 
644         WWWGetWord(entries[i]->val,WWWBuffer,'&');
645         PlusToSpace(entries[i]->val);
646         WWWUnescapeUrl(entries[i]->val);
647         WWWGetWord(entries[i]->name,entries[i]->val,'=');
648 
649         entries[i]->name = (CharPtr) Realloc(entries[i]->name,
650                                              StringLen(entries[i]->name)+1);
651         entries[i]->val  = (CharPtr) Realloc(entries[i]->val,
652                                              StringLen(entries[i]->val)+1);
653         entries[i]->size = StringLen(entries[i]->val);
654     }
655 
656     ASSERT ( i < MAX_WWW_ENTRIES );
657     entries[i] = (WWWEntryPtr) MemNew(sizeof(WWWEntry));
658     entries[i]->name = NULL;
659     entries[i]->val  = NULL;
660 
661     MemFree(WWWBuffer);
662     *num_entries = i;
663     return entries;
664 }
665 
666 
WWWGetEntriesEx(Int4Ptr num_entries,CharPtr WWWBuffer_in,Int4 WWWBuffer_len)667 NLM_EXTERN WWWEntryPtr PNTR WWWGetEntriesEx(Int4Ptr  num_entries,
668                                             CharPtr  WWWBuffer_in,
669                                             Int4     WWWBuffer_len)
670 {
671     register Int4 i;
672     Int4 size;
673     CharPtr WWWBuffer;
674     WWWEntryPtr PNTR entries;
675 
676     if (WWWBuffer_in == NULL || WWWBuffer_in[0] == NULLB)
677         return NULL;
678 
679     if ((entries = (WWWEntryPtr*)MemNew(sizeof(WWWEntryPtr) *
680                                         MAX_WWW_ENTRIES)) == NULL)
681         return NULL;
682 
683     if (StringStr(WWWBuffer_in, "Content-Disposition: form-data;") != NULL) {
684         *num_entries = WWWGetEntriesFormDataEx(entries, WWWBuffer_in,
685                                                WWWBuffer_len);
686         return entries;
687     }
688 
689     WWWBuffer = StringSave(WWWBuffer_in); /* this copy may be used for logs */
690     size = StringLen(WWWBuffer) + 1;
691 
692     for (i=0; WWWBuffer[0] != NULLB; i++) {
693         entries[i] = (WWWEntryPtr) MemNew(sizeof(WWWEntry));
694         entries[i]->name = (CharPtr) MemNew(WWW_MAX_NAME_LEN);
695         entries[i]->val  = (CharPtr) MemNew(size);
696 
697         WWWGetWord(entries[i]->val,WWWBuffer,'&');
698         PlusToSpace(entries[i]->val);
699         WWWUnescapeUrl(entries[i]->val);
700         WWWGetWord(entries[i]->name,entries[i]->val,'=');
701 
702         entries[i]->name = (CharPtr) Realloc(entries[i]->name,
703                                              StringLen(entries[i]->name)+1);
704         entries[i]->val  = (CharPtr) Realloc(entries[i]->val,
705                                              StringLen(entries[i]->val)+1);
706     }
707 
708     ASSERT ( i < MAX_WWW_ENTRIES );
709     entries[i] = (WWWEntryPtr) MemNew(sizeof(WWWEntry));
710     entries[i]->name = NULL;
711     entries[i]->val  = NULL;
712 
713     MemFree(WWWBuffer);
714     *num_entries = i;
715     return entries;
716 }
717 
718 
WWWGetEntriesFormDataEx(WWWEntryPtr PNTR entries,CharPtr WWWBuffer_in,Int4 WWWBuffer_len)719 NLM_EXTERN Int4 WWWGetEntriesFormDataEx(WWWEntryPtr PNTR entries,
720                                         CharPtr WWWBuffer_in,
721                                         Int4 WWWBuffer_len)
722 {
723     Int4 FieldLen, pos;
724     register Int4 i;
725     Char BoundaryString[512];
726     CharPtr FieldValue, FieldTmp;
727     CharPtr WWWBuffer = WWWBuffer_in;
728 
729     if (WWWBuffer == NULL || WWWBuffer[0] == NULLB)
730         return -1;
731 
732     if (WWWBuffer_len < 0)
733         WWWBuffer_len = StringLen(WWWBuffer);
734 
735     for (i = 0; !isspace(WWWBuffer[i]); i++) {
736         BoundaryString[i] = WWWBuffer[i];
737     }
738     BoundaryString[i] = NULLB;
739 
740     for (i=0; WWWBuffer < WWWBuffer_in + WWWBuffer_len; i++) {
741 
742         entries[i] = (WWWEntryPtr) MemNew(sizeof(WWWEntry));
743         entries[i]->name = (CharPtr) MemNew(128);
744 
745         if ((pos = MemSearch(WWWBuffer,
746                              WWWBuffer_in + WWWBuffer_len - WWWBuffer,
747                              BoundaryString,
748                              StringLen(BoundaryString))) < 0)
749             break;
750         WWWBuffer += pos;
751         if (*(WWWBuffer = WWWBuffer + StringLen(BoundaryString) + 1) == '-')
752             break;
753         if ((WWWBuffer = StringStr(WWWBuffer , "form-data;")) == NULL)
754             break;
755 
756         WWWBuffer += 11;
757 
758         if ((FieldLen = MemSearch(WWWBuffer,
759                                  WWWBuffer_in + WWWBuffer_len - WWWBuffer,
760                                  BoundaryString,
761                                  StringLen(BoundaryString))) < 0)
762             break;
763 
764         FieldValue = (CharPtr) MemNew(FieldLen+1);
765         MemCopy(FieldValue, WWWBuffer, FieldLen);
766         FieldValue[FieldLen] = NULLB;
767 
768         sscanf(FieldValue, "name=\"%s ", entries[i]->name);
769 
770         if (entries[i]->name[StringLen(entries[i]->name)-1] != ';')
771             entries[i]->name[StringLen(entries[i]->name)-1] = NULLB;
772         else
773             entries[i]->name[StringLen(entries[i]->name)-2] = NULLB;
774 
775         if ((FieldTmp = StringStr(FieldValue, "\r\n\r\n")) != NULL) {
776             FieldTmp = FieldTmp + 4;
777             pos = FieldValue + FieldLen - FieldTmp;
778             FieldTmp[pos-2] = NULLB;
779             MemMove(FieldValue, FieldTmp, pos - 1);
780             entries[i]->val = Realloc(FieldValue, pos -1);
781             entries[i]->size = pos - 2;
782         } else {
783             MemFree(FieldValue);
784             entries[i]->val = "";
785             entries[i]->size = 0;
786         }
787     }
788 
789     entries[i] = (WWWEntryPtr) MemNew(sizeof(WWWEntry));
790     entries[i]->name = NULL;
791     entries[i]->val  = NULL;
792 
793     return i;
794 }
795 
796 
WWWGetEntriesFormData(WWWEntryPtr PNTR entries,CharPtr WWWBuffer)797 NLM_EXTERN Int4 WWWGetEntriesFormData(WWWEntryPtr PNTR entries,
798                                       CharPtr WWWBuffer)
799 {
800     return WWWGetEntriesFormDataEx(entries, WWWBuffer, -1);
801 }
802 
803 
WWWReadFileInMemory(FILE * fd,Int4 len,Boolean filter)804 NLM_EXTERN CharPtr WWWReadFileInMemory(FILE *fd, Int4 len, Boolean filter)
805 {
806     Int4     bytes = 0;
807     CharPtr  in_buff;
808     Int4     new_size = INIT_BUFF_SIZE;
809     Int4     buff_len = 0;
810     register Int4 i;
811 
812     if (fd == NULL)
813         return NULL;
814 
815     if (len == 0) {
816         /* initial allocation of memory */
817 
818         if ((in_buff = (CharPtr)MemNew(INIT_BUFF_SIZE)) == NULL) {
819             ErrLogPrintf("Error in allocating memory\n");
820             return NULL;
821         }
822 
823         while ((bytes = FileRead(in_buff + buff_len, 1,
824                                  INIT_BUFF_SIZE, fd)) > 0) {
825             new_size += bytes;
826             buff_len += bytes;
827 
828             if ((in_buff = (CharPtr)Realloc(in_buff, new_size)) == NULL) {
829                 ErrLogPrintf("Error in reallocating memory\n");
830                 exit(1);
831             }
832         }
833         in_buff[buff_len] = NULLB;
834 
835     } else {
836 
837         in_buff = (CharPtr) MemNew(len+1);
838 
839         while (buff_len < len) {
840             if ((bytes = FileRead(in_buff+buff_len, 1, len, stdin)) == 0
841                || bytes == len) {
842                 buff_len += bytes;
843                 break; /* EOF or done*/
844             } else if (bytes < 0) {
845                 /* some error setting may be here */
846                 return NULL;
847             }
848             buff_len += bytes;
849         }
850         in_buff[buff_len] = NULLB;
851     }
852 
853     /* some filtering of non-printing characters */
854 
855     if (filter) {
856         for (i = 0; i < buff_len; i++) {
857             if (!isprint(in_buff[i]) && !isspace(in_buff[i]))
858                 in_buff[i] = ' ';
859         }
860     }
861 
862     return(in_buff);
863 }
864 
865 
WWWReadFileInMemoryEx(FILE * fd,Int4 len,Boolean filter,Int4Ptr rsize)866 NLM_EXTERN CharPtr WWWReadFileInMemoryEx(FILE *fd, Int4 len, Boolean filter, Int4Ptr rsize)
867 {
868     Int4     bytes = 0;
869     CharPtr  in_buff;
870     Int4     new_size = INIT_BUFF_SIZE;
871     Int4     buff_len = 0;
872     register Int4 i;
873 
874     if (rsize)
875         *rsize = 0;
876 
877     if (fd == NULL)
878         return NULL;
879 
880     if (len == 0) {
881         /* initial allocation of memory */
882 
883         if ((in_buff = (CharPtr)MemNew(INIT_BUFF_SIZE)) == NULL) {
884             ErrLogPrintf("Error in allocating memory\n");
885             return NULL;
886         }
887 
888         while ((bytes = FileRead(in_buff + buff_len, 1,
889                                  INIT_BUFF_SIZE, fd)) > 0) {
890             new_size += bytes;
891             buff_len += bytes;
892 
893             if ((in_buff = (CharPtr)Realloc(in_buff, new_size)) == NULL) {
894                 ErrLogPrintf("Error in reallocating memory\n");
895                 exit(1);
896             }
897         }
898         in_buff[buff_len] = NULLB;
899 
900     } else {
901 
902         in_buff = (CharPtr)MemNew(len+1);
903 
904         while (buff_len < len) {
905             if ((bytes = FileRead(in_buff+buff_len, 1, len, stdin)) == 0
906                || bytes == len) {
907                 buff_len += bytes;
908                 break; /* EOF or done*/
909             } else if (bytes < 0) {
910                 /* some error setting may be here */
911                 if (rsize)
912                     *rsize = buff_len;
913                 return NULL;
914             }
915             buff_len += bytes;
916         }
917         in_buff[buff_len] = NULLB;
918     }
919 
920     /* some filtering of non-printing characters */
921 
922     if (filter) {
923         for (i = 0; i < buff_len; i++) {
924             if (!isprint(in_buff[i]) && !isspace(in_buff[i]))
925                 in_buff[i] = ' ';
926         }
927     }
928     if (rsize) {
929         *rsize = buff_len;
930     }
931     return(in_buff);
932 }
933 
934 
WWWGetArgsAttr_Create(void)935 NLM_EXTERN SWWWGetArgsAttr WWWGetArgsAttr_Create(void)
936 {
937     SWWWGetArgsAttr attr =(SWWWGetArgsAttr)MemNew(sizeof(SWWWGetArgsAttrData));
938     attr->filter_non_print = TRUE;
939     attr->read_argv = FALSE;
940     return attr;
941 }
942 
943 
WWWGetArgsAttr_Destroy(SWWWGetArgsAttr attr)944 NLM_EXTERN void WWWGetArgsAttr_Destroy(SWWWGetArgsAttr attr)
945 {
946     MemFree(attr);
947 }
948 
949 
WWWGetArgsAttr_SetFilter(SWWWGetArgsAttr attr,Boolean filter_non_print)950 NLM_EXTERN Boolean WWWGetArgsAttr_SetFilter(SWWWGetArgsAttr attr,
951                                             Boolean filter_non_print)
952 {
953     Boolean prev_val = attr->filter_non_print;
954     attr->filter_non_print = filter_non_print;
955     return prev_val;
956 }
957 
958 
WWWGetArgsAttr_SetReadArgv(SWWWGetArgsAttr attr,Boolean read_argv)959 NLM_EXTERN Boolean WWWGetArgsAttr_SetReadArgv(SWWWGetArgsAttr attr,
960                                               Boolean read_argv)
961 {
962     Boolean prev_val = attr->read_argv;
963     attr->read_argv = read_argv;
964     return prev_val;
965 }
966 
967 
968 /****************************************************************************/
969 /* STATIC FINCTIONS */
970 /****************************************************************************/
971 
WWWReadEnvironment(WWWInfoDataPtr info)972 static Boolean WWWReadEnvironment(WWWInfoDataPtr info)
973 {
974     CharPtr Method;
975 
976     if (!info)
977         return 0;
978 
979     info->method = COMMAND_LINE;
980 
981     if ((Method = getenv("REQUEST_METHOD")) != NULL) {
982 
983         if (!StringICmp(Method, "GET")) {
984             info->method = WWW_GET;
985         } else if (!StringICmp(Method, "POST")) {
986             info->method= WWW_POST;
987         }
988     }
989 
990     if ((info->host = StringSave(getenv("REMOTE_HOST"))) == NULL)
991         info->host = StringSave("Host unknown");
992 
993     if ((info->address = StringSave(getenv("REMOTE_ADDR"))) == NULL)
994         info->address =StringSave("Address unknown");
995 
996     if ((info->proxied_ip = StringSave(getenv("PROXIED_IP"))) == NULL)
997         info->proxied_ip = StringSave(info->address);
998 
999     if ((info->doc_root = StringSave(getenv("DOCUMENT_ROOT"))) == NULL)
1000         info->doc_root =StringSave("_unknown_");
1001 
1002     if ((info->agent = StringSave(getenv("HTTP_USER_AGENT"))) == NULL)
1003         info->agent =StringSave("Agent unknown");
1004 
1005     if ((getenv("SERVER_PORT") == NULL) ||
1006        (info->port = atol(getenv("SERVER_PORT"))) == 0)
1007         info->port = -1;
1008 
1009     if ((info->server_name = StringSave(getenv("SERVER_NAME"))) == NULL)
1010         info->server_name = StringSave("Server unknown");
1011 
1012     if ((info->script_name = StringSave(getenv("SCRIPT_NAME"))) == NULL)
1013         info->script_name = StringSave("Script unknown");
1014 
1015     info->browser = MISC_BROWSER;
1016 
1017     if (StringStr(info->agent, "Mozilla"))
1018         info->browser = NETSCAPE;
1019 
1020     /*  if(StringStr(info->agent, "MSIE") ||
1021         StringStr(info->agent, "Microsoft"))
1022         info->browser = EXPLORER; */
1023 
1024     if (info->method == WWW_POST || info->method == WWW_GET)
1025         return TRUE;
1026     else
1027         return FALSE;
1028 }
1029 
1030 
WWWGetWord(CharPtr word,CharPtr line,Char stop)1031 static void WWWGetWord(CharPtr word, CharPtr line, Char stop)
1032 {
1033     register Int4 x = 0,y =0;
1034 
1035     for (x=0; ((line[x]) && (line[x] != stop)); x++)
1036         word[x] = line[x];
1037 
1038     word[x] = '\0';
1039 
1040     if (line[x]) ++x;
1041 
1042     while ((line[y++] = line[x++]) != NULLB)
1043         continue;
1044 
1045 }
1046 
1047 
PlusToSpace(CharPtr str)1048 static void PlusToSpace(CharPtr str)
1049 {
1050     register Int4 x;
1051 
1052     for (x=0; str[x]; x++) if(str[x] == '+')
1053         str[x] = ' ';
1054 }
1055 
1056 
WWWUnescapeUrl(CharPtr url)1057 static void WWWUnescapeUrl(CharPtr url)
1058 {
1059     register Int4 x,y;
1060 
1061     for (x=0, y=0; url[y]; ++x, ++y) {
1062         if ((url[x] = url[y]) == '%') {
1063             url[x] = WWWx2c(&url[y+1]);
1064             y+=2;
1065         }
1066     }
1067     url[x] = '\0';
1068 }
1069 
1070 
WWWx2c(CharPtr what)1071 static Char WWWx2c(CharPtr what)
1072 {
1073     register Char digit;
1074 
1075     digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
1076     digit *= 16;
1077     digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
1078 
1079     return(digit);
1080 }
1081