-
Notifications
You must be signed in to change notification settings - Fork 96
/
cgic.html
2085 lines (2066 loc) · 103 KB
/
cgic.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<html>
<head>
<title>cgic: an ANSI C library for CGI Programming</title>
</head>
<body>
<h1>cgic 2.07: an ANSI C library for CGI Programming</h1>
<blockquote>
<strong>IMPORTANT NOTICES:</strong>
<p>
If you have CGIC 1.05 or earlier, you should upgrade to CGIC 1.07,
or to CGIC 2.02 or better, in order to obtain important security fixes.
<p>
If you have CGIC 2.0 or CGIC 2.01 and you use the cgiCookie routines,
you should upgrade to CGIC 2.02 or better, in order to obtain
important security fixes.
</blockquote>
<h3>Table of Contents</h3>
<ul>
<li><a href="#credits">Credits and license terms</a>
<li><a href="#whatsnew208">What's new in version XYZ of CGIC?</a>
<li><a href="#whatis">What is cgic?</a>
<li><a href="#obtain">Obtaining cgic</a>
<li><a href="#build">Building and testing cgic: a sample application</a>
<li><a href="#nocompile">What to do if it won't compile</a>
<li><a href="#howto">How to write a cgic application</a>
<li><a href="#images">How can I generate images from my cgic application?</a>
<li><a href="#debug">CGI debugging features: using capture</a>
<li><a href="#functions">cgic function reference</a>
<li><a href="#variables">cgic variable reference</a>
<li><a href="#resultcodes">cgic result code reference</a>
<li><a href="#index">cgic quick index</a>
</ul>
<h3><a name="credits">Credits and License Terms</a></h3>
<p>
cgic is now distributed under the MIT license:
</p>
<p>
Copyright (c) 1996-2019 Thomas Boutell
</p>
<p>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
</p>
<p>
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
</p>
<p>
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
</p>
<p>
Thanks are due to Robert Gustavsson, Ken Holervich, Bob Nestor,
Jon Ribbens, Thomas Strangert, Wu Yongwei, and other CGIC users
who have corresponded over the years. Although the implementation
of multipart/form-data file upload support in CGIC 2.x is my own,
I particularly wish to thank those who submitted their own
implementations of this feature.
</p>
<h3><a name="whatsnew207">What's new in version 2.07?</a></h3>
Per a suggestion by Geoff Mulligan, cgic now tolerates keys without a value in URL-encoded GET and POST submissions. Although the HTML5 spec discourages it, there are existing systems in the wild that do leave the `=` off entirely if the value is an empty string. Beginning with version 2.07, `cgic` handles this as you'd expect: you get an entry with the corresponding key and an empty string as the value. A simple unit test compilation target was also added, to test this feature and rule out side effects.
<h3><a name="whatsnew206">What's new in version 2.06?</a></h3>
A long list of significant fixes generously contributed by Jeffrey Hutzelman.
<a href="https://github.com/boutell/cgic/commit/2065a2dfa480209bd6171acb2a4edd6e1c27a062"> These are especially important on platforms where attempting to read beyond the content length stated by the request can lead to a deadlock. Please see the commit notes.</a>
<h3><a name="whatsnew205">What's new in version 2.05?</a></h3>
Uploaded files properly closed; corrects a resource leak and enables
file uploads to work properly on platforms with particular file
locking semantics.
<h3><a name="whatsnew204">What's new in version 2.04?</a></h3>
Documentation fixes: the cgiHtmlEscape, cgiHtmlEscapeData,
cgiValueEscape, and cgiValueEscapeData routines were named
incorrectly in the manual. No code changes in version 2.04.
<h3><a name="whatsnew203">What's new in version 2.03?</a></h3>
<ul>
<li>Support for setting cookies has been reimplemented. The new
code closely follows the actual practice of web sites that successfully
use cookies, rather than attempting to implement the specification.
The new code can successfully set more than one cookie at a time in
typical web browsers.
</ul>
<h3><a name="whatsnew202">What's new in version 2.02?</a></h3>
<ul>
<li>In CGIC 2.0 and 2.01, if the HTTP_COOKIE environment variable
was exactly equal to the name of a cookie requested with cgiCookieString,
with no value or equal sign or other characters present, a buffer
overrun could take place. This was not normal behavior and it is
unknown whether any actual web server would allow it to occur, however
we have of course released a patch to correct it.
Thanks to Nicolas Tomadakis.
<li>cgiCookieString returned cgiFormTruncated when cgiFormSuccess would
be appropriate. Fixed; thanks to Mathieu Villeneuve-Belair.
<li>Cookies are now set using a simpler Set-Cookie: header, and with
one header line per cookie, based on data collected by Chunfu Lai.
<li>Memory leaks in cgiReadEnvironment fixed by Merezko Oleg. These
memory leaks were <em>not</em> experienced in a normal CGI situation, only
when reading a saved CGI environment.
</ul>
<h3><a name="whatsnew201">What's new in version 2.01?</a></h3>
<ul>
<li>Makefile supports "make install"
<li>Compiles without warnings under both C and C++ with strict
warnings and strict ANSI compliance enabled
<li>Builds out of the box on Windows (#include <fcntl.h> was needed)
<li>Rare problem in cgiReadEnvironment corrected; no impact on
normal CGI operations
<li>cgiCookieString now sets the result to an empty string
when returning cgiFormNotFound
<li>Minor code cleanups
</ul>
<h3><a name="whatsnew200">What's new in version 2.0?</a></h3>
1. CGIC 2.0 provides support for file upload fields. User-uploaded
files are kept in temporary files, to avoid the use of
excessive swap space (Solaris users may wish to change the
<code>cgicTempDir</code> macro in cgic.c before compiling).
The <code><a href="#cgiFormFileName">cgiFormFileName</a></code>,
<code><a href="#cgiFormFileContentType">cgiFormFileContentType</a></code>,
<code><a href="#cgiFormFileSize">cgiFormFileSize</a></code>,
<code><a href="#cgiFormFileOpen">cgiFormFileOpen</a></code>,
<code><a href="#cgiFormFileRead">cgiFormFileRead</a></code>, and
<code><a href="#cgiFormFileClose">cgiFormFileClose</a></code> functions
provide a complete interface to this new functionality. Remember,
the <code>enctype</code> attribute of the <code>form</code> tag
must be set to <code>multipart/form-data</code> when
<code><input type="file"></code> tags are used.
<p>
2. CGIC 2.0 provides support for setting and examining cookies
(persistent data storage on the browser side).
The <code><a href="#cgiCookieString">cgiCookieString</a></code>,
and <code><a href="#cgiCookieInteger">cgiCookieInteger</a></code>
and <code><a href="#cgiCookies">cgiCookies</a></code>
functions retrieve cookies. The
<code><a href="#cgiHeaderCookieSetString">cgiHeaderCookieSetString</a></code>
and <code><a href="#cgiHeaderCookieSetInteger">cgiHeaderCookieSetInteger</a></code> functions set cookies.
<p>
3. CGIC 2.0 offers a convenient way to retrieve a list of all form fields.
The new <code><a href="#cgiFormEntries">cgiFormEntries</a></code>
function performs this operation.
<p>
4. CGIC 2.0 provides convenience functions to correctly escape
text before outputting it as part of HTML, or as part of the
value of a tag attribute, such as the <code>HREF</code> or
<code>VALUE</code> attribute. See
<code><a href="#cgiHtmlEscape">cgiHtmlEscape</a></code>,
<code><a href="#cgiHtmlEscapeData">cgiHtmlEscapeData</a></code>,
<code><a href="#cgiValueEscape">cgiValueEscape</a></code> and
<code><a href="#cgiValueEscapeData">cgiValueEscapeData</a></code>.
<p>
5. Users have often asked the correct way to determine which submit
button was clicked. This could always be accomplished in previous versions,
but CGIC 2.0 also provides
<a href="#cgiFormSubmitClicked">cgiFormSubmitClicked</a>,
a convenient alternate label for the
<a href="#cgiFormCheckboxSingle">cgiFormCheckboxSingle</a> function.
<h3><a name="whatsnew107">What's new in version 1.07?</a></h3>
A problem with the cgiFormString and related functions has been
corrected. These functions were previously incorrectly returning cgiFormTruncated
in cases where the returned string fit the buffer exactly.
<h3><a name="whatsnew106">What's new in version 1.06?</a></h3>
1. A potentially significant buffer overflow problem has been
corrected. Jon Ribbens correctly pointed out to me (and to the
Internet's bugtraq mailing list) that the cgiFormEntryString
function, which is used directly or indirectly by almost all
CGIC programs, can potentially write past the buffer passed
to it by the programmer. This bug has been corrected.
Upgrading to version 1.06 is <strong>strongly recommended.</strong>
<P>
2. The function <code>cgiSaferSystem()</code> has been
removed entirely. This function escaped only a few metacharacters,
while most shells have many, and there was no way to account for
the many different operating system shells that might be in use
on different operating systems. Since this led to a false sense
of security, the function has been removed. It is our recommendation
that user input should never be passed directly on the command line
unless it has been carefully shown to contain only characters
regarded as safe and appropriate by the programmer. Even then, it is
better to design your utilities to accept their input from standard
input rather than the command line.
<h3><a name="whatsnew105">What's new in version 1.05?</a></h3>
Non-exclusive commercial license fee reduced to $200.
<h3><a name="whatsnew104">What's new in version 1.04?</a></h3>
For consistency with other packages, the standard Makefile
now produces a true library for cgic (libcgic.a).
<h3><a name="whatsnew103">What's new in version 1.03?</a></h3>
Version 1.03 sends line feeds only (ascii 10) to end
Content-type:, Status:, and other HTTP protocol output lines,
instead of CR/LF sequences. The standard specifies CR/LF.
Unfortunately, too many servers reject CR/LF to make
implementation of that standard practical. No server
tested ever rejects LF alone in this context.
<h3><a name="whatsnew102">What's new in version 1.02?</a></h3>
Version 1.02 corrects bugs in previous versions:
<ul>
<li>
<a href="#cgiFormDoubleBounded">cgiFormDoubleBounded</a> specified
its arguments in the wrong order, with surprising results.
This bug has been corrected.
</ul>
<h3><a name="whatsnew101">What's new in version 1.01?</a></h3>
Version 1.01 adds no major functionality but corrects
significant bugs and incompatibilities:
<ul>
<li>
<a href="#cgiFormInteger">cgiFormInteger</a>,
<a href="#cgiFormIntegerBounded">cgiFormIntegerBounded</a>,
<a href="#cgiFormDouble">cgiFormDouble</a> and
<a href="#cgiFormDoubleBounded">cgiFormDoubleBounded</a> now
accept negative numbers properly. They also accept positive
numbers with an explicit + sign.
<li>Hex values containing the digit <code>9</code> are
now properly decoded.
<li><a href="#cgiFormString">cgiFormString</a> now
represents each newline as a single line feed (ascii 10 decimal)
as described in the documentation, not a carriage return
(ascii 13 decimal) as in version 1.0. The latter approach
pleased no one.
<li><a href="#cgiFormString">cgiFormString</a> and
<a href="#cgiFormStringNoNewlines">cgiFormStringNoNewlines</a>
no longer erroneously return cgiFormEmpty in place of
cgiFormSuccess.
<li>The main() function of cgic now flushes standard output
and sleeps for one second before exiting in order to inhibit
problems with the completion of I/O on some platforms. This was
not a cgic bug per se, but has been reported as a common problem
with CGI when used with the CERN server. This change should
improve compatibility.
<li>The single selection example in the testform.html
example now works properly. This was an error in the
form itself, not cgic.
<li><a href="#cgiRemoteUser">cgiRemoteUser</a> and
<a href="#cgiRemoteIdent">cgiRemoteIdent</a> are now
documented accurately. They were reversed earlier.
</ul>
<h3><a name="whatis">What is cgic?</a></h3>
cgic is an ANSI C-language library for the creation of CGI-based
World Wide Web applications. For basic information about
the CGI standard, see the <a href="http://hoohoo.ncsa.uiuc.edu/cgi/">
CGI documentation</a> at NCSA.
<p>
cgic performs the following tasks:
<ul>
<li>Parses form data, correcting for defective and/or inconsistent browsers
<li>Transparently accepts both GET and POST form data
<li>Accepts uploaded files as well as regular form fields
<li>Provides functions to set and retrieve "cookies"
(browser-side persistent information)
<li>Handles line breaks in form fields in a consistent manner
<li>Provides string, integer, floating-point, and single- and
multiple-choice functions to retrieve form data
<li>Provides bounds checking for numeric fields
<li>Loads CGI environment variables into C strings which are always non-null
<li>Provides a way to capture CGI situations for replay in a debugging
environment, including file uploads and cookies
</ul>
<p>
cgic is compatible with any CGI-compliant server environment, and
compiles without modification in Posix/Unix/Linux and Windows
environments.
<h3><a name="obtain">Obtaining cgic</a></h3>
cgic is distributed via the web in two forms: as a Windows-compatible
.ZIP file, and as a gzipped tar file. Most users of Windows and
related operating systems have access to 'unzip' or 'pkunzip'. All modern Unix
systems come with 'gunzip' and 'tar' as standard equipment, and gzip/gunzip
is not difficult to find if yours does not. Versions
of these programs for other operating systems are widely
available if you do not already have them.
<p>
<strong>Important:</strong> to use cgic, you will need an ANSI-standard
C compiler. Under Unix, just obtain and use gcc. Most Unix systems have
standardized on gcc. Users of Windows operating systems should not have
ANSI C-related problems as all of the popular compilers follow the ANSI
standard.
<p>
<strong>Note for Windows Programmers:</strong> you must use a modern
32-bit compiler. Visual C++ 2.0 or higher, Borland C++ and the
mingw32 gcc compiler are all appropriate, as is cygwin. Do
<strong>NOT</strong> use an ancient 16-bit DOS executable compiler, please.
<blockquote>
<h4>What Operating System Does Your WEB SERVER Run?</h4>
Remember, the computer on your desk is usually NOT your web server.
Compiling a Windows console executable will not give you a CGI program that
can be installed on a Linux-based server.
</blockquote>
<h3><a name="build">Building cgic: a sample application</a></h3>
The sample application 'cgictest.c' is provided as part of the
cgic distribution. This CGI program displays an input form,
accepts a submission, and then displays what was submitted.
In the process essentially all of cgic's features are tested.
<p>
On a Unix system, you can build cgictest simply by typing
'make cgictest.cgi'. cgic.c and cgictest.c will be compiled and linked
together to produce the cgictest application. Under non-Unix
operating systems, you will need to create and compile an appropriate
project containing the files cgic.c and cgictest.c.
<p>
<strong>IMPORTANT:</strong> after compiling cgictest.cgi, you will
need to place it in a location on your server system which is
designated by your server administrator as an appropriate location
for CGI scripts. Some servers are configured to recognize any
file ending in .cgi as a CGI program when it is found in any
subdirectory of the server's web space, but this is not always
the case! The right locations for CGI
programs vary greatly from one server to another. Resolving
this issue is between you, your web server administrator,
and your web server documentation. Before submitting a bug
report for cgic, make certain that the CGI example programs
which came with your server <em>do</em> work for you. Otherwise
it is very likely that you have a server configuration problem.
<p>
Once you have moved cgictest.cgi (or cgictest.exe, under Windows)
to an appropriate cgi directory,
use the web browser of your choice to access the URL at which
you have installed it
(for instance, <code>www.mysite.com/cgi-bin/cgictest.cgi</code>).
Fill out the various fields in any manner you wish, then
select the SUBMIT button.
<p>
If all goes well, cgictest.cgi will respond with a page which
indicates the various settings you submitted. If not,
please reread the section above regarding the correct location in
which to install your CGI program on your web server.
<h3><a name="nocompile">What to do if it won't compile</a></h3>
<ul>
<li><strong>Are you using Visual C++ or Borland C++? Did you forget to add
cgic.c to your project?</strong>
<li><strong>Make sure you are using an ANSI C or C++ compiler.</strong>
(All of the Windows compilers are ANSI C compliant.)
</ul>
If none of the above proves effective, please see the
section regarding <a href="#support">support</a>.
<h3><a name="howto">How to write a cgic application</a></h3>
<em>Note: </em> All cgic applications must be linked to the cgic.c module
itself. How to do this depends on your operating system; under Unix,
just use the provided Makefile as an example.
<p>
Since all CGI applications must perform certain initial
tasks, such as parsing form data and examining
environment variables, the cgic library provides its
own main() function. When you write applications that
use cgic, you will begin your own programs by writing
a cgiMain() function, which cgic will invoke when
the initial cgi work has been successfully completed. Your
program must also be sure to #include the file cgic.h.
<p>
<strong>Important:</strong> if you write your own main()
function, your program will not link properly. Your own
code should begin with cgiMain(). The library
provides main() for you. (Those who prefer different behavior
can easily modify cgic.c.)
<p>
Consider the cgiMain function of cgictest.c:
<p>
<PRE>
int cgiMain() {
#ifdef DEBUG
LoadEnvironment();
#endif /* DEBUG */
/* Load a previously saved CGI scenario if that button
has been pressed. */
if (cgiFormSubmitClicked("loadenvironment") == cgiFormSuccess) {
LoadEnvironment();
}
/* Set any new cookie requested. Must be done *before*
outputting the content type. */
CookieSet();
/* Send the content type, letting the browser know this is HTML */
cgiHeaderContentType("text/html");
/* Top of the page */
fprintf(cgiOut, "<HTML><HEAD>\n");
fprintf(cgiOut, "<TITLE>cgic test</TITLE></HEAD>\n");
fprintf(cgiOut, "<BODY><H1>cgic test</H1>\n");
/* If a submit button has already been clicked, act on the
submission of the form. */
if ((cgiFormSubmitClicked("testcgic") == cgiFormSuccess) ||
cgiFormSubmitClicked("saveenvironment") == cgiFormSuccess)
{
HandleSubmit();
fprintf(cgiOut, "<hr>\n");
}
/* Now show the form */
ShowForm();
/* Finish up the page */
fprintf(cgiOut, "</BODY></HTML>\n");
return 0;
}
</PRE>
Note the DEBUG #ifdef. If DEBUG is defined at compile time, either by
inserting the line "#define DEBUG 1" into the program or by setting
it in the Makefile or other development environment, then the
LoadEnvironment function is invoked. This function calls
<a href="#cgiReadEnvironment">cgiReadEnvironment()</a>
to restore a captured CGI environment for debugging purposes. See
also the discussion of the <a href="#debug">capture</a> program, which is
provided for use in CGI debugging. Because this is a test program,
the <a href="#cgiFormSubmitClicked">cgiFormSubmitClicked</a> function is
also called to check for the use of a button that requests the reloading
of a saved CGI environment. A completed CGI program typically would
never allow the end user to make that decision.
<h4>Setting Cookies</h4>
Next, one of the cgiHeader functions should be called.
This particular program demonstrates many features, including
the setting of cookies. If the programmer wishes to set a cookie,
the cookie-setting function must be called
first, before other headers are output. This is done by the
CookieSet() function of cgictest.c:
<pre>
void CookieSet()
{
char cname[1024];
char cvalue[1024];
/* Must set cookies BEFORE calling
cgiHeaderContentType */
cgiFormString("cname", cname, sizeof(cname));
cgiFormString("cvalue", cvalue, sizeof(cvalue));
if (strlen(cname)) {
/* Cookie lives for one day (or until
browser chooses to get rid of it, which
may be immediately), and applies only to
this script on this site. */
cgiHeaderCookieSet(cname, cvalue,
86400, cgiScriptName, cgiServerName,
cgiCookieHttpOnly | cgiCookieSameSiteStrict);
}
}
</pre>
Since this is a test program, the <a href="#cgiFormString">cgiFormString</a>
function is used to fetch the name and value from the form previously filled
in by the user. Normally, cookie names and values are chosen to meet the
needs of the programmer and provide a means of identifying the same
user again later.
<p>
The <a href="#cgiHeaderCookieSet">cgiHeaderCookieSet</a>
function sets the cookie by requesting that the web browser store it.
<strong>There is never any guarantee that this will happen!</strong>
Many browsers reject cookies completely; others do not necessarily keep
them as long as requested or return them with their values intact.
Always code defensively when using cookies.
<p>
The cname and cvalue parameters are of course the name and value for
the cookie. The third argument is the time, in seconds, that the
cookie should "live" on the browser side before it expires; in this
case it has been set to 86,400 seconds, which is exactly one day.
<strong>The browser may or may not respect this setting, as with everything
else about cookies.</strong>
<p>
The fourth argument identifies the "path" within the web site for which
the cookie is considered valid. A cookie that should be sent back
for every access to the site should be set with a path of <code>/</code>.
In this case the cookie is relevant only to the CGI program itself, so
<code><a href="#cgiScriptName">cgiScriptName</a></code> (the URL of the CGI program, not including the
domain name) is sent. Similarly, a cookie can be considered relevant
to a single web site or to an entire domain, such as
<code>www.boutell.dev</code> or the entire <code>.boutell.dev</code>
domain. In this case, the current site on which the program is running
is the only relevant site, so <code><a href="#cgiServerName">cgiServerName</a></code> is used
as the domain.
<p>
The sixth argument sets extra security options, for example <i>HttpOnly</i> or
<i>SameSite=Strict</i> to prevent cross-site-scripting attacks.
<h4>Outputting the Content Type Header</h4>
Next, <a href="#cgiHeaderContentType">cgiHeaderContentType()</a> is
called to indicate the MIME type of the document being output, in this case
"text/html" (a normal HTML document). A few other common MIME types are
"image/gif", "image/jpeg" and "audio/wav".
<p>
Note that <a href="#cgiHeaderStatus">cgiHeaderStatus()</a> or
<a href="#cgiHeaderLocation">cgiHeaderLocation()</a> could have
been invoked instead to output an error code or redirect the
request to a different URL. Only one of the cgiHeader functions
should be called in a single execution of the program.
<p>
<strong>Important:</strong> one of the cgiHeader functions,
usually <a href="#cgiHeaderContentType">cgiHeaderContentType()</a>,
<em>must</em> be invoked before outputting any other
response to the user. Otherwise, the result will not be a valid
document and the browser's behavior will be unpredictable.
You may, of course, output your own ContentType and other
header information to <a href="#cgiOut">cgiOut</a> if you prefer. The cgiHeader functions
are provided as a convenience.
<h4>Handling Form Submissions</h4>
Like many CGI programs, cgictest makes decisions about the way it
should behave based on whether various submit buttons have been clicked.
When either the testcgic or saveenvironment button is present, cgictest
invokes the HandleSubmit function, which invokes additional functions to
handle various parts of the form:
<pre>
void HandleSubmit()
{
Name();
Address();
Hungry();
Temperature();
Frogs();
Color();
Flavors();
NonExButtons();
RadioButtons();
File();
Entries();
Cookies();
/* The saveenvironment button, in addition to submitting
the form, also saves the resulting CGI scenario to
disk for later replay with the 'load saved environment'
button. */
if (cgiFormSubmitClicked("saveenvironment") == cgiFormSuccess) {
SaveEnvironment();
}
}
</pre>
<h4>Handling Text Input</h4>
The Name() function of cgictest is shown below, in its simplest
possible form:
<PRE>
void Name() {
char name[81];
<a href="#cgiFormStringNoNewlines">cgiFormStringNoNewlines</a>("name", name, 81);
fprintf(cgiOut, "Name: ");
cgicHtmlEscape(name);
fprintf(cgiOut, "<BR>\n");
}
</PRE>
The purpose of this function is to retrieve and display the name that was
input by the user. Since the programmer has decided that names should
be permitted to have up to 80 characters, a buffer of 81 characters
has been declared (allowing for the final null character).
The <a href="#cgiFormStringNoNewlines">cgiFormStringNoNewlines()</a>
function is then invoked to retrieve the name and ensure that
carriage returns are not present in the name (despite the
incorrect behavior of some web browsers). The first argument
is the name of the input field in the form, the second argument
is the buffer to which the data should be copied, and the third
argument is the size of the buffer. cgic will never write beyond
the size of the buffer, and will always provide a null-terminated
string in response; if the buffer is too small, the string will
be shortened. If this is not acceptable, the
<a href="#cgiFormStringSpaceNeeded">cgiFormStringSpaceNeeded()</a>
function can be used to check the amount of space needed; the
return value of cgiFormStringNoNewlines() can also be checked
to determine whether truncation occurred. See
the full description of <a href="#cgiFormStringNoNewlines">
cgiFormStringNoNewlines()</a>.
<h4>Handling Output</h4>
Note that Name() writes its HTML output to <a href="#cgiOut">cgiOut</a>, not
to stdout.
<p>
The actual name submitted by the user may or may not contain
characters that have special meaning in HTML, specifically the
the <code><</code>, <code>></code>, and <code>&</code> characters.
The <a href="#cgiHtmlEscape">cgiHtmlEscape</a> function is used to output
the user-entered name with any occurrences of these characters
correctly escaped as <code>&lt;</code>, <code>&gt;</code>,
and <code>&amp;</code>.
<p>
<strong>Important:</strong> <a href="#cgiOut">cgiOut</a> is normally equivalent
to stdout, and there is no performance penalty for using it.
It is recommended that you write output to <a href="#cgiOut">cgiOut</a> to ensure compatibility
with modified versions of the cgic library for special
environments that do not provide stdin and stdout for
each cgi connection.
<p>
Note that, for text input areas in which carriage returns <em>are</em>
desired, the function <a href="#cgiFormString">cgiFormString</a>
should be used instead. cgiFormString ensures that line breaks
are always represented by a single carriage return (ascii decimal 13),
making life easier for the programmer. See the source code to
the Address() function of cgictest.c for an example.
<h4>Handling Single Checkboxes</h4>
Consider the Hungry() function, which determines whether
the user has selected the "hungry" checkbox:
<PRE>
void Hungry() {
if (<a href="#cgiFormCheckboxSingle">cgiFormCheckboxSingle</a>("hungry") == <a href="#cgiFormSuccess">cgiFormSuccess</a>) {
fprintf(cgiOut, "I'm Hungry!<BR>\n");
} else {
fprintf(cgiOut, "I'm Not Hungry!<BR>\n");
}
}
</PRE>
This function takes advantage of the
<a href="#cgiFormCheckboxSingle">cgiFormCheckboxSingle()</a> function, which
determines whether a single checkbox has been selected.
cgiFormCheckboxSingle() accepts the name attribute of the checkbox
as its sole argument and returns <a href="#cgiFormSuccess">
cgiFormSuccess</a> if the checkbox is selected, or
<a href="#cgiFormNotFound">cgiFormNotFound</a> if it is not.
If multiple checkboxes with the same name are in use,
consider the <a href="#cgiFormCheckboxMultiple">
cgiFormCheckboxMultiple()</a> and
<a href="#cgiFormStringMultiple">cgiFormStringMultiple()</a>
functions.
<h4>Handling Numeric Input</h4>
Now consider the Temperature() function, which retrieves
a temperature in degrees (a floating-point value) and ensures
that it lies within particular bounds:
<PRE>
void Temperature() {
double temperature;
<a href="#cgiFormDoubleBounded">cgiFormDoubleBounded</a>("temperature", &temperature, 80.0, 120.0, 98.6);
fprintf(<a href="#cgiOut">cgiOut</a>, "My temperature is %f.<BR>\n", temperature);
}
</PRE>
The temperature is retrieved by the function
<a href="#cgiFormDoubleBounded">cgiFormDoubleBounded()</a>. The first
argument is the name of the temperature input field in the form;
the second argument points to the address of the variable that will
contain the result. The next two arguments are the lower and upper
bounds, respectively. The final argument is the default value to
be returned if the user did not submit a value.
<p>
This function always retrieves a reasonable value within the
specified bounds; values above or below bounds are constrained
to fit the bounds. However, the return value of
cgiFormDoubleBounded can be checked to make sure the
actual user entry was in bounds, not blank, and so forth;
see the description of <a href="#cgiFormDoubleBounded">
cgiFormDoubleBounded()</a> for more details. If bounds checking
is not desired, consider using <a href="#cgiFormDouble">
cgiFormDouble()</a> instead.
<p>
Note that, for integer input, the functions
<a href="#cgiFormInteger">cgiFormInteger</a> and
<a href="#cgiFormIntegerBounded">cgiFormIntegerBounded</a>
are available. The behavior of these functions is similar to
that of their floating-point counterparts above.
<h4>Handling Single-Choice Input</h4>
The <SELECT> tag of HTML is used to provide the user with
several choices. Radio buttons and checkboxes can also be used
when the number of choices is relatively small. Consider
the Color() function of cgictest.c:
<PRE>
char *colors[] = {
"Red",
"Green",
"Blue"
};
void Color() {
int colorChoice;
<a href="#cgiFormSelectSingle">cgiFormSelectSingle</a>("colors", colors, 3, &colorChoice, 0);
fprintf(<a href="#cgiOut">cgiOut</a>, "I am: %s<BR>\n", colors[colorChoice]);
}
</PRE>
This function determines which of several colors the user chose
from a <SELECT> list in the form. An array of colors is
declared; the <a href="#cgiFormSelectSingle">cgiFormSelectSingle()</a>
function is then invoked to determine which, if any, of those choices
was selected. The first argument indicates the name of the input
field in the form. The second argument points to the list of
acceptable colors. The third argument indicates the number of
entries in the color array. The fourth argument points to the
variable which will accept the chosen color, and the last argument
indicates the index of the default value to be set if no
selection was submitted by the browser.
<p>
<a href="#cgiFormSelectSingle">cgiFormSelectSingle()</a> will
always indicate a reasonable selection value. However, if
the programmer wishes to know for certain that a value was
actually submitted, that the value submitted was a legal
response, and so on, the return value of cgiFormSelectSingle()
can be consulted. See the full description of
<a href="#cgiFormSelectSingle">cgiFormSelectSingle()</a> for
more information.
<p>
Note that radio button groups and <SELECT> lists can both
be handled by this function. If you are processing radio
button groups, you may prefer to invoke
<a href="#cgiFormRadio">cgiFormRadio()</a>, which functions
identically.
<p>
<em>"What if I won't know the acceptable choices at runtime?"</em>
<p>
If the acceptable choices aren't known <em>until</em> runtime,
one can simply load the choices from disk. But if the acceptable
choices aren't fixed at all (consider a list of country names;
new names may be added to the form at any time and it is
inconvenient to also update program code or a separate list
of countries), simply invoke
<a href="#cgiFormStringNoNewlines">cgiFormStringNoNewlines()</a>
instead to retrieve the string directly. Keep in mind that, if
you do so, validating the response to make sure it is
safe and legitimate becomes a problem for your own
program to solve. The advantage of cgiFormSelectSingle() is that invalid
responses are never returned.
<p>
To handle multiple-selection <SELECT> lists and
groups of checkboxes with the same name, see the
discussion of the NonExButtons() function of cgictest.c, immediately below.
<h4>Handling Multiple-Choice Input</h4>
Consider the first half of the NonExButtons() function of cgictest.c:
<PRE>
char *votes[] = {
"A",
"B",
"C",
"D"
};
void NonExButtons() {
int voteChoices[4];
int i;
int result;
int invalid;
char **responses;
/* Method #1: check for valid votes. This is a good idea,
since votes for nonexistent candidates should probably
be discounted... */
fprintf(<a href="#cgiOut">cgiOut</a>, "Votes (method 1):<BR>\n");
result = <a href="#cgiFormCheckboxMultiple">cgiFormCheckboxMultiple</a>("vote", votes, 4,
voteChoices, &invalid);
if (result == <a href="#cgiFormNotFound">cgiFormNotFound</a>) {
fprintf(<a href="#cgiOut">cgiOut</a>, "I hate them all!<p>\n");
} else {
fprintf(<a href="#cgiOut">cgiOut</a>, "My preferred candidates are:\n");
fprintf(<a href="#cgiOut">cgiOut</a>, "<ul>\n");
for (i=0; (i < 4); i++) {
if (voteChoices[i]) {
fprintf(<a href="#cgiOut">cgiOut</a>, "<li>%s\n", votes[i]);
}
}
fprintf(<a href="#cgiOut">cgiOut</a>, "</ul>\n");
}
</PRE>
This function takes advantage of
<a href="#cgiFormCheckboxMultiple">cgiFormCheckboxMultiple()</a>,
which is used to identify one or more selected checkboxes with
the same name. This function performs identically to
<a href="#cgiFormSelectMultiple">cgiFormSelectMultiple()</a>.
That is, <SELECT> tags with the MULTIPLE attribute are handled
just like a group of several checkboxes with the same name.
<p>
The first argument to <a href="#cgiFormCheckboxMultiple">
cgiFormCheckboxMultiple()</a> is the name given to all
checkbox input fields in the group. The second argument
points to an array of legitimate values; these should
correspond to the VALUE attributes of the checkboxes
(or OPTION tags in a <SELECT> list). The third argument
indicates the number of entries in the array of
legitimate values. The fourth argument points to
an array of integers with the same number of entries
as the array of legitimate values; each entry
will be set true if that checkbox or option was selected,
false otherwise.
<p>
The last argument points to an integer which will be set to the
number of invalid responses (responses not in the array of
valid responses) that were submitted. If this value is not
of interest, the last argument may be a null pointer (0).
<p>
Note that the return value of cgiFormCheckboxMultiple is
inspected to determine whether any choices at all were
set. See the full description of
<a href="#cgiFormCheckboxMultiple">cgiFormCheckboxMultiple</a>
for other possible return values.
<p>
<em>"What if I won't know the acceptable choices at runtime?"</em>
<p>
If the acceptable choices aren't known <em>until</em> runtime,
one can simply load the choices from disk. But if the acceptable
choices aren't fixed at all (consider a list of ice cream flavors;
new names may be added to the form at any time and it is
inconvenient to also update program code or a separate list
of countries), a more dynamic approach is needed. Consider
the second half of the NonExButtons() function of cgictest.c:
<PRE>
/* Method #2: get all the names voted for and trust them.
This is good if the form will change more often
than the code and invented responses are not a danger
or can be checked in some other way. */
fprintf(<a href="#cgiOut">cgiOut</a>, "Votes (method 2):<BR>\n");
result = <a href="#cgiFormStringMultiple">cgiFormStringMultiple</a>("vote", &responses);
if (result == <a href="#cgiFormNotFound">cgiFormNotFound</a>) {
fprintf(<a href="#cgiOut">cgiOut</a>, "I hate them all!<p>\n");
} else {
int i = 0;
fprintf(<a href="#cgiOut">cgiOut</a>, "My preferred candidates are:\n");
fprintf(<a href="#cgiOut">cgiOut</a>, "<ul>\n");
while (responses[i]) {
fprintf(<a href="#cgiOut">cgiOut</a>, "<li>%s\n", responses[i]);
i++;
}
fprintf(<a href="#cgiOut">cgiOut</a>, "</ul>\n");
}
/* We must be sure to free the string array or a memory
leak will occur. Simply calling free() would free
the array but not the individual strings. The
function cgiStringArrayFree() does the job completely. */
<A HREF="#cgiStringArrayFree">cgiStringArrayFree</a>(responses);
}
</PRE>
This code excerpt demonstrates an alternate means of retrieving
a list of choices. The function
<a href="#cgiFormStringMultiple">cgiFormStringMultiple()</a> is used
to retrieve an array consisting of all the strings submitted
for with a particular input field name. This works both for
<SELECT> tags with the MULTIPLE attribute and for
groups of checkboxes with the same name.
<P>
The first argument to <a href="#cgiFormStringMultiple">
cgiFormStringMultiple()</a> is the name of the input field or
group of input fields in question. The second argument should
be the address of a pointer to a pointer to a string, which
isn't as bad as it sounds. Consider the following simple call
of the function:
<PRE>
/* An array of strings; each C string is an array of characters */
char **responses;
<a href="#cgiFormStringMultiple">cgiFormStringMultiple</a>("vote", &responses);
</PRE>
<em>"How do I know how many responses there are?"</em>
<p>
After the call, the last entry in the string array will be
a null pointer. Thus the simple loop:
<PRE>
int i = 0;
while (responses[i]) {
/* Do something with the string responses[i] */
i++;
}
</PRE>
can be used to walk through the array until the last
entry is encountered.
<p>
<strong>Important:</strong> the
<a href="#cgiFormStringMultiple">cgiFormStringMultiple</a> function
returns a pointer to <strong>allocated memory</strong>. Your code
should not modify the strings in the responses array or the responses
array itself; if modification is needed, the strings should be
copied. When your code is done examining the responses array,
you <strong>MUST</strong> call <a href="#cgiStringArrayFree">
cgiStringArrayFree()</a> with the array as an argument to free the memory
associated with the array. Otherwise, the memory will not be available
again until the program exists. <strong>Don't</strong> just call the
free() function; if you do, the individual strings will not be freed.
<h4>Accessing Uploaded Files</h4>
CGIC provides functions to access files that have been uploaded
as part of a form submission. <strong>IMPORTANT: you MUST</strong> set
the <code>enctype</code> attribute of your <code>form</code> tag
to <code>multipart/form-data</code> for this feature to work! For an
example, see the <a href="#ShowForm">ShowForm</a> function of
cgictest.c, examined below.
<p>
The <code>File</code> function of cgictest.c takes care of
receiving uploaded files:
<pre>
void File()
{
cgiFilePtr file;
char name[1024];
char contentType[1024];
char buffer[1024];
int size;
int got;
if (cgiFormFileName("file", name, sizeof(name)) !=
cgiFormSuccess)
{
printf("<p>No file was uploaded.<p>\n");
return;
}
fprintf(cgiOut, "The filename submitted was: ");
cgiHtmlEscape(name);
fprintf(cgiOut, "<p>\n");
cgiFormFileSize("file", &size);
fprintf(cgiOut, "The file size was: %d bytes<p>\n", size);
cgiFormFileContentType("file", contentType, sizeof(contentType));
fprintf(cgiOut, "The alleged content type of the file was: ");
cgiHtmlEscape(contentType);
fprintf(cgiOut, "<p>\n");
fprintf(cgiOut, "Of course, this is only the claim the browser "
"made when uploading the file. Much like the filename, "
"it cannot be trusted.<p>\n");
fprintf(cgiOut, "The file's contents are shown here:<p>\n");
if (cgiFormFileOpen("file", &file) != cgiFormSuccess) {
fprintf(cgiOut, "Could not open the file.<p>\n");
return;
}
fprintf(cgiOut, "<pre>\n");
while (cgiFormFileRead(file, buffer, sizeof(buffer), &got) ==
cgiFormSuccess)
{
cgiHtmlEscapeData(buffer, got);
}
fprintf(cgiOut, "</pre>\n");
cgiFormFileClose(file);
}
</pre>
First, the File function checks to determine the filename that was
submitted by the user. <strong>VERY IMPORTANT: this filename may or
may not bear any relation to the real name of the file on the user's
computer, may be deliberately manipulated with malicious intent,</strong>
and should not be used for <strong>any</strong> purpose unless you have
determined that its content is safe for your intended use and will not,
at the very least, overwrite another file of importance to you, especially if
you intend to use it as a file name on the server side. The cgic library
itself does not use this file name for temporary storage.
<p>
If the <a href="#cgiFormFileName">cgiFormFileName</a> function does
not succeed, no file was uploaded.
<p>
Next, the <a href="#cgiFormFileSize">cgiFormFileSize</a> function is called
to determine the size of the uploaded file, in bytes.
<p>
The File function then proceeds to query the content type of the uploaded
file. Files uploaded by the user have their own content type information,
which may be useful in determining whether the file is an image, HTML document,
word processing document, or other type of file. However,
<strong>as with the filename and any other claim made by the browser,
this information should not be blindly trusted.</strong> The browser
may upload a file with the name <code>picture.jpg</code> and the
content type <code>image/jpeg</code>, but this does not guarantee that the
actual file will contain a valid JPEG image suitable for display.
<p>
The content type submitted by the browser can be queried using the
<a href="#cgiFormFileContentType">cgiFormFileContentType</a> function.
<p>
Of course, CGIC also provides access to the actual uploaded file.
First, the programmer calls <a href="#cgiFormFileOpen">cgiFormFileOpen</a>,
passing the address of a <code>cgiFilePtr</code> object. If this function
succeeds, the <code>cgiFilePtr</code> object becomes valid, and can be
used in subsequent calls to <a href="#cgiFormFileRead">cgiFormFileRead</a>.
Notice that the number of bytes read may be less than the number requested,
in particular on the last successful call before cgiFormFileRead begins
to return <code>cgiFormEOF</code>. When cgiFormFileRead no longer returns
cgiFormSuccess,
the programmer calls <a href="#cgiFormClose">cgiFormFileClose</a> to
release the <code>cgiFilePtr</code> object.
<p>
The uploaded file data may contain anything, including binary data,
null characters, and so on. The example program uses the
<a href="#cgiHtmlEscapeData">cgiHtmlEscapeData</a> function to output the
data with any special characters that have meaning in HTML escaped.
Most programs will save the uploaded information to a server-side file or
database.
<h4>Fetching All Form Entries</h4>
From time to time, the programmer may not know the names of all
form fields in advance. In such situations it is convenient to
use the <a href="#cgiFormEntries">cgiFormEntries</a> function.
The Entries function of cgictest.c demonstrates the use of
cgiFormEntries:
<pre>
void Entries()
{
char **array, **arrayStep;
fprintf(cgiOut, "List of All Submitted Form Field Names:<p>\n");
if (cgiFormEntries(&array) != cgiFormSuccess) {
return;
}
arrayStep = array;
fprintf(cgiOut, "<ul>\n");
while (*arrayStep) {
fprintf(cgiOut, "<li>");
cgiHtmlEscape(*arrayStep);
fprintf(cgiOut, "\n");
arrayStep++;
}
fprintf(cgiOut, "</ul>\n");
cgiStringArrayFree(array);
}
</pre>
The cgiFormEntries function retrieves an array of form field names.
This array consists of pointers to strings, with a final null pointer
to mark the end of the list. The above code illustrates one way of
looping through the returned strings. Note the final call to
<a href="#cgiStringArrayFree">cgiStringArrayFree</a>, which is
essential in order to return the memory used to store the strings
and the string array.
<h4>Retrieving Cookies</h4>
The Cookies function of cgictest.c displays a list of all cookies
submitted by the browser with the current form submission, along
with their values:
<pre>
void Cookies()
{
char **array, **arrayStep;
char cname[1024], cvalue[1024];
fprintf(cgiOut, "Cookies Submitted On This Call, With Values "
"(Many Browsers NEVER Submit Cookies):<p>\n");
if (cgiCookies(&array) != cgiFormSuccess) {
return;
}
arrayStep = array;
fprintf(cgiOut, "<table border=1>\n");
fprintf(cgiOut, "<tr><th>Cookie<th>Value</tr>\n");
while (*arrayStep) {
char value[1024];
fprintf(cgiOut, "<tr>");
fprintf(cgiOut, "<td>");
cgiHtmlEscape(*arrayStep);
fprintf(cgiOut, "<td>");
cgiCookieString(*arrayStep, value, sizeof(value));
cgiHtmlEscape(value);
fprintf(cgiOut, "\n");
arrayStep++;
}
fprintf(cgiOut, "</table>\n");
cgiFormString("cname", cname, sizeof(cname));
cgiFormString("cvalue", cvalue, sizeof(cvalue));
if (strlen(cname)) {
fprintf(cgiOut, "New Cookie Set On This Call:<p>\n");
fprintf(cgiOut, "Name: ");