董老师前几天给我们布置了3道作业,第三道作业是cgi程序设计。

题目:

  web服务器cgi接口功能的实现

要求:

  能调用cgi程序并得到返回结果;

  cgi程序能接受参数并得到返回结果;

  使用两种或以上语言实现。

我的想法是:

1、既然要求能够接受参数,那么必然需要使用到表单来提交用户数据,方法可以为get或者post。

2、使用linux系统下最通用的语言——c语言,最通用的脚本语言——shell脚本。

3、该cgi程序为一个linux命令,post的数据即为该命令的参数。我选择了man命令,因为使用该命令,基本上不会产生安全隐患。不仅输入的参数具有丰富的可选项,而且不同的参数返回的结果具有很强的差异性。

一、前台html的设计

代码示例

<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>man for web</title>
<link rel="stylesheet" type="text/css" href="man.css"/> <body>
<div id="box">
<h1>man for web</h1>
<form method="get" action="/cgi-bin/man.sh" name="myform">
<input type="text" placeholder="使用shell脚本" name="cmd"></input>
<button class="but" type="submit">确定</button>
</form>
<br>
<form method="post" action="/cgi-bin/man.exe" name="myform">
<input type="text" placeholder="使用c语言" name="cmd"></input>
<button class="but" type="submit">确定</button>
</form>
</div>
</body>
</html>

  

man.css代码

html{
width: 100%;
height: 100%;
overflow: hidden;
}
body{
width: 100%;
height: 100%;
margin: 0;
background-color: #4A374A;
}
#box{
position: absolute;
top: 50%;
left:50%;
margin: -150px 0 0 -150px;
width: 300px;
height: 300px;
}
#box h1{
color: #fff;
letter-spacing: 1px;
text-align: center;
}
h1{
font-size: 2em;
margin: 0.67em 0;
}
input{
width: 278px;
height: 18px;
margin-bottom: 10px;
outline: none;
padding: 10px;
font-size: 13px;
color: #fff;
border-top: 1px solid #312E3D;
border-left: 1px solid #312E3D;
border-right: 1px solid #312E3D;
border-bottom: 1px solid #56536A;
border-radius: 4px;
background-color: #2D2D3F;
}
.but{
width: 300px;
min-height: 20px;
display: block;
background-color: #4a77d4;
border: 1px solid #3762bc;
color: #fff;
padding: 9px 14px;
font-size: 15px;
line-height: normal;
border-radius: 5px;
margin: 0;
}

  

二、cgi程序设计

  1、c语言

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE 2000
main()
{
char poststr[14];
char cmd[10];
printf ("Content-type:text/plain \n\n");
int n=0;
int i;
if(getenv("CONTENT_LENGTH"))
{
n=atoi(getenv("CONTENT_LENGTH"));
fgets(poststr,n+1,stdin);
sscanf(poststr,"cmd=%s",cmd); char cmds[15];
sprintf(cmds,"man %s > data.txt",cmd);
system(cmds); FILE* fp;
int len;
if((fp=fopen("data.txt","r"))==NULL)
{
perror("fail to read");
}
while(fgets(buf,MAX_LINE,fp)!=NULL)
{
len=strlen(buf);
buf[len-1] = '\0';
printf("%s\n",buf);
}
} else{
printf("error");}
}

程序思路:

调用system函数,将处理过得post数据作为参数进行处理。

具体实现方法:  

  "Content-type:html/plain \n\n"这条语句用于输出头信息,浏览器读取到后,可获知该网页格式为plain(标准ascii字符),紧接着的两个\n\n缺一不可,否则该cgi程序不会被执行,并且访问的时候会显示500错误,查看apache2错误日志,记录为“malformed header from script. Bad header=xxx”或者“Premature end of script headers”。

  数组poststr[15]用于存储环境变量CONTENT_LENGTH,cmd[10]用于存储用户真正输入的数据,长度15够用了。cmds[15]用于存储system函数调用的程序path及参数。比如欲查询find命令相关用法,按下确定后,浏览器将使用post方法发送一串字符串到服务器,该字符串经过url编码,编码后的字符串为“cmd=find”。在这个案例中,数组poststr的作用就是存储这个字符串,数组cmd的作用是存储"find",数组cmds的作用是存储“man find > in.txt”,至于怎么通过poststr来生成cmd、cmds,则需要用到相应的函数。

  if(getenv("CONTENT_LENGTH")用于判断传递的字符串是否为空。

  语句 fgets(poststr,n+1,stdin) 作用是从标准输入中读取n个字符串并存储到数组poststr[]。参考百度百科:“从文件结构体指针stream中读取数据,每次读取一行。读取的数据保存在buf指向的字符数组中,每次最多读取bufsize-1个字符(第bufsize个字符赋'\0')”,函数原型:char *fgets(char *buf, int bufsize, FILE *stream)。

  语句 sscanf(poststr,"cmd=%s",cmd) 作用是生成cmd字符串。参考百度百科:“sscanf() - 从一个字符串中读进与指定格式相符的数据”。通俗的理解就是裁剪字符串,提取有效信息。

  语句 sprintf(cmds,"man %s > data.txt",cmd) 作用是将字符串cmd和“man ”拼接,生成字符串cmds。

  c语言中,system()函数用于调用系统命令。比如system("ls")调用ls命令,然而system调用成功返回值是0,因此需要将结果重定向到一个文本文件中再读取此文本文档以显示命令执行结果。system(cmds)相当于system("man xxx")。

  之后的语句用于打开文本文档,不再详细解释。

  2、使用shell脚本

#!/bin/bash
echo "content-type:text/html"
echo
echo "<html>"
echo "<head>"
echo "<meta charset="UTF-8">"
echo "<title>shell-cgi实现man命令</title>"
echo "<style>"
echo "pre {margin:0 auto; width:"50%"; height:"100%"; font-size:12pt;}"
echo "</style>"
echo "</head>"
echo "<body>"
echo "<pre>"
data=$QUERY_STRING
cmd=${data#*cmd=}
if man $cmd >/dev/null;then
man $cmd
else
echo "没有查询到相关信息"
echo "</pre>"
echo "</body>"
echo "</html>"

  data=$QUERY_STRING用于从环境变量中获取数据并赋给data。

  cmd=${data#*cmd=} 作用是从data字符串中截取“cmd=”之后的字符串。

  之所以使用<pre>标签是因为位如果不使用的话生成的html页面不自动换行。 

ps.不需要担心不怀好意的人输入一下诸如 "ls && rm -rf / "之类的数据到cgi,因为数据的传输都是经过了url编码的,空格会变成加号,特殊字符也会改变。shell.cgi没有进行相应的解码,输入多个命令传递给cgi程序的只是一堆无意义的乱码,如果设计成对url完全解码的cgi程序,应该格外注意安全问题。

利用cgi编程实现web版man手册的更多相关文章

  1. shell脚本作为cgi程序--以web版man为例

    man.cgi源码 #! /bin/sh eval `sh proccgi.sh $*` echo "Content-type: text/html" echo echo echo ...

  2. Web 版 PowerDesigner (Canvas) 技术

    什么是 Canvas?    HTML5 的 canvas 元素使用 JavaScript 在网页上绘制图像. 画布是一个矩形区域,您可以控制其每一像素. canvas 拥有多种绘制路径.矩形.圆形. ...

  3. Python的Web编程[1] -> Web服务器[0] -> Web 服务器与 CGI / WSGI

    Web服务器 / Web Server 对于Web来说,需要建立一个Web服务器,必须建立一个基本的服务器和一个处理程序, 基本服务器的主要作用是,在客户端和服务器端完成必要的HTTP交互, 处理程序 ...

  4. Kali Linux Web渗透测试手册(第二版) - 1.3 - 靶机的安装

    Kali Linux Web渗透测试手册(第二版) - 1.3 - 靶机的安装  一.配置KALI Linux和渗透测试环境 在这一章,我们将覆盖以下内容: 在Windows和Linux上安装Virt ...

  5. JAVA面向对象编程课程设计——web版斗地主

    一.团队课程设计博客链接 JAVA面向对象编程课程设计--网络版单机斗地主 二.个人负责模块或任务说明 实体类的设计 斗地主规则的实现 人机自动出牌的算法 实现数据库的DAO模式 三.自己的代码提交记 ...

  6. CGI编程完全手册

    一.基本原理 CGI:通用网关接口(Common Gateway Interface)是一个Web服务器主机提供信息服务的标准接口.通过CGI接口,Web服务器就能够获取客户端提交的信息,转交给服务器 ...

  7. 物联网网络编程、Web编程综述

    本文是基于嵌入式物联网研发工程师的视觉对网络编程和web编程进行阐述.对于专注J2EE后端服务开发的童鞋们来说,这篇文章可能稍显简单.但是网络编程和web编程对于绝大部分嵌入式物联网工程师来说是一块真 ...

  8. Python学习笔记-CGI编程(如何在IIS上挂Python开发的Webservice)

    一.如何用Python开发一个简单的Webservice 利用python的cgi编程,可以传入参数将结果输出. 定义需要编码以及需要引用的模块 #conding=utf-8 #修正中文乱码 impo ...

  9. (笔记)Linux下的简单CGI编程

    为什么要进行CGI编程?  在HTML中,当客户填写了表单,并按下了发送(submit)按钮后,表单的内容被发送到了服务器端,一般的,这时就需要有一个服务器端脚本来对表单的内容进行一些处理,或者是把它 ...

随机推荐

  1. 合理利用配置不同的机器资源做redis cluster的server

    Redis cluster可以使用不同配置的机器学习因为我们可以手动调整不同的机器所承担的slot的个数,这样内存小CPU相对少的机器应该承担更少的slots

  2. xshell 禁用铃声 提示音

    xshell 的铃声在操作时比较烦,所以通常会关闭. 操作方法: 工具 > 选项 > 高级, 在“终端”选项下的 “禁用铃声” 前面打上勾, 确定即可.

  3. python call so

    作为一个老程序员,如果,python不能与c发生点儿关系,我都挺过意不去的啊 那么,就解决了这个强迫症吧,阿门! //pycall.c #include <stdio.h> #includ ...

  4. 解读经典面试题for循环console.log

    for (var i = 1; i <= 5; i++) { setTimeout(function () { console.log(i) },1000)} 会打印出5个6,这是why 因为 ...

  5. c# 在mongo中查询经纬度范围

    #region 索引 //IndexKeysDocument doc = new IndexKeysDocument();//新建索引 //2d 平面坐标索引,适用于基于平面的坐标计算.也支持球面距离 ...

  6. leetCodelinked-list-cycle-ii找到链表的环

    题目 Given a linked list, return the node where the cycle begins. If there is no cycle, return null. N ...

  7. ps 证件照(1,2寸)

    制作证件照      9*9打印 1,1寸  图片裁剪 2, 2寸 图片裁剪 3,将裁剪完成后的图片选择添加画布  Alt Ctrl  c 将高和宽各加20px  ,背景选择白色 4,将得到的带有白色 ...

  8. UIView常见方法

    - (void)addSubview:(UIView *)view; 添加一个子控件view   - (void)removeFromSuperview; 从父控件中移除 - (UIView *)vi ...

  9. C#之Action的实际应用例子

    public class DemoAction{ public Action action; public Action<int> action1; public Action<in ...

  10. Django admin模块无法调用css样式文件

    在使用Django Admin开发时,发现admin模块css样式文件丢失,无法调用,使火狐浏览器提示: 此 URL 的资源不是文本: http://127.0.0.1:8000/statics/ad ...