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