董老师前几天给我们布置了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. CentOS6.5安装kafka-2.10-0.8.2(单机)

    1.下载 地址:https://kafka.apache.org/downloads 本文中下载版本:kafka_2.10-0.8.2.2.tgz 2.安装 安装目录:/usr/local [root ...

  2. SEO--网站流量提升

    话术设置,提炼优质的话术 关键词的挖掘 1.头脑风暴 (开晨会,一堆人坐在一起聊.) 2.利用搜索引擎相关搜索(将关键词设置为搜索热词,利用工具:百度指数,查看关键词) 3.工具 4.长尾关键词(词比 ...

  3. 获取 Google USB 驱动程序

    获取 Google USB 驱动程序       另请参阅 安装 USB 驱动程序 使用硬件设备 使用任何 Google Nexus 设备进行 ADB 调试时,只有 Windows 需要 Google ...

  4. vmvare 将主机的文件复制到虚拟机系统中 安装WMware tools

    在虚拟机里的ubuntu这里找到VMware tools包

  5. 一个获取本机ip地址的正则

    ifconfig|grep -oP '(?<=inet addr:)(?=(?!127\.0\.0\.1))\d+(\.\d+){3}'

  6. 删除SQL Server大容量日志的方法(转)

    删除SQL Server大容量日志的方法 亲自实践的方法 1.分享数据库,如果提示被其他连接占用,不能分离,刚勾上drop connections 2.复制下所有文件,一定要备份好,以防自己操作失误 ...

  7. report源码分析——report_handle和report_server和report_catcher

    report_handle主要实现对message的action,severity,file的设置,然后将message传递给server: 主要的function有两个:initial和proces ...

  8. 《大话设计模式》c++实现 之工厂模式

    工厂模式 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 在工厂模式中,我们在创建对象时不会对客户端 ...

  9. sublime text3配置及相关小技巧

    1.下载&安装: 官方地址:http://www.sublimetext.com/,sublime text3又更新了,支持不依赖插件进行侧边栏颜色的更改,同时自带的皮肤颜色也有四种,十分方便 ...

  10. Spark学习之路 (十一)SparkCore的调优之Spark内存模型

    摘抄自:https://www.ibm.com/developerworks/cn/analytics/library/ba-cn-apache-spark-memory-management/ind ...