解码数据发送给CGI脚本
当使用表单的时候,收集在表单的信息给发送给CGI脚本用于处理。这个信息被放置在环境变量QUERY_STRING中。
为了清除地将信息传递给环境变量QUERY_STRING,被修改锚标签的表单将被使用。在这个被修改的锚标签中,传递给环境变量 QUERY_STRING的数据是在指示CGI脚本的URL之后附上的。字符”?”被用来分隔指定CGI脚本以及发送给脚本的数据的URL。比如:
<A HREF="/cgi-bin/script?name=Your+name&action=find"> Link </A>
其中数据"name=Your+name&action=find"被放置在环境变量QUERY_STRING中并且CGI脚本被执行。
下面给出一个例子:由C++编写一个类,具体文件parse.h 和parse.cpp被用于在QUERY_STRING中提取个别的组件,其中的头文件t99_type.h在上节教程已经提到,它是包含了一些定义。具体代码如下:
//以下是parse.h文件
#ifndef CLASS_PARSE
#define CLASS_PARSE
//#define NO_MAP // 定义没有用户处理
#include "t99_type.h"//这个文件在前面教程中有
class Parse
{
public:
Parse( char [] );
~Parse();
void set( char [] );
char *get_item( char [], int pos=1, bool=false );
char *get_item_n( char [], int pos=1, bool=false );
protected:
void remove_escape(char []);
int hex( char ); //返回十六进制数
char *map_uname( char [] );
private:
enum { SEP = '&' }; // 使用&分隔字符
char *the_str; // 字符部分
int the_length; // 字符长度
};
#endif
//以下是parse.cpp文件
#ifndef CLASS_PARSE_IMP
#define CLASS_PARSE_IMP
#include "parse.h"
#include
#include
#ifndef NO_MAP
# include
#endif
Parse::Parse( char list[] )
{
the_str = NULL;
set( list );
}
Parse::~Parse()
{
if ( the_str != NULL ) { // 释放存储器
delete [] the_str;
}
}
void Parse::set( char list[] )
{
if ( the_str != NULL ) { // 释放存储器
delete [] the_str;
}
the_length = strlen( list ); // 字符长度
the_str = new char[the_length+1]; // 分配空间
strcpy( the_str, list ); // 复制
}
char *Parse::get_item( char name[], int pos, bool file )
{
int len = strlen( name );
int cur_tag = 1;
for( int i=0; i
{
if ( the_str[i] == name[0] &&
strncmp( &the_str[i], name, len ) == 0 )
{
if ( the_str[i+len] == '=' )
{
if ( cur_tag == pos )
{
int start = i+len+1; int j = start;
while ( the_str[j] != SEP && the_str[j] != '\0' ) j++;
int str_len = j-start;
char *mes = new char[ str_len+1 ];
strncpy( mes, &the_str[start], str_len );
mes[str_len] = '\0';
remove_escape( mes );
# ifndef NO_MAP
return file ? map_uname(mes) : mes;
# else
return file ? mes : mes;
# endif
} else {
cur_tag++;
}
}
}
}
return NULL;
}
char *Parse::get_item_n( char name[], int pos, bool file )
{
char *res = get_item( name, pos, file );
return res == NULL ? (char*)"----" : res;
}
void Parse::remove_escape(char str[])
{
char * from = &str[0];
char * to = &str[0];
while ( *from != '\0' )
{
char ch = *from++;
switch ( ch )
{
case '%' :
ch = (hex(*from++)><4) | hex(*from++);
break;
case '+' :
ch = ' '; break;
}
*to++ = ch;
}
*to = '\0';
}
int Parse::hex( char c )
{
if ( isdigit( c ) )
return c-'0';
if ( isalpha( c ) )
return tolower(c)-'a'+10;
return 0;
}
char* Parse::map_uname( char *path )
{
#ifndef NO_MAP
if ( path[0] == '~' )
{
char uname[255]; // 容纳用户名字的变量
char *rest = &path[1];
char *p = &uname[0];
while ( *rest != '/' && *rest != '\0' )
{
*p++ = *rest++;
}
*p = '\0'; // 结束标识
char *root = uname;
passwd *pw = getpwnam( uname );
if ( pw != NULL )
{
root = pw->pw_dir; // 用户的主目录
}
int len_root = strlen(root);
int len_path = len_root + strlen(rest);
char *new_path = new char[len_path+1]; // 动态字符
strcpy( &new_path[0], root ); // 复制用户路径
strcpy( &new_path[len_root], rest ); // 其余部分
return new_path;
} else {
return path;
}
#endif
return path;
}
#endif
解码数据发送给CGI脚本
这个类的成员函数有:
方法
任务
Parse
设置将要解析的字符串
set
设置一个要解析的不同字符串
get_item
返回字符串有关的关键字作为参数传递,如果没有数据就返回NULL
get_item_n
返回字符串有关的关键字作为参数传递,如果没有数据就返回空字符串
当使用成员函数get_item和get_item_n的时候,可选的第二个参数指定哪个跟关键字有关的字符串被返回。这样就允许恢复附在同一关键字的信息。另外,返回的字符串将有以下一系列的替代物:
+将被转换成空格;
%HH将把十六进制的数转换为字符;
~user将被用户主目录的完整路径取代,这也只有在可选第三个参数为true的时候才可以。
解码数据发送给CGI脚本
下面举个例字,如果QUERY_STRING包含以下内容:
tag=one&name=mike&action=%2B10%25&tag=two&log=~mas/log&tag=three
那么以下的程序将被编译和运行:
enum bool { false, true };
#include
#include
#include "parse.h"
#include "parse.cpp"
void main()
{
char *query_str = getenv("QUERY_STRING");
Parse list( query_str );
cout << "name = " << list.get_item_n( "name" ) << "\n";
cout << "action= " << list.get_item_n( "action" ) << "\n";
cout << "log = " << list.get_item_n( "log", 1, true ) << "\n";
for ( int i=1; i<=4; i++ )
{
cout << "tag (" << i << ") = ";
cout << list.get_item_n( "tag" , i ) << "\n";
}
}
结果它的输出为:
name = mike
action= +10%
log = /usr/staff/mas/log
tag (1) = one
tag (2) = two
tag (3) = three
tag (4) =