CGIC(二)——实例编程


向浏览器打印信息

源码

#include "cgic.h"
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int cgiMain(){
    //打印HTTP协议请求头
    cgiHeaderContentType("text/html");
    fprintf(cgiOut,"<html><HEAD>\n");
    fprintf(cgiOut,"<TITLE>Printf information to browser</TITLE></HEAD>\n");
    fprintf(cgiOut,"<BODY><H1>Hello CGIC</H1><BODY>\n");
    fprintf(cgiOut,"</HTML>\n");
    return 0;
}


Makefile

SOURCE := cgic_print.c cgic.c
OBJ := cgic_print.o cgic.o

TARGET :=cgic_print

CC := gcc
CROSS_COMPILE :=
LIBS :=
LDFLAGS :=
INCLUDE := -I .
DEFINES :=
CFLAGS :=-Wall -g $(INCLUDE) $(DEFINES)
OUTPUT := /home/jacky/www/cgi
HTML := index.html
www := /home/jacky/www/www
all:$(TARGET)
$(TARGET):$(OBJ)
	$(CROSS_COMPILE)$(CC)  $(LDFLAGS) -o $@ $^
	cp $@ $(OUTPUT)

%.o:%.c
	$(CROSS_COMPILE)$(CC) $(CFLAGS) -c -o $@ $^
.PHONY:clean
clean:
	rm -f $(TARGET) *.o

测试

在这里插入图片描述启动服务器
在这里插入图片描述
浏览器访问
在这里插入图片描述
在这里插入图片描述

获取请求参数

如果不使用CGIC库,要获取请求参数:
用getenv从环境变量中获取QueryString:char* queryString=getenv("QUERY_STRING");

char* qs=getenv("QUERY_STRING");
//使用sscanf函数,可以从字符串中进行查找字符

使用cgic库函数cgiFormString:

char pwd[128]={0};
cgiFormString("pwd",pwd,sizeof(pwd)-1);

重定位网页

调用cgic库函数
void cgiHeaderLocation(char* redirectUrl);
重定向到redirectUrl指定的地址。
cgiHeaderLocation("http://www.baidu.com");就会直接跳转到百度网页

获取GET请求字符串

GET请求就是我们在浏览器地址栏输入URL时发送请求的方式,或者我们在HTML表单中定义一个表单(form)时,把METHOD属性设置为GET工作时的工作方式;
GET请求字符串就是跟在URL后面以问号开始的字符串,但不包括问号,如果有多个值,则使用&进行分割。比如http:/127.0.0.1/cgi-bin/1.cgi?uer=xxx&pwd=xxx
在上面的例子中后面的就是GET请求的字符串。
在进入我们编写的代码前,CGIC库通过环境变量已经获取到了这个字符串,而我们只需要调用函数接口,就可以直接获得。因此我们需要提前声明该函数
extern char* cgiQueryString;

HTML

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta http-equiv="Content-Type" content="text/html"; charset="UTF-8">
    <title>CGIC-GET</title>
</head>
<body>
    <form action="cgi-bin/cgic_get" method="get" enctype="multipart/form-data" target="_blank">
        <input type="text" autocomplete="off" name="user" value="" placeholder="用户名" required/>
        <br>
        <input type="password" autocomplete="off" name="pwd" placeholder="密码" required maxlength="32"/>
        <br>
        <input type="submit" name="submit" value="提交">
    </form>
</body>
</html>

源码

#include "cgic.h"
#include<stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

//声明获取QUERY_STRING环境变量值函数
extern char* cgiQueryString;
int cgiMain(){
    char user[128];
    char pwd[128];
    //打印请求信息头
    cgiHeaderContentType("text/html");
    fprintf(cgiOut,"<HTML><HEAD>\n");
    fprintf(cgiOut,"<TITLE>GET TEST</TITLE></HEAD>\n");
    fprintf(cgiOut,"<BODY>");
    cgiFormString("user",user,sizeof(user)-1);
    cgiFormString("pwd",pwd,sizeof(pwd)-1);
    fprintf(cgiOut,"<H1>%s</H1>",cgiQueryString);
    fprintf(cgiOut,"<br>");
    fprintf(cgiOut,"<h2>%s</h2>",user);
    fprintf(cgiOut,"<br>");
    fprintf(cgiOut,"<h2>%s</h2>",pwd);
    fprintf(cgiOut,"</BODY>\n");
    fprintf(cgiOut,"</HTML>\n");
    return 0;
}


Makefile

SOURCE := cgic_get.c cgic.c
OBJ := cgic_get.o cgic.o

TARGET :=cgic_get

CC := gcc
CROSS_COMPILE :=
LIBS :=
LDFLAGS :=
INCLUDE := -I .
DEFINES :=
CFLAGS :=-Wall -g $(INCLUDE) $(DEFINES)
OUTPUT := /home/jacky/www/cgi
HTML := index.html
www := /home/jacky/www/www
all:$(TARGET)
$(TARGET):$(OBJ)
	$(CROSS_COMPILE)$(CC)  $(LDFLAGS) -o $@ $^
	cp $@ $(OUTPUT)
	cp $(HTML) $(www)
%.o:%.c
	$(CROSS_COMPILE)$(CC) $(CFLAGS) -c -o $@ $^
.PHONY:clean
clean:
	rm -f $(TARGET) *.o

测试

启动程序
在这里插入图片描述

浏览器访问
在这里插入图片描述
测试
Get方式提交信息
在这里插入图片描述
在这里插入图片描述

获取POST请求字符串

相信到现在,大家已经对POST和GET方式请求服务器数据已经非常清晰了,这里我还是进行说明,POST传递请求参数不会放在URL中,而是放在请求信息中,所以不会有大小的限制,而且相对安全。下面我们以POST的方式来传递表单信息。

HTML

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta http-equiv="Content-Type" content="text/html"; charset="UTF-8">
    <title>CGIC-GET</title>
</head>
<body>
    <form action="cgi-bin/cgic_post" method="post" enctype="multipart/form-data" target="_blank">
        <input type="text" autocomplete="off" name="user" value="" placeholder="用户名" required/>
        <br>
        <input type="password" autocomplete="off" name="pwd" placeholder="密码" required maxlength="32"/>
        <br>
        <input type="submit" name="submit" value="提交">
    </form>
</body>
</html>

源码

#include "cgic.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

extern char* cgiQueryString;
int cgiMain(){
    char user[128];
    char pwd[128];
    //打印HTTP协议头
    cgiHeaderContentType("text/html");
    fprintf(cgiOut,"<html><head>\n");
    fprintf(cgiOut,"<title>POST TEST</title></head>\n");
    fprintf(cgiOut,"<body>");
    fprintf(cgiOut,"<h1>%s</h1>",cgiQueryString);
    cgiFormString("user",user,sizeof(user)-1);
    cgiFormString("pwd",pwd,sizeof(pwd)-1);
    fprintf(cgiOut,"<br>");
    fprintf(cgiOut,"<h2>%s</h2>",user);
    fprintf(cgiOut,"<br>");
    fprintf(cgiOut,"<h2>%s</h2>",pwd);
    fprintf(cgiOut,"</body>\n");
    fprintf(cgiOut,"</html>\n");
    return 0;
}

Makefile

SOURCE := cgic_post.c cgic.c
OBJ := cgic_post.o cgic.o

TARGET :=cgic_post

CC := gcc
CROSS_COMPILE :=
LIBS :=
LDFLAGS :=
INCLUDE := -I .
DEFINES :=
CFLAGS :=-Wall -g $(INCLUDE) $(DEFINES)
OUTPUT := /home/jacky/www/cgi
HTML := index.html
www := /home/jacky/www/www
all:$(TARGET)
$(TARGET):$(OBJ)
	$(CROSS_COMPILE)$(CC)  $(LDFLAGS) -o $@ $^
	cp $@ $(OUTPUT)
	cp $(HTML) $(www)
%.o:%.c
	$(CROSS_COMPILE)$(CC) $(CFLAGS) -c -o $@ $^
.PHONY:clean
clean:
	rm -f $(TARGET) *.o

测试

在这里插入图片描述在这里插入图片描述浏览器访问
在这里插入图片描述

在这里插入图片描述

CGIC反转义

在前面的GET请求中,已经介绍过反转义是什么了。这里在详细介绍并告诉大家如何操作
浏览器在发送GET请求时,会把请求字符串进行转义操作;
比如我们在地址栏输入
http://localhost/~Jack/cgi-bin/out.cgi?it's me
浏览器就会自动转义为
http://localhost/~Jack/cgi-bin/out.cgi?it%27s%20me
那么通过CGIC,我们可以把这些转义后的字符还原为本来的输入,这就是反转义

操作

第一步:
cgic.c中找到该函数的声明,注意不是定义
在这里插入图片描述去掉这个static关键字
第二步:
在第一步函数声明上方有一个枚举
在这里插入图片描述将这几行语句复制到cgic.h头文件中,并在这里将它注释掉

第三步:
下面我们就可以愉快的使用该函数了
extern cgiUnescapeResultType cgiUnescapeChars(char **sp,char *cp ,int len);

HTML

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta http-equiv="Content-Type" content="text/html"; charset="UTF-8">
    <title>CGIC-GET</title>
</head>
<body>
    <form action="cgi-bin/cgic_unescape" method="GET" enctype="multipart/form-data" target="_blank">
        <input type="text" autocomplete="off" name="user" value="" placeholder="信息" required/>
        <br>
        <input type="submit" name="submit" value="submit">
    </form>
</body>
</html>

源码

#include "cgic.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
extern char* cgiQueryString;
extern cgiUnescapeResultType cgiUnescapeChars(char **sp,char *cp,int len);

int cgiMain(){
    //打印HTTP协议信息头
    char *buffer;
    cgiHeaderContentType("text/html");
    fprintf(cgiOut, "<HTML><HEAD>\n");
    fprintf(cgiOut, "<TITLE>My CGI</TITLE></HEAD>\n");
    fprintf(cgiOut, "<BODY>");
    cgiUnescapeChars(&buffer,cgiQueryString,strlen(cgiQueryString));
    fprintf(cgiOut, "<H1>%s</H1>",buffer);
    fprintf(cgiOut, "</BODY>\n");
    fprintf(cgiOut, "</HTML>\n");
    //释放掉由CGIC库函数在堆上申请的空间
    free(buffer);
    return 0;
}


Makefile

SOURCE := cgic_unescape.c cgic.c
OBJ := cgic_unescape.o cgic.o

TARGET :=cgic_unescape

CC := gcc
CROSS_COMPILE :=
LIBS :=
LDFLAGS :=
INCLUDE := -I .
DEFINES :=
CFLAGS :=-Wall -g $(INCLUDE) $(DEFINES)
OUTPUT := /home/jacky/www/cgi
HTML := index.html
www := /home/jacky/www/www
all:$(TARGET)
$(TARGET):$(OBJ)
	$(CROSS_COMPILE)$(CC)  $(LDFLAGS) -o $@ $^
	cp $@ $(OUTPUT)
	cp $(HTML) $(www)
%.o:%.c
	$(CROSS_COMPILE)$(CC) $(CFLAGS) -c -o $@ $^
.PHONY:clean
clean:
	rm -f $(TARGET) *.o

测试

在这里插入图片描述
浏览器访问
在这里插入图片描述在这里插入图片描述反转义成功

注意

buffer的存储空间是cgiUnescapeChars帮我们分配的,但是最后是需要我们手动释放的,防止内存泄漏

为什么不得不用hacker的方式来完成该让任务,而CGIC不显示提供?

CGIC 的出发点是,我们平时只需要解析请求中的键值对,比如:”?q=nice&client=IE”,当我们在服务端查询“q”的值时,我们就能得到 “nice”。CGIC有一族函数帮助我们完成这个任务,比如cgiFormString。在解析这种请求格式的时候,如果我们提供的参数值含有被转义的字符,那么CGIC就会在内部调用cgiUnescapeChars完成反转义。
但是,有时候我们会发送非常复杂的Get请求字符串,但并不是“键-值”对的格式。这就需要直接使用cgiUnescapeChars进行反转义了。
例如:假设我们有个服务端cgi程序chat.cgi,这是个网络聊天机器人(也许你可以开发自己的Web版MSN机器人、QQ机器人)。如果我们发送如下请求:
http://127.0.0.1/cgi-bin/chat.cgi?"this is a cgi user"
  那么chat.cgi就会把“this is a cgi user”当做你对它说的话,经过处理,它会回复一段语句。为了方便,我们并没有写成“键-值”对的形式。这个时候被我们hack的cgiUnescapeChars就能派上用场了。

浏览器上传文件

在上一个CGIC博客中实现的就是上传文件到BOA,需要的朋友可以去看上一篇博客。

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jacky~~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值