首页    新闻    下载    文档    论坛     最新漏洞    黑客教程    数据库    搜索    小榕软件实验室怀旧版    星际争霸WEB版    最新IP准确查询   
名称: 密码:      忘记密码  马上注册
安全知识 :: 黑客教程

post是什么意思


http://www.gipsky.com/
在许多应用程序中使用GET都没有问题。但是,GET要求通过一个环境变量将自己的数据传递给CGI程序。但假如GET字串过长,有些Web服务器可能用光自己的环境空间(若字串长度超过200字符,就应开始关心这方面的问题)。CGI为此提供了一个解决方案:POST。通过POST,数据可以编码,并按与GET相同的方法连结起来。但POST利用标准输入将编码过后的查询字串传递给CGI程序。我们要做的全部事情就是判定查询字串的长度,而这个长度已在环境变量CONTENT_LENGTH中保存好了。一旦知道了长度,就可自由分配存储空间,并从标准输入中读入指定数量的字符。

对一个用来控制POST的CGI程序,由CGITools.h提供的Pair和CGI_vector均可不加丝毫改变地使用。下面这段程序揭示了写这样的一个CGI程序有多么简单。这个例子将采用“纯”C ,所以studio.h库被iostream(IO数据流)代替。对于iostream,我们可以使用两个预先定义好的对象:cin,用于同标准输入连接;以及cout,用于同标准输出连接。有几个办法可从cin中读入数据以及向cout中写入。但下面这个程序预备采用标准方法:用“<<”将信息发给cout,并用一个成员函数(此时是read())从cin中读入数据:





//: POSTtest.cpp

// CGI_vector works as easily with POST as it

// does with GET. Written in "pure" C .

#include <iostream.h>

#include "CGITools.h"



void main() {

cout << "Content-type: text/plain\n" << endl;

// For a CGI "POST," the server puts the length

// of the content string in the environment

// variable CONTENT_LENGTH:

char* clen = getenv("CONTENT_LENGTH");

if(clen == 0) {

cout << "Zero CONTENT_LENGTH" << endl;

return;

}

int len = atoi(clen);

char* query_str = new char[len 1];

cin.read(query_str, len);

query_str[len] = '\0';

CGI_vector query(query_str);

// Test: dump all names and values

for(int i = 0; i < query.size(); i )

cout << "query[" << i << "].name() = [" <<

query<i>.name() << "], " <<

"query[" << i << "].value() = [" <<

query<i>.value() << "]" << endl;

delete query_str; // Release storage

} ///:~

getenv()函数返回指向一个字串的指针,那个字串指示着内容的长度。若指针为零,表明CONTENT_LENGTH环境变量尚未设置,所以肯定某个地方出了问题。否则就必须用ANSI C库函数atoi()将字串转换成一个整数。这个长度将与new一起运用,分配足够的存储空间,以便容纳查询字串(另加它的空中止符)。随后为cin()调用read()。read()函数需要取得指向目标缓冲区的一个指针以及要读入的字节数。随后用空字符(null)中止query_str,指出已经抵达字串的末尾,这就叫作“空中止”。

到这个时候,我们得到的查询字串与GET查询字串已经没有什么区别,所以把它传递给用于CGI_vector的构建器。随后便和前例一样,我们可以自由vector内不同的字段。

为测试这个程序,必须把它编译到主机Web服务器的cgi-bin目录下。然后就可以写一个简单的HTML页进行测试,就象下面这样:





<HTML>

<HEAD>

<META CONTENT="text/html">

<TITLE>A test of standard HTML POST</TITLE>

</HEAD>

Test, uses standard html POST

<Form method="POST" ACTION="/cgi-bin/POSTtest">

<P>Field1: <INPUT TYPE = "text" NAME = "Field1"

VALUE = "" size = "40"></p>

<P>Field2: <INPUT TYPE = "text" NAME = "Field2"

VALUE = "" size = "40"></p>

<P>Field3: <INPUT TYPE = "text" NAME = "Field3"

VALUE = "" size = "40"></p>

<P>Field4: <INPUT TYPE = "text" NAME = "Field4"

VALUE = "" size = "40"></p>

<P>Field5: <INPUT TYPE = "text" NAME = "Field5"

VALUE = "" size = "40"></p>

<P>Field6: <INPUT TYPE = "text" NAME = "Field6"

VALUE = "" size = "40"></p>

<p><input type = "submit" name = "submit" > </p>

</Form>

</HTML>

填好这个表单并提交出去以后,会得到一个简单的文本页,其中包含了解析出来的结果。从中可知道CGI程序是否在正常工作。

当然,用一个程序片来提交数据显得更有趣一些。然而,POST数据的提交属于一个不同的过程。在用常规方式调用了CGI程序以后,必须另行建立与服务器的一个连接,以便将查询字串反馈给它。服务器随后会进行一番处理,再通过标准输入将查询字串反馈回CGI程序。

为建立与服务器的一个直接连接,必须取得自己创建的URL,然后调用openConnection()创建一个URLConnection。但是,由于URLConnection一般不答应我们把数据发给它,所以必须很可笑地调用setDoOutput(true)函数,同时调用的还包括setDoInput(true)以及setAllowUserInteraction(false)??注释⑥。最后,可调用getOutputStream()来创建一个OutputStream(输出数据流),并把它封装到一个DataOutputStream里,以便能按传统方式同它通信。下面列出的便是一个用于完成上述工作的程序片,必须在从它的各个字段里收集了数据之后再执行它:





//: POSTtest.java

// An applet that sends its data via a CGI POST

import java.awt.*;

import java.applet.*;

import java.net.*;

import java.io.*;



public class POSTtest extends Applet {

final static int SIZE = 10;

Button submit = new Button("Submit");

TextField[] t = new TextField[SIZE];

String query = "";

Label l = new Label();

TextArea ta = new TextArea(15, 60);

public void init() {

Panel p = new Panel();

p.setLayout(new GridLayout(t.length 2, 2));

for(int i = 0; i < t.length; i ) {

p.add(new Label(

"Field " i " ", Label.RIGHT));

p.add(t<i> = new TextField(30));

}

p.add(l);

p.add(submit);

add("North", p);

add("South", ta);

}

public boolean action (Event evt, Object arg) {

if(evt.target.equals(submit)) {

query = "";

ta.setText("");

// Encode the query from the field data:

for(int i = 0; i < t.length; i )

query = "Field" i "="

URLEncoder.encode(

t<i>.getText().trim())

"&";

query = "submit=Submit";

// Send the name using CGI's POST process:

try {

URL u = new URL(

getDocumentBase(), "cgi-bin/POSTtest");

URLConnection urlc = u.openConnection();

urlc.setDoOutput(true);

urlc.setDoInput(true);

urlc.setAllowUserInteraction(false);

DataOutputStream server =

new DataOutputStream(

urlc.getOutputStream());

// Send the data

server.writeBytes(query);

server.close();

// Read and display the response. You

// cannot use

// getAppletContext().showDocument(u);

// to display the results as a Web page!

DataInputStream in =

new DataInputStream(

urlc.getInputStream());

String s;

while[1] != null) {

ta.appendText(s "\n");

}

in.close();

}

catch (Exception e) {

l.setText(e.toString());

}

}

else return super.action(evt, arg);

return true;

}

} ///:~⑥:我不得不说自己并没有真正理解这儿都发生了什么事情,这些概念都是从Elliotte Rusty Harold编著的《Java Network Programming》里得来的,该书由O'Reilly于1997年出版。他在书中提到了Java连网函数库中出现的许多令人迷惑的Bug。所以一旦涉足这些领域,事情就不是编写代码,然后让它自己运行那么简单。一定要警惕潜在的陷阱!



信息发送到服务器后,我们调用getInputStream(),并把返回值封装到一个DataInputStream里,以便自己能读取结果。要注重的一件事情是结果以文本行的形式显示在一个TextArea(文本区域)中。为什么不简单地使用getAppletContext().showDocument(u)呢?事实上,这正是那些陷阱中的一个。上述代码可以很好地工作,但假如试图换用showDocument(),几乎一切都会停止运行。也就是说,showDocument()确实可以运行,但从POSTtest得到的返回结果是“Zero CONTENT_LENGTH”(内容长度为零)。所以不知道为什么原因,showDocument()阻止了POST查询向CGI程序的传递。我很难判定这到底是一个在以后版本里会修复的Bug,还是由于我的理解不够(我看过的书对此讲得都很模糊)。但无论在哪种情况下,只要能坚持在文本区域里观看自CGI程序返回的内容,上述程序片运行时就没有问题。
附注
  1. s = in.readLine(
<< 用Delphi实现文件下载的方法 c 读取文件 >>
评分
10987654321
API:
gipsky.com& 安信网络
网友个人意见,不代表本站立场。对于发言内容,由发表者自负责任。

系统导航

 

Copyright © 2001-2010 安信网络. All Rights Reserved
京ICP备05056747号