CGI & APACHE

   
            CGI Simple Sample
    CGI规定了Web服务器调用其他可执行程序(CGI程序)的接口协议标准。Web服务器通过调用CGI程序实现和Web浏览器的交互。CGI程序可

以用任何程序设计语言编写,如Shell脚本语言、 Perl、Fortran、Pascal、C语言等。但是用C语言编写的CGI程序具有执行速度快、安全性高等

特点。本文详细分析了用C语言进行CGI程序设计的方法、过程和技巧。

正文: 用C语言进行CGI程序设计

一、CGI概述

    CGI(Common Gateway Interface:公用网关接口)规定了Web服务器调用其他可执行程序(CGI程序)的接口协议标准。Web服务器通过调用

CGI程序实现和Web浏览器的交互,也就是CGI程序接受Web浏览器发送给Web服务器的信息,进行处理, 将响应结果再回送给Web服务器及Web浏览器

。CGI程序一般完成Web网页中表单(Form)数据的处理、数据库查询和实现与传统应用系统的集成等工作。CGI程序可以用任何程序设计语言编写

,如Shell脚本语言、Perl、Fortran、Pascal、C语言等。但是用C语言编写的CGI程序具有执行速度快、安全性高(因为C语言程序是编译执行且

不可被修改)等特点。

    CGI接口标准包括标准输入、环境变量、标准输出三部分。
    1.标准输入
    CGI程序像其他可执行程序一样,可通过标准输入(stdin)从Web服务器得到输入信息,如Form中的数据,这就是所谓的向CGI程序传递数据

的 POST方法。这意味着在操作系统命令行状态可执行CGI程序,对CGI程序进行调试。POST方法是常用的方法,本文将以此方法为例,分析CGI程序

设计的方法、过程和技巧。

    2.环境变量
操作系统提供了许多环境变量,它们定义了程序的执行环境,应用程序可以存取它们。Web服务器和CGI接口又另外设置了自己的一些环境变量,用

来向CGI 程序传递一些重要的参数。CGI的GET方法还通过 环境变量QUERY-STRING向CGI程序传递Form中的数据。

    3.标准输出
    CGI程序通过标准输出(stdout)将输出信息传送给Web服务器。传送给Web服务器的信息可以用各种格式,通常是以纯文本或者HTML文本

的形式,这样我们就可以在命令行状态调试CGI程序,并且得到它们的输出。下面是一个简单的CGI程序,它将HTML中Form的信息直接输出到Web浏

览器。

    下面举一个"hello world" CGI 程序的例子。

    apache的配置文件的位置
    Apache's configure file:
    /etc/httpd/conf/httpd.conf

    在配置文件中找到 AddHandler cgi-script .cgi 在这一行后面加上 .exe,并且去掉前边的#.这个表示可调用的程序的后缀名.


    CGI程序的程序文件的位置
    Cgi program’s location:
    /var/www/cgi-bin/
    Sample: /var/www/cgi-bin/hello.exe

    Html文件的位置
    Web page’s location:
    /var/www/html/
    sample: /var/www/html/index.html

    编写一个html文件index.html.放在/var/www/html/目录下.
    Index.html文件表示一个网站的首页.
    如:当如输入http://13.187.241.242/    (web server 端的IP,也就是linux 的IP)的时候就显示的为这个html文件.

    <html>
    <head>
    <title><h1>First HTML<h1></title>
    </head>
    <body>
    <p><b>This is my first HTML</b></p>
    </body>
    </html>

    编写一个"hello world"的 C 程序.

#include <stdio.h>
int main(void)
{
        printf("Content-Type: text/plain;charset=us-ascii/n/n");
        printf("<html> ");
        printf("<head
        printf("<head;
        printf("<body;
        printf("<from action = /"http://13.187.241.242/cgi-bin/tt /" method= /"post /" > ");
        printf("<p> Hello World </p>");
        printf("</form> ");
        printf("</body> ");
        printf("</html>");
        return 0;
}


    这个程序输出的其实就是html 的代码.

    注意: printf("Content-Type: text/plain;charset=us-ascii/n/n");
    此行通过标准输出将字符串"Content-Type: text/plain;charset=us-ascii"传送给Web服务器。它是一个MIME头信息,它告诉Web服务

器随后的输出是以纯ASCII文本的形式。请注意在这个头信息中有两个换行符,这是因为Web服务器需要在实际的文本信息开始之前先看见一个空

行。

    编译这个程序,生成一个执行文件demo.放在/var/www/cgi-bin/下.然后启动apache.

    现在可以访问了http://13.187.241.242/ 这个访问的是index.html
    访问http://13.187.241.242/cgi-bin/demo/ 访问的为"hello world" 程序.




    sample 2 : 编写一个计算两个数字相乘的页面.


    先编写一个mul.html

    <head>
    <title><h1>Multiplication HTML<h1></title>
    </head>
    <body>
    <form action="http://13.187.241.242/cgi-bin/mul">
    <div><label>Multiplicand 1: <input name="m" size="5"></label></div>
    <div><label>Multiplicand 2: <input name="n" size="5"></label></div>
    <div><input type="submit" value="Multiply!"></div>
    </form>
    </body>
    </html>

    存放在/var/www/html/目录下.


    编写一个计算两个数相乘的C程序.

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
        char *data;
        long m,n;
        printf("%s%c%c/n","Content-Type:text/html;charset=iso-8859-1",13,10);
        printf("<TITLE>Multiplication results</TITLE>/n");
        printf("<H3>Multiplication results</H3>/n");
        data = getenv("QUERY_STRING");
        if(data == NULL)
                printf("<P>Error! Error in passing data from form to script./n");
        else if(sscanf(data,"m=%ld&n=%ld",&m,&n)!=2)
                printf("<P>Error! Invalid data. Data must be numeric.");
        else
                printf("<P>The product of %ld and %ld is %ld.",m,n,m*n);
        return 0;
}


    编译后放在/var/www/cgi-bin/目录下.

    访问http://13.187.241.242/mul.html即可.

    通过此例,我们可将CGI程序的一般工作过程总结为如下几点。
    1.通过检查环境变量CONTENT-LENGTH,确定有多少输入;
    2.循环使用getchar()或者其他文件读函数得到所有的输入;
    3.以相应的方法处理输入;
    4.通过"Contenttype:"头信息,将输出信息的格式告诉Web服务器;
    5.通过使用printf()或者putchar()或者其他的文件写函数,将输出传送给Web服务器。
    总之,CGI程序的主要任务就是从Web服务器得到输入信息,进行处理,然后将输出结果再送回给Web服务器。

二、环境变量

    环境变量是文本串(名字/值对),可以被OS Shell或其他程序设置 ,也可以被其他程序访问。它们是Web服务器传递数据给CGI程序的简

单手段,之所以称为环境变量是因为它们是全局变量,任何程序都可以存取它们。

    下面是CGI程序设计中常常要用到的一些环境变量。
    HTTP-REFERER:调用该CGI程序的网页的URL。
    REMOTE-HOST:调用该CGI程序的Web浏览器的机器名和域名。
    REQUEST-METHOD:指的是当Web服务器传递数据给CGI程序时所采用的方法,分为GET和POST两种方法。GET方法仅通过环境变量(如QUERY

-STRING)传递数据给CGI程序,而POST方法通过环境变量和标准输入传递数据给CGI程序,因此POST方法可较方便地传递较多的数据给CGI程序。

    SCRIPT-NAME:该CGI程序的名称。
    QUERY-STRING:当使用POST方法时,Form中的数据最后放在QUERY-STRING中,传递给CGI程序。
    CONTENT-TYPE:传递给CGI程序数据的MIME类型,通常为"applica tion/x-www-form-url encodede",它是从HTML Form中以POST方法传递

数据给CGI程序的数据编码类型,称为URL编码类型。
    CONTENT-LENGTH:传递给CGI程序的数据字符数(字节数)。
    在C语言程序中,要访向环境变量,可使用getenv()库函数。例如:
    if (getenv ("CONTENT-LENGTH"))
        n=atoi(getenv ("CONTENT-LENGTH"));

    请注意程序中最好调用两次getenv():第一次检查是否存在该环境变量,第二次再使用该环境变量。这是因为函数getenv()在给定的环

境变量名不存在时,返回一个NULL(空)指针,如果你不首先检查而直接引用它,当该环境变量不存在时会引起CGI程序崩溃。

三、From输入的分析和解码

    1.分析名字/值对
    当用户提交一个HTML Form时,Web浏览器首先对Form中的数据以名字/值对的形式进行编码,并发送给Web服务器,然后由Web服务器传递

给CGI程序。其格式如下:
    name1=value1&name2=value2&name3=value3&name4=value4&...
    其中名字是Form中定义的INPUT、SELECT或TEXTAREA等标置(Tag)名字,值是用户输入或选择的标置值。这种格式即为URL编码,程序中需

要对其进行分析和解码。要分析这种数据流,CGI程序必须首先将数据流分解成一组组的名字/值对。这可以通过在输入流中查找下面的两个字符

来完成。
    每当找到字符=,标志着一个Form变量名字的结束;每当找到字符& ,标志着一个Form变量值的结束。请注意输入数据的最后一个变量的

值不以&结束。
   一旦名字/值对分解后,还必须将输入中的一些特殊字符转换成相应的ASCII字符。这些特殊字符是:
   +:将+转换成空格符;
   %xx:用其十六进制ASCII码值表示的特殊字符。根据值xx将其转换成相应的ASCII字符。
   对Form变量名和变量值都要进行这种转换。下面是一个对Form数据进行分析并将结果回送给Web服务器的CGI程序。
   #include
   #include
   #include
   int htoi(char *);
   main()
   {
    int i,n;
   char c;
   printf ("Contenttype: text/plain");
   n=0;
   if (getenv("CONTENT-LENGTH"))
    n=atoi(getenv("CONTENT-LENGTH"));
   for (i=0; i   int is-eq=0;
   c=getchar();
   switch (c){
    case '&':
     c='';
     break;
    case '+':
     c=' ';
     break;
    case '%':{
     char s[3];
     s[0]=getchar();
     s[1]=getchar();
     s[2]=0;
     c=htoi(s);
     i+=2;
    }
    break;
   case '=':
    c=':';
    is-eq=1;
    break;
   };
   putchar(c);
   if (is-eq) putchar(' ');
   }
   putchar ('');
   fflush(stdout);
   }
   /* convert hex string to int */
   int htoi(char *s)
   {
    char *digits="0123456789ABCDEF";
   if (islower (s[0])) s[0]=toupper(s[0]);
   if (islower (s[1])) s[1]=toupper(s[1]);
   return 16 * (strchr(digits, s[0]) -strchr (digits,'0')
)
   +(strchr(digits,s[1])-strchr(digits,'0'));
   }

  上面的程序首先输出一个 MIME头信息给Web服务器,检查输入中的字符数,并循环检查每一个字符。当发现字符为&时,意味着一个名字/值对

的结束,程序输出一个空行; 当发现字符为+时,将它转换成空格; 当发现字符为%时,意味着一个两字符的十六进制值的开始,调用htoi()函数将

随后的两个字符转换为相应的ASCII字符;当发现字符为=时,意味着一个名字/值对的名字部分的结束,并将它转换成字符:。最后将转换后的字符

输出给Web服务器。

四、产生HTML输出

  CGI程序产生的输出由两部分组成:MIME头信息和实际的信息。两部分之间以一个空行分开。我们已经看到怎样使用MIME头信息"Content

type :text/plain"和printf()、put char()等函数调用来输出纯ASCII文本给Web服务器。实际上,我们也可以使用MIME头信息"Content type

:text/html"来输出HTML源代码给Web服务器。请注意任何MIME头信息后必须有一个空行。一旦发送这个MIME头信息给We b服务器后,Web浏览器

将认为随后的文本输出为HTML源代码,在HTML源代码中可以使用任何HTML结构,如超链、图像、Form,及对其他CGI 程 序的调用。也就是说,我们

可以在CGI程序中动态产生HTML源代码输出 ,下面是一个简单的例子。
   #include
   #include
   main()
   {
    printf("Contenttype:text/html");
    printf("<html>");
    printf("<head><title>An HTML Page From a CGI</title></head>");
    printf("<body><br>");
    printf("<h2> This is an HTML page generated from with i n a CGI program.. .</h2>");
    printf("<hr><p>");
    printf("<a href="../output.html#two"><b> Go back to output.html page </b></a>");
    printf("</body>");
    printf("</html>");
    fflush(stdout);
  }

  上面的CGI程序简单地用printf()函数来产生HTML源代码。请注意在输出的字符串中如果有双引号,在其前面必须有一个后斜字符/, 这是因

为整个HTML代码串已经在双引号内,所以HTML代码串中的双引号符必须用一个后斜字符/来转义。

五、结束语

  本文详细分析了用C语言进行CGI程序设计的方法、过程和技巧。C语言的CGI程序虽然执行速度快、可靠性高,但是相对于Perl语言来说,C语

言缺乏强有力的字符串处理能力,因此在实际应用中,应根据需 要和个人爱好来选择合适的CGI程序设计语言。




资料:http://www.cs.tut.fi/~jkorpela/forms/cgic.html

Getting Started with CGI Programming in C
Content
Why CGI programming?
A basic example
Analysis of the example
So what is CGI programming?
Using a C program as a CGI script
The Hello world test
How to process a simple form
Using METHOD="POST"
Further reading
This is an introduction to writing CGI programs in the C language. The reader is assumed to know the basics of C as well how

to write simple forms in HTML and to be able to install CGI scripts on a Web server. The principles are illustrated with very

simple examples.

Two important warnings:
To avoid wasting your time, please check—from applicable local doc­u­ments or by contacting local webmaster—whether you can

install and run CGI scripts written in C on the server. At the same time, please check how to do that in detail—

specifically, where you need to put your CGI scripts.
This document was written to illustrate the idea of CGI scripting to C pro­gram­mers. In practice, CGI programs are usually

written in other lan­guages, such as Perl, and for good reasons: except for very simple cases, CGI programming in C is clumsy

and error-prone.
Why CGI programming?
As my document How to write HTML forms briefly explains, you need a server side-script in order to use HTML forms reliably.

Typically, there are simple server-side scripts available for simple, common ways of processing form submissions, such as

sending the data in text format by E-mail to a specified address.

However, for more advanced processing, such as collecting data into a file or database, or retrieving information and sending

it back, or doing some calculations with the submitted data, you will probably need to write a server-side script of your

own.

CGI is simply an interface between HTML forms and server-side scripts. It is not the only possibility—see the excellent

tutorial How the web works: HTTP and CGI explained by Lars Marius Garshol for both an introduction to the concepts of CGI and

notes on other pos­si­bil­i­ties.

If someone suggests using JavaScript as an alternative to CGI, ask him to read my JavaScript and HTML: possibilities and

caveats. Briefly, JavaScript is inherently unreliable at least if not “backed up” with server-side scripting.

A basic example
The above-mentioned How the web works: HTTP and CGI explained is a great tutorial. The following introduction of mine is just

another attempt to present the basics; please consult other sources if you get confused or need more information.

Let us consider the following simple HTML form:

<form action="http://www.cs.tut.fi/cgi-bin/run/~jkorpela/mult.cgi">
<div><label>Multiplicand 1: <input name="m" size="5"></label></div>
<div><label>Multiplicand 2: <input name="n" size="5"></label></div>
<div><input type="submit" value="Multiply!"></div>
</form>It will look like the following on your current browser:

Multiplicand 1:
Multiplicand 2:

You can try it if you like. Just in case the server used isn’t running and accessible when you try it, here’s what you

would get as the result:

Multiplication results
The product of 4 and 9 is 36.

Analysis of the example
We will now analyze how the example above works.

Assume that you type 4 into one input field and 9 into another and then invoke sub­mis­sion—typically, by clicking on a

submit button. Your browser will send, by the HTTP protocol, a request to the server at www.cs.tut.fi. The browser pick up

this server name from the value of ACTION attribute where it occurs as the host name part of a URL. (Quite often, the ACTION

attribute refers, often using a relative URL, to a script on the same server as the document resides on, but this is not

necessary, as this example shows.)

When sending the request, the browser provides additional information, specifying a relative URL, in this case
/cgi-bin/run/~jkorpela/mult.cgi?m=4&n=9
This was constructed from that part of the ACTION value that follows the host name, by appending a question mark “?” and

the form data in a specifically encoded format.

The server to which the request was sent (in this case, www.cs.tut.fi) will then process it according to its own rules.

Typically, the server’s configuration defines how the relative URLs are mapped to file names and which directories/folders

are interpreted as containing CGI scripts. As you may guess, the part cgi-bin/ in the URL causes such interpretation in this

case. This means that instead of just picking up and sending back (to the browser that sent the request) an HTML document or

some other file, the server invokes a script or a program specified in the URL (mult.cgi in this case) and passes some data

to it (the data m=4&n=9 in this case).

It depends on the server how this really happens. In this particular case, the server actually runs the (executable) program

in the file mult.cgi in the subdirectory cgi-bin of user jkorpela’s home directory. It could be something quite different,

depending on server configuration.


So what is CGI programming?
The often-mystified abbreviation CGI, for Common Gateway Interface, refers just to a convention on how the invocation and

parameter passing takes place in detail.

Invocation means different things in different cases. For a Perl script, the server would invoke a Perl interpreter and make

it execute the script in an interpretive manner. For an executable program, which has typically been produced by a compiler

and a loader from a source program in a language like C, it would just be started as a separate process.

Although the word script typically suggests that the code is interpreted, the term CGI script refers both to such scripts and

to executable programs. See the answer to question Is it a script or a program? in CGI Programming FAQ by Nick Kew.

Using a C program as a CGI script
In order to set up a C program as a CGI script, it needs to be turned into a binary executable program. This is often

problematic, since people largely work on Windows whereas servers often run some version of UNIX or Linux. The system where

you develop your program and the server where it should be installed as a CGI script may have quite different architectures,

so that the same executable does not run on both of them.

This may create an unsolvable problem. If you are not allowed to log on the server and you cannot use a binary-compatible

system (or a cross-compiler) either, you are out of luck. Many servers, however, allow you log on and use the server in

interactive mode, as a “shell user,” and contain a C compiler.

You need to compile and load your C program on the server (or, in principle, on a system with the same architecture, so that

binaries produced for it are executable on the server too).

Normally, you would proceed as follows:

Compile and test the C program in normal interactive use.
Make any changes that might be needed for use as a CGI script. The program should read its input according to the intended

form sub­mis­sion method. Using the default GET method, the input is to be read from the environment variable. QUERY_STRING.

(The program may also read data from files—but these must then reside on the server.) It should generate output on the

standard output stream (stdout) so that it starts with suitable HTTP headers. Often, the output is in HTML format.
Compile and test again. In this testing phase, you might set the environment variable QUERY_STRING so that it contains the

test data as it will be sent as form data. E.g., if you intend to use a form where a field named foo contains the input data,

you can give the command
setenv QUERY_STRING "foo=42" (when using the tcsh shell)
or
QUERY_STRING="foo=42" (when using the bash shell).
Check that the compiled version is in a format that works on the server. This may require a recompilation. You may need to

log on into the server computer (using Telnet, SSH, or some other terminal emulator) so that you can use a compiler there.
Upload the compiled and loaded program, i.e. the executable binary program (and any data files needed) on the server.
Set up a simple HTML document that contains a form for testing the script, etc.
You need to put the executable into a suitable directory and name it according to server-specific conventions. Even the

compilation commands needed here might differ from what you are used to on your workstation. For example, if the server runs

some flavor of Unix and has the Gnu C compiler available, you would typically use a compilation command like gcc -o mult.cgi

mult.c and then move (mv) mult.cgi to a directory with a name like cgi-bin. Instead of gcc, you might need to use cc. You

really need to check local instructions for such issues.

The filename extension .cgi has no fixed meaning in general. However, there can be server-dependent (and operating system

dependent) rules for naming executable files. Typical extensions for executables are .cgi and .exe.

The Hello world test
As usual when starting work with some new programming technology, you should probably first make a trivial program work. This

avoids fighting with many potential problems at a time and concentrating first on the issues specific to the environment,

here CGI.

You could use the following program that just prints Hello world but preceded by HTTP headers as required by the CGI

interface. Here the header specifies that the data is plain ASCII text.

#include <stdio.h>
int main(void) {
  printf("Content-Type: text/plain;charset=us-ascii/n/n");
  printf("Hello world/n/n");
  return 0;
}
After compiling, loading, and uploading, you should be able to test the script simply by entering the URL in the browser’s

address bar. You could also make it the destination of a normal link in an HTML document. The URL of course depends on how

you set things up; the URL for my installed Hello world script is the following:
http://www.cs.tut.fi/cgi-bin/run/~jkorpela/hellow.cgi

How to process a simple form
For forms that use METHOD="GET" (as our simple example above uses, since this is the default), CGI specifications say that

the data is passed to the script or program in an environment variable called QUERY_STRING.

It depends on the scripting or programming language used how a program can access the value of an environment variable. In

the C language, you would use the library function getenv (defined in the standard library stdlib) to access the value as a

string. You might then use various techniques to pick up data from the string, convert parts of it to numeric values, etc.

The output from the script or program to “primary output stream” (such as stdin in the C language) is handled in a special

way. Effectively, it is directed so that it gets sent back to the browser. Thus, by writing a C program that it writes an

HTML document onto its standard output, you will make that document appear on user’s screen as a response to the form

submission.

In this case, the source program in C is the following:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *data;
long m,n;
printf("%s%c%c/n",
"Content-Type:text/html;charset=iso-8859-1",13,10);
printf("<TITLE>Multiplication results</TITLE>/n");
printf("<H3>Multiplication results</H3>/n");
data = getenv("QUERY_STRING");
if(data == NULL)
  printf("<P>Error! Error in passing data from form to script.");
else if(sscanf(data,"m=%ld&n=%ld",&m,&n)!=2)
  printf("<P>Error! Invalid data. Data must be numeric.");
else
  printf("<P>The product of %ld and %ld is %ld.",m,n,m*n);
return 0;
}
As a disciplined programmer, you have probably noticed that the program makes no check against integer overflow, so it will

return bogus results for very large operands. In real life, such checks would be needed, but such considerations would take

us too far from our topic.

Note: The first printf function call prints out data that will be sent by the server as an HTTP header. This is required for

several reasons, including the fact that a CGI script can send any data (such as an image or a plain text file) to the

browser, not just HTML documents. For HTML documents, you can just use the printf function call above as such; however, if

your character encoding is different from ISO 8859-1 (ISO Latin 1), which is the most common on the Web, you need to replace

iso-8859-1 by the registered name of the encoding (“charset”) you use.

I have compiled this program and saved the executable program under the name mult.cgi in my directory for CGI scripts at

www.cs.tut.fi. This implies that any form with action="http://www.cs.tut.fi/cgi-bin/run/~jkorpela/mult.cgi" will, when

submitted, be processed by that program.

Consequently, anyone could write a form of his own with the same ACTION attribute and pass whatever data he likes to my

program. Therefore, the program needs to be able to handle any data. Generally, you need to check the data before starting to

process it.

Using METHOD="POST"
The idea of METHOD="POST"
Let us consider next a different processing for form data. Assume that we wish to write a form that takes a line of text as

input so that the form data is sent to a CGI script that appends the data to a text file on the server. (That text file could

be readable by the author of the form and the script only, or it could be made readable to the world through another script.)

It might seem that the problem is similar to the example considered above; one would just need a different form and a

different script (program). In fact, there is a difference. The example above can be regarded as a “pure query” that does

not change the “state of the world.” In particular, it is “idempotent,” i.e. the same form data could be submitted as

many times as you like without causing any problems (except minor waste of resources). How­ever, our current task needs to

cause such changes—a change in the content of a file that is intended to be more or less permanent. Therefore, one should

use METHOD="POST". This is explained in more detail in the document Methods GET and POST in HTML forms - what’s the

difference? Here we will take it for granted that METHOD="POST" needs to be used and we will consider the technical

implications.

For forms that use METHOD="POST", CGI specifications say that the data is passed to the script or program in the standard

input stream (stdin), and the length (in bytes, i.e. characters) of the data is passed in an environment variable called

CONTENT_LENGTH.

Reading input
Reading from standard input sounds probably simpler than reading from an environment variable, but there are complications.

The server is not required to pass the data so that when the CGI script tries to read more data than there is, it would get

an end of file indi­ca­tion! That is, if you read e.g. using the getchar function in a C program, it is undefined what

happens after reading all the data characters; it is not guaranteed that the function will return EOF.

When reading the input, the program must not try to read more than CONTENT_LENGTH characters.

Sample program: accept and append data
A relatively simple C program for accepting input via CGI and METHOD="POST" is the following:

#include <stdio.h>
#include <stdlib.h>
#define MAXLEN 80
#define EXTRA 5
/* 4 for field name "data", 1 for "=" */
#define MAXINPUT MAXLEN+EXTRA+2
/* 1 for added line break, 1 for trailing NUL */
#define DATAFILE "../data/data.txt"

void unencode(char *src, char *last, char *dest)
{
 for(; src != last; src++, dest++)
   if(*src == '+')
     *dest = ' ';
   else if(*src == '%') {
     int code;
     if(sscanf(src+1, "%2x", &code) != 1) code = '?';
     *dest = code;
     src +=2; }    
   else
     *dest = *src;
 *dest = '/n';
 *++dest = '/0';
}

int main(void)
{
char *lenstr;
char input[MAXINPUT], data[MAXINPUT];
long len;
printf("%s%c%c/n",
"Content-Type:text/html;charset=iso-8859-1",13,10);
printf("<TITLE>Response</TITLE>/n");
lenstr = getenv("CONTENT_LENGTH");
if(lenstr == NULL || sscanf(lenstr,"%ld",&len)!=1 || len > MAXLEN)
  printf("<P>Error in invocation - wrong FORM probably.");
else {
  FILE *f;
  fgets(input, len+1, stdin);
  unencode(input+EXTRA, input+len, data);
  f = fopen(DATAFILE, "a");
  if(f == NULL)
    printf("<P>Sorry, cannot store your data.");
  else
    fputs(data, f);
  fclose(f);
  printf("<P>Thank you! Your contribution has been stored.");
  }
return 0;
}
Essentially, the program retrieves the information about the number of characters in the input from value of the

CONTENT_LENGTH environment variable. Then it unencodes (decodes) the data, since the data arrives in the specifically encoded

format that was already men­tioned. The program has been written for a form where the text input field has the name data

(actually, just the length of the name matters here). For example, if the user types
Hello there!
then the data will be passed to the program encoded as
data=Hello+there%21
(with space encoded as + and exclamation mark encoded as %21). The unencode routine in the program converts this back to the

original format. After that, the data is appended to a file (with a fixed file name), as well as echoed back to the user.

Having compiled the program I have saved it as collect.cgi into the directory for CGI scripts. Now a form like the following

can be used for data submissions:

<FORM ACTION="http://www.cs.tut.fi/cgi-bin/run/~jkorpela/collect.cgi"
 METHOD="POST">
<DIV>Your input (80 chars max.):<BR>
<INPUT NAME="data" SIZE="60" MAXLENGTH="80"><BR>
<INPUT TYPE="SUBMIT" VALUE="Send"></DIV>
</FORM>
Sample program: view data stored on a file
Finally, we can write a simple program for viewing the data; it only needs to copy the content of a given text file onto

standard output:

#include <stdio.h>
#include <stdlib.h>
#define DATAFILE "../data/data.txt"
int main(void)
{
FILE *f = fopen(DATAFILE,"r");
int ch;
if(f == NULL) {
  printf("%s%c%c/n",
  "Content-Type:text/html;charset=iso-8859-1",13,10);
  printf("<TITLE>Failure</TITLE>/n");
  printf("<P><EM>Unable to open data file, sorry!</EM>"); }
else {
  printf("%s%c%c/n",
  "Content-Type:text/plain;charset=iso-8859-1",13,10);
  while((ch=getc(f)) != EOF)
    putchar(ch);
  fclose(f); }
return 0;
}
Notice that this program prints (when successful) the data as plain text, preceded by a header that says this, i.e. has

text/plain instead of text/html.

A form that invokes that program can be very simple, since no input data is needed:

<form action="http://www.cs.tut.fi/cgi-bin/run/~jkorpela/collect.cgi"
 method="POST">
<div><label for="data">Your input</label> (80 chars max.):</div>
<div><input id="data" name="data" size="60" maxlength="80"></div>
<div><input type="submit" value="Send"></div>
</form>Finally, here’s what the two forms look like. You can now test them:

Form for submitting data
Please notice that anything you submit here will become visible to the world:

Your input (80 chars max.):


Form for checking submitted data
The content of the text file to which the submissions are stored will be displayed as plain text.


Even though the output is declared to be plain text, Internet Explorer may interpret it partly as containing HTML markup.

Thus, if someone enters data that contains such markup, strange things would happen. The viewdata.c program takes this into

account by writing the NUL character ('/0') after each occurrence of the greater-than character lt;, so that it will not be

taken (even by IE) as starting a tag.

Further reading
You may now wish to read The CGI specification, which tells you all the basic details about CGI. The next step is probably to

see what the CGI Programming FAQ contains. Beware that it is relatively old.

There is a lot of material, including introductions and tutorials, in the CGI Resource Index. Notice in particular the

section Programs and Scripts: C and C++: Libraries and Classes, which contains libraries that can make it easier to process

form data. It can be instructive to parse simple data format by using code of your own, as was done in the simple examples

above, but in practical application a library routine might be better.

The C language was originally designed for an environment where only ASCII characters were used. Nowadays, it can be used—

with caution—for processing 8-bit characters. There are various ways to overcome the limitation that in C implementations, a

character is generally an 8-bit quantity. See especially the last section in my book Unicode Explained.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值