CGI 程 式 设 计
———————————————————————-
———-
大 纲
一 、 为 什 么 要 使 用 CGI ?
二 、 什 么 是 CGI ?
2-1 CGI 简 介
2-2 CGI 的 输 入 输 出
2-3 CGI 可 用 的 程 式 语 言
三 、 CGI 的 输 入 介 面
3-1 ISINDEX
3-2 FORM
3-2-1 FORM 标 签
3-2-2 INPUT 标 签
3-2-3 SELECT 标 签
3-2-4 TEXTAREA 标 签
四 、 CGI 如 何 运 作 ?
4-1 CGI 运 作 流 程
4-2 CGI 传 递 资 料 的 方 法
4-3 CGI 的 参 数
五 、 CGI 输 出 介 面
5-1 CGI 输 出 格 式
5-2 基 本 程 式 范 例
5-2-1 Perl
5-2-2 C for POST METHOD
5-2-3 C for GET METHOD
附 录 A 、 相关 参 考 资 料
附 录 B 、 范例 原 始 程 式
附 录 C 、 CGI 函 式 库
———————————————————————-
———-
一 、 为 什 么 要 使 用 CGI ?
随 著 全 球 资 讯 网 (World Wide Web, WWW) 的 兴 起 , 网 路 从 平 淡
的文 字 世 界 进 入 了 影 音 声 光 的 新 纪 元 。 同 时 也 引 进 了 新
的阅 读 方 法 , 一 种 有 别 於 传 统 循 序 式 的 阅 读 方 法 ━ Hype
rText 。 让 人 们 能 够 直 接 从 有 兴 趣 的 主 题 切 入 , 并 且 在 其
间 相互 跳 跃 、 链 结 , 以 取 得 所 想 要 的 资 料 。 也 因 此 带 动
了 网路 人 口 的 激 增 以 及 无 限 的 商 机 , 所 以 在 商 业 应 用 上
这 是一 个 值 得 开 发 的 空 间 。
但 是 这 样 的 方 式 却 缺 少 了 一 个 商 业 应 用 上 一 个 重 要 的特
性 , 那 就 是 ━ 互 动 性 。 而 CGI 的 出 现 正 是 为 了 弥 补 其 不
足 ! 有 了 CGI 功 能 的 加 入 可 以 使 得 WWW 的 环 境 不 仅 有 单 向
的 资 讯 浏 览 , 更 可 以 有 双 向 的 互 动 。 若 说 CGI 的 发 展 是
WWW 能 受 广 大 使 用 者 喜 爱 的 最 大 原 因 是 不 为 过 的 。
事 实 上 , CGI 的 应 用 相 当 的 广 泛 , 可 以 藉 著 与 其 它 系统 的
结 合 而 增 强 WWW Server 的 功 能 。 例 如 ∶ 与 资 料 库 管 理系 统
(DBMS) 结 合 , 便 是 一 种 最 常 见 , 而 且 是 最 具 扩 充 性 的方
式 。 因 为 经 由 不 同 的 资 料 库 , 可 以 使 WWW Server 提 供 或者
是 记 录 多 样 化 的 资 讯 。
同 时 , 也 可 利 用 CGI 制 作 登 录 (Login) 系 统 , 将 具 有 机 密性
的 资 料 , 以 密 码 的 方 式 加 以 保 护 。 不 但 省 去 了 系 统 过於
开 放 的 困 扰 , 也 可 以 有 效 的 管 理 使 用 者 。 更 进 一 步 ,可
以 记 录 使 用 者 的 使 用 情 形 , 以 便 加 以 计 费 或 者 是 在 网路
上 进 行 电 子 交 易 。
是 故 如 果 要 将 商 业 应 用 在 WWW 上 , CGI 势 必 是 不 可 或 缺的
一 环 。 以 下 我 们 将 会 以 和 资 料 库 管 理 系 统 结 合 为 核 心,
逐 步 介 绍 何 谓 CGI 、 CGI 如 何 输 入 资 料 、 CGI 如 何 运 作 以及
CGI 怎 么 输 出 资 讯 回 给 使 用 者 , 并 且 在 最 後 附 上 几 个 CG
I 应 用 的 范 例 , 让 您 了 解 并 且 实 作 CGI 。
此 外 , 本 章 的 实 作 以 及 范 例 使 用 的 作 业 系 统 为 MicroSoft
NT , WWW Server 为 EMWAC HTTPS , 资 料 库 管 理 系 统 为 MicroSoft S
QL Server , 程 式 语 言 为 Microsoft C 与 资 料 库 管 理 系 统 的 介
面 为 DB-Library 。 关 於 这 些 部 分 的 详 细 资 料 将 不 在 赘 述 ,
如 果您 对 其 它 的 CGI 系 统 有 兴 趣 或 是 想 要 更 深 入 了 解 本
章 实 作的 非 CGI 部 分 , 请 自 行 参 考 相 关 资 料 。
二 、 什 么 是 CGI ?
2-1 CGI 简 介
CGI 是 Common Gateway Interface 的 简 称 。 其 主 要 的 功 能 是 在 WW
W 环 境 下 , 藉 由 从 客 户 端 传 递 一 些 讯 息 给 WWW Server , 再
由 WWW Server 去 启 动 所 指 定 的 程 式 码 来 完 成 特 定 的 工 作 。
所以 更 明 确 的 说 , CGI 仅 是 在 WWW Server 上 可 执 行 的 程 式 码
,而 她 的 工 作 就 是 控 制 讯 息 要 求 而 且 产 生 并 传 回 所 需 的
文件 。
使 用 CGI , 你 的 Server 可 以 读 取 并 显 示 在 客 户 端 无 法 读取
的 格 式 (像 是 SQL DataBase) 。 而 且 可 以 像 闸 道 (Gateway) 一 样,
在 伺 服 端 和 客 户 端 之 间 , 产 生 客 户 端 所 需 要 的 讯 息 。基
本 上 , 在 此 种 主 从 式 (Client/Server) 的 环 境 之 下 , 其 IPC (
InterProcess Communication) 的 协 定 是 利 用 讯 息 传 递 及 记 忆 体分
享 (环 境 变 数) 的 方 式 来 完 成 。 CGI 有 其 特 定 的 写 法 及 规格
, 必 须 遵 守 其 原 则 , 方 可 达 到 主 从 端 资 讯 交 流 的 目 的。
2-2 CGI 的 输 入 输 出
CGI 可 以 使 用 在 很 多 方 面 , 大 部 份 是 控 制 ISINDEX 和 FORM 的
需 求 , 亦 即 ISINDEX 和 FORM 最 常 被 使 用 作 CGI 的 输 入 介 面 。
但 也 有 利 用 链 结 (LINK) 的 方 式 来 呼 叫 所 要 执 行 的 程 式 ,
通常 是 在 使 用 者 的 资 讯 已 固 定 , 或 是 为 达 成 某 种 单 一 目
的而 使 用 。 而 使 用 链 结 方 式 其 程 式 执 行 所 需 的 参 数 是 以
GET METHOD 的 方 式 含 在 URL 中 传 入 , 亦 即 CGI 程 式 在 发 展 时
必 须使 用 GET METHOD 的 方 式 来 读 取 参 数 。 在 第 四 节 , 我 们
将 会详 细 介 绍 传 递 参 数 的 方 法 。
输 出 的 部 分 则 大 部 分 是 利 用 程 式 来 产 生 虚 拟 文 件 , 也就
是 文 件 并 不 是 储 存 Server 的 储 存 媒 体 中 , 而 是 由 程 式 建
构 出 来 的 , 浏 览 程 式 结 束 之 後 文 件 即 不 再 存 在 。 大 部 分
的 文 件 格 式 是 超 本 文 标 示 语 言 (HTML) 或 是 文 字 档 。 也 有
利用 程 式 链 结 到 另 一 份 文 件 , 或 是 只 记 录 使 用 者 输 入 资
讯而 不 做 输 出 !
下 面 是 常 见 输 入 输 出 的 例 子 ∶
转 换 您 的 系 统 参 考 手 册 变 成 超 本 文 标 示 语 言 (HTML) 的 格
式, 接 著 将 结 果 送 给 客 户 端 。
当 做 WAIS 和 ARCHIE 资 料 库 的 界 面 , 将 结 果 转 成 超 本 文 标 示
语 言 (HTML) 的 格 式 送 给 客 户 端 。
允 许 使 用 者 透 过 HTML FORM 和 附 加 的 CGI 解 码 来 回 给 你 的 Se
rver 。
在 下 面 各 节 , 我 们 将 会 进 一 步 说 明 有 关 这 一 部 分 的 使 用
方 法 , 或 是 简 单 的 范 例 。
2-3 CGI 可 用 的 程 式 语 言
至 於 CGI 要 使 用 何 种 程 式 语 言 来 达 成 ? 从 前 面 的 说 明 可
以知 道 , CGI 仅 是 在 WWW Server 上 可 执 行 的 程 式 码 。 是 故 ,
只要 是 您 的 WWW Server 以 及 WWW Server 所 在 的 作 业 系 统 可 执
行 的程 式 语 言 皆 能 使 用 在 CGI 上 。 以 下 列 出 几 种 较 常 在 C
GI 中使 用 的 语 言 ∶
C/C++
PERL
THE BOURNE SHELL
THE C SHELL
TCL
Visual Basic
AppleScript
这 些 程 式 在 完 成 之 後 要 放 置 於 何 处 ? 事 实 上 , 不 同 的 W
WW Server 有 不 同 的 规 定 。 以 HTTPS 为 例 , 她 只 执 行 副 档 名
为 EXE 的 执 行 档 , 且 程 式 不 能 为 图 形 介 面 (GUI) 的 程 式 。
而 程 式只 要 放 置 在 指 定 文 件 的 树 状 目 录 中 任 一 位 置 即 可
。 但 是值 得 注 意 的 是 , 大 部 分 的 WWW Server 尤 其 是 UNIX 上
的 WWW Server , 都 将 CGI 程 式 放 置 在 一 共 同 的 指 定 目 录 之 下
。 所 以 在 放置 CGI 程 式 时 , 请 先 参 考 您 的 WWW Server 手 册 。
三 、 CGI 的 输 入 介 面
在 一 个 完 整 的 系 统 中 , 输 入 介 面 是 直 接 和 使 用 者 接 触 的
第 一 线 。 所 以 输 入 介 面 , 在 整 个 系 统 中 扮 演 著 举 足 轻 重
的 地 位 , 输 入 介 面 的 好 坏 将 直 接 影 向 系 统 的 成 败 。 好 的
输 入 介 面 可 以 弥 补 系 统 设 计 上 的 某 些 缺 陷 , 但 是 要 如 何
设 计 出 一 个 好 的 输 入 介 面 呢 ? 所 谓 「 工 欲 善 其 事 , 必 先
利 其 器 」 , 要 设 计 出 好 的 输 入 介 面 , 第 一 步 应 了 解 手 边
究 竟 有 哪 些 修 缮 门 面 的 工 具 ! 在 这 一 节 中 , 我 们 将 为 您
介 绍 CGI 的 主 要 输 入 介 面 , 让 您 做 好 成 功 的 第 一 步 。
在 CGI 中 较 常 见 的 输 入 介 面 有 ISINDEX 和 FORM 两 种 , 详 细内
容 分 述 如 下 ∶
3-1 ISINDEX
ISINDEX 是 一 个 特 殊 的 标 签 , 使 用 的 方 法 如 下 ∶
<ISINDEX ACTION=”URL”>
其 中 URL 为 想 要 执 行 的 程 式 之 所 在 位 址 及 档 名 。
如 此 会 使 浏 览 程 式 产 生 一 个 输 入 的 视 窗 , 当 使 用 者 完成
输 入 按 下 ENTER 键 後 , Server 会 执 行 参 数 ACTION 中 指 定 的程
式 。 下 面 是 一 个 简 单 的 范 例 ∶
———————————————————————-
———-
可以搜索该索引。请键入要搜索的关键字:
———————————————————————-
———-
常 见 的 用 法 是 与 WAIS Server 结 合 , 或 是 做 档 案 的 搜 寻 。本
节 的 重 点 将 放 在 FORM 的 实 作 上 , 所 以 我 们 在 这 里 不 对 I
SINDEX 做 详 细 的 介 绍 , 如 有 兴 趣 请 自 行 参 考 相 关 资 料 。
3-2 FORM
FROM 在 CGI 中 是 最 常 被 使 用 的 输 入 介 面 , 虽 然 并 不 十 分 完
美 , 但 却 是 目 前 WWW 中 最 强 大 的 输 入 工 具 。 FORM 是 由 一 组
相 关 连 的 标 签 所 组 成 , 使 用 方 法 就 像 其 它 标 签 一 样 。 在
FORM 中 提 供 了 我 们 多 种 输 入 资 料 的 工 具 , 例 如 文 字 输 入
区 (Text) 、 下 拉 式 表 单 (Select Box) 、 按 钮 (Button) 、 选
择 钮 (Radio Button) 等 等 。
就 目 前 所 定 义 的 标 准 中 , FORM 的 标 签 可 分 为 三 大 类 ∶ <I
NPUT> 、 <SELECT> 以 及 <TEXTAREA> 。 下 面 的 例 子 是 FORM 的 一 个
概 观 ∶
———————————————————————-
———-
INPUT 标 签 ∶
← TYPE: TEXT
← TYPE: PASSWORD
这是确定纽1 ← TYPE: CHECKBOX CHECKED
这是确定纽2 ← TYPE: CHECKBOX
这是选择纽1 ← TYPE: RADIO CHECKED
这是选择纽2 ← TYPE: RADIO
← TYPE: SUBMIT
← TYPE: RESET
← TYPE: IMAGE
SELECT 标 签 ∶
这是选项1这是选项2这是选项3
TEXTAREA 标 签 ∶
这是文字输入区
———————————————————————-
———-
接 下 来 , 我 们 将 依 这 三 大 类 以 及 FORM 的 基 本 标 签 做 介绍
。
3-2-1 FORM 标 签
使 用 格 式 如 下 ∶
<FORM METHOD=”POST/GET” ACTION=”URL”> … </FORM>
FORM 这 个 标 签 是 FORM 的 基 本 标 签 , 所 有 与 FORM 有 关 的 标 签
必 须 要 放 在 <FORM> 与 </FORM> 这 标 签 之 内 。 如 果 没 有 将与 FO
RM 有 关 的 标 签 放 在 <FORM> 与 </FORM> 这 个 标 签 之 内, 则 这 些
标 签 将 不 会 产 生 作 用 。
FORM 的 参 数 解 释 如 下 ∶
· ACTION 是 指 定 当 使 用 者 完 成 输 入 并 将 资 料 传 回 Server 时
, Server 会 将 资 料 送 入 的 位 址 ; 如 果 这 个 参 数 没 有 被 指
定时 , FORM 所 在 超 本 文 标 示 语 言 (HTML) 文 件 的 URL 将 成 为 内
定值 。
· METHOD 是 指 定 使 用 者 输 入 的 资 料 会 以 何 种 方 式 传 回 给
Server 。
· GET — 是 CGI 内 定 的 传 输 方 法 , 使 用 者 输 入 的 资 料 会 以
含 入 URL 的 方 式 传 回 。
· POST — 此 种 方 式 有 别 於 GET 将 使 用 者 输 入 的 资 料 含 入 U
RL 的 方 式 。 在 程 式 端 , 资 料 会 以 STDIN 的 方 式 被 接 收 。
· ENCTYPE — 这 个 参 数 只 有 在 METHOD 被 设 定 为 POST 时 才 会 产
生 作 用 , 其 作 用 是 将 使 用 者 输 入 的 资 料 加 码 传 回 。
3-2-2 INPUT 标 签
使 用 格 式 如 下 ∶
<INPUT TYPE=TypeName NAME=ValName VALUE=Value>
其 参 数 如 下 ∶
· TYPE — 设 定 使 用 输 入 的 方 法 。 输 入 的 方 法 一 共 有 下 列
数 种 ∶
· TEXT — 文 字 输 入 区 。 这 是 内 定 值 。
· PASSWORD — 基 本 上 和 TEXT 是 相 同 的 。 只 是 专 门 提 供 给 文
件 阅 读 者 输 入 密 码 之 用 。 不 管 输 入 什 么 字 , 在 画 面 上 都
只 能 看 到 「 * 」 这 个 符 号 。
· CHECKBOX — 选 择 方 块 , 不 是 ON 就 是 OFF 。
· RADIO — 选 择 圆 扭 。 和 CHECKBOX 不 同 的 是 , 选 择 圆 扭 通 常
成 群 出 现 , 并 且 在 这 群 选 项 中 只 能 选 择 其 中 一 个 。
· SUBMIT — 也 就 是 按 钮 (Button) 。 文 件 阅 读 者 会 在 画 面 上
看 到 一 个 按 钮 。 一 旦 按 下 这 个 按 钮 , 浏 览 程 式 (Browser)就
会 把 这 个 FORM 上 文 件 使 用 者 所 输 入 的 一 切 资 料 传 回 给 WW
W Server 做 处 理 。
· RESET — 它 的 外 观 和 SUBMIT 相 似 , 不 过 一 旦 文 件 阅 读 者
按下 它 , 这 个 FORM 上 面 的 所 有 输 入 工 具 的 值 都 会 被 清 除
,或 者 是 回 到 初 始 值 。
· HIDDEN — 这 个 TYPE 将 不 会 出 现 在 FORM 上 , 而 是 隐 藏 在 FO
RM 之 下 。 其 目 的 是 为 了 将 使 用 者 不 需 要 知 道 而 程 式 流 程
上却 需 要 的 资 讯 记 录 在 FORM 上 , 以 便 追 踪 使 用 者 现 在 的
使用 状 况 。
· IMAGE — 在 FORM 上 会 如 IMAGE 标 签 一 样 显 示 图 形 , 其 功 用
和 SUBMIT 一 样 会 将 使 用 者 所 输 入 的 一 切 资 料 传 回 给 WWW Se
rver 。 而 IMAGE 本 身 会 以 滑 鼠 点 下 的 X 和 Y 座 标 传 回 , 这 个
座 标是 以 图 的 左 上 角 以 原 点 向 右 以 及 向 下 增 加 。
· NAME — 定 义 传 回 的 变 数 名 称 。 除 了 SUBMIT 与 RESET 型 态 不
需 NAME 外 , 其 馀 皆 一 定 要 有 , 因 为 如 此 程 式 才 能 分 辨 不
同 的 资 料 。
· VALUE — 配 合 不 同 的 TYPE 有 不 同 的 意 义 , 对 TEXT 或 PASSWO
RD 输 入 型 别 而 言 , 是 设 定 输 入 区 域 之 内 定 值 。 对 RADIO 或
CHECKBOX 也 是 指 定 选 项 之 内 定 值 ( ON 或 是 OFF ) , 不 过 必
须 连 CHECKED 这 个 参 数 一 起 使 用 才 有 效 。 对 SUBMIT 或 RESET
输 入 型 别 而 言, 其 VALUE 的 值 将 会 变 成 按 钮 上 的 文 字 。
· CHECKED — 前 面 已 提 过 这 个 参 数 只 对 RADIO 或 CHECKBOX 之 输
入 型 别 有 效 , 有 内 定 圈 选 之 意 。
· SIZE — 针 对 TEXT 或 PASSWORD 输 入 型 别 , 可 以 定 义 输 入 区
域的 大 小 , 如 果 没 有 指 定 输 入 区 域 大 小 时 , 则 内 定 的 大
小为 20 个 英 文 字 元 的 长 度 。
· MAXLENGTH — 只 对 TEXT 或 PASSWORD 输 入 型 别 有 效 , 用 来 限 制
文 件 阅 读 者 输 入 字 串 的 最 大 长 度 。 若 没 有 指 定 MAXLENGTH
大小 , 则 内 定 值 为 无 限 大 。
· SRC — 这 个 参 数 只 用 在 IMAGE 中 , 用 来 指 定 所 用 图 形 的
URL 。
请 参 见 底 下 的 范 例 ∶
———————————————————————-
———-
<H3> <P align=center> 快 捷 线 上 邮 购 公司 杂 志 订 购 服 务 </P> </
H3>
<Form>
<P>请 输 入 您 的 会 员 代 号 ∶
<INPUT TYPE=TEXT NAME=”MemberID” SIZE=10> </P>
<P>请 输 入 密 码 以 确 认 身 份 ∶
<INPUT TYPE=PASSWORD NAME=”Password” MAXLENGTH=8> </P>
<P>请 选 择 您 的 付 款 方 式 ∶ </P>
- <INPUT TYPE=RADIO NAME=”Pay” VALUE=”现 金” CHECKED>现 金
- <INPUT TYPE=RADIO NAME=”Pay” VALUE=”VISA Card” >VISA Card
- <INPUT TYPE=RADIO NAME=”Pay” VALUE=”Master Card” >Master Card
<P>请 选 择 您 要 订 阅 的 杂 志 名 称 ∶ </P>
- <INPUT TYPE=CHECKBOX NAME=”Magzine” CHECKED>天下
- <INPUT TYPE=CHECKBOX NAME=”Magzine”>远 见
- <INPUT TYPE=CHECKBOX NAME=”Magzine”>中 国生 产 力
- <INPUT TYPE=CHECKBOX NAME=”Magzine” CHECKED>广告
- <INPUT TYPE=CHECKBOX NAME=”Magzine”>美 丽佳 人
- <INPUT TYPE=CHECKBOX NAME=”Magzine”>哈 泼时 尚
<INPUT TYPE=SUBMIT VALUE=”以上资料正确无误”>
<INPUT TYPE=RESET VALUE=”清除刚才所有输入的资料”>
</Form>
使 用 浏 览 程 式 (Browser)来 看 看 结 果 ∶
快 捷 线 上 邮 购 公 司 杂 志 订 购 服 务
请 输 入 您 的 会 员 代 号 ∶
请 输 入 密 码 以 确 认 身 份 ∶
请 选 择 您 的 付 款 方 式 ∶
现 金
VISA Card
Master Card
请 选 择 您 要 订 阅 的 杂 志 名 称 ∶
天 下
远 见
中 国 生 产 力
广 告
美 丽 佳 人
哈 泼 时 尚
———————————————————————-
———-
3-2-3 SELECT 标 签
使 用 格 式 如 下 ∶
<SELECT NAME=ValName SIZE=ScrollSize>
<OPTION SELECTED>选 项 1
<OPTION>选 项 2
</SELECT>
这 个 标 签 提 供 下 拉 式 表 单 或 者 是 卷 动 式 表 单 , 让 使 用 者
可 以 从 表 单 中 选 择 一 个 或 多 个 项 目 。 表 单 是 以 <SELECT> 开
始 , 表 单 中 每 一 个 选 项 以 <OPTION> 开 头 ,最 後 以 </SELECT>
结 束 这 个 表 单 。 SELECT 标 签 一 定 要 使 用 NAME 参 数 来 定 义 选
项 之 栏 位 名 称 。
其 参 数 如 下 ∶
· SIZE — 当 SIZE=1 时 , 此 表 单 为 「 卷 动 式 表 单 」 , 大 於 1
时 则 是 下 拉 式 表 单 。 若 没 有 指 定 SIZE , 则 内 定 值 为 1 。
· MULTIPLE — 当 指 定 此 参 数 时 , 不 管 有 无 指 定 SIZE 参 数 ,
此 表 单 一 定 是 「 卷 动 式 表 单 」 , 并 且 允 许 文 件 阅 读 者 从
表 单 中 一 次 选 取 一 个 以 上 的 选 项 。
· OPTION 标 签 内 可 以 加 上 参 数 SELECTED , 表 示 此 选 项 为 内
定值 , 已 经 预 先 被 选 择 了 。 在 一 个 MULTIPLE 表 单 中 可 以 有
多个 选 项 被 设 为 内 定 值 。
请 参 考 下 面 的 范 例 ∶
———————————————————————-
———-
<H3><P Align=Center> 本 公 司 产 品 介 绍 </P></H3>
<P>请 选 择 一 个 项 目 以 获 得 进 一 步 说 明 ∶ </P>
<Form>
<SELECT NAME=”Product” SIZE=8>
<OPTION>舒跑运动饮料
<OPTION SELECTED>伯朗蓝山咖啡
<OPTION>开喜乌龙茶
<OPTION>雀巢柠檬茶
<OPTION>波蜜果菜汁
<OPTION>黑松沙士
<OPTION>统一优酪乳
<OPTION>可口可乐
<OPTION>义美果茶小站
</SELECT>
<P><INPUT TYPE=SUBMIT VALUE=”选择完毕”> </P>
</Form>
结 果 如 下 ∶
本 公 司 产 品 介 绍
请 选 择 一 个 项 目 以 获 得 进 一 步 说 明 ∶
舒跑运动饮料 伯朗蓝山咖啡 开喜乌龙茶 雀巢柠檬茶 波蜜果菜汁 黑松沙士 统
一优酪乳 可口可乐 义美果茶小站
———————————————————————-
———-
3-2-4 TEXTAREA 标 签
使 用 格 式 如 下 ∶
<TEXTAREA NAME=ValName ROWS=Number COLS=Number>
这 文 字 输 入 区
</TEXTAREA>
这 个 标 签 的 目 的 在 提 供 一 个 多 行 的 输 入 区 域 。 以 <TEXTAR
EA> 开 始 , 以 </TEXTAREA> 结 束 。 这 个 标 签 也 允 许 设 定 内 定
值, 供 使 用 者 修 改 。 输 入 区 的 大 小 由 ROWS 与 COLS 这 两 个 参
数决 定 。 例 如 ∶ ROWS=20 COLS=5 表 示 一 个 大 小 为 20 乘 5 的 输
入区 。 请 参 看 下 列 范 例 ∶
———————————————————————-
———-
<Form>
<P>请 输 入 您 对 本 公 司 的 建 议 ∶ </P>
<TEXTAREA NAME=”InputData” ROWS=15 COLS=40>我 的建 议 是 ∶</TEXTAREA>
<P>
<INPUT TYPE=SUBMIT VALUE=”我写完了”>
<INPUT TYPE=RESET VALUE=”清除重写”>
</P>
</Form>
结 果 如 下 ∶
请 输 入 您 对 本 公 司 的 建 议 ∶
我 的 建 议 是 ∶
———————————————————————-
———-
当 使 用 者 输 入 的 资 料 送 到 程 式 内 时 , 程 式 会 同 时 接 收 到
NAME 及 VALUE 的 值 。 但 当 所 使 用 的 FORM 中 有 RADIO 或 SELECT 等
多 选 择 的 资 料 输 入 型 态 时 , 程 式 则 会 接 收 到 同 一 个 NAME
的 值 会 对 应 到 多 个 VALUE 的 值 。 程 式 可 以 藉 著 这 样 的 特
性, 分 辨 使 用 者 所 做 的 多 重 选 择 并 加 以 处 理 。 但 是 , SE
LECT 和 RADIO 的 传 回 值 并 不 相 同 。 在 RADIO 中 , 其 值 并 不 是
FORM 上 所 见 到 的 值 , 而 是 在 VALUE 中 所 设 定 的 值 ; 在 SELE
CT 中 ,则 是 以 OPTION 标 签 之 後 的 值 为 传 回 值 。 也 就 是 说 使
用 SELECT , 程 式 所 收 到 的 值 和 使 用 者 看 到 的 一 样 ; 使 用
RADIO 则 可以 设 定 不 同 的 值 , 使 得 使 用 者 可 以 见 到 有 意 义
的 选 项 ,而 程 式 可 以 以 更 简 单 的 参 数 , 来 处 理 使 用 者 选
择 的 资 料。 如 果 , 在 RADIO 中 没 有 设 定 VALUE 的 值 , 则 传 回
的 是 字 串 “on” 。
四 、 CGI 如 何 运 作 ?
4-1 CGI 运 作 流 程
首 先 在 客 户 端 , 客 户 端 按 下 FORM 上 的 SUBMIT 按 钮 或 是 按 下
链 结 (LINK) , 告 知 浏 览 程 式 (Browser)完 成 输 入 後 。 浏 览 程
式 (Browser)将 客 户 端 输 入 的 资 讯 传 回 WWW Server , Server 启 动
指定 的 程 式 并 将 包 装 过 的 参 数 传 入 。 接 著 程 式 依 照 传 入
的参 数 完 成 指 定 的 工 作 。 如 果 此 时 有 需 要 传 回 结 果 的 话
,则 程 式 会 把 结 果 传 回 给 Server , Server 再 传 至 浏 览 程 式
(Browser),完 成 整 个 运 作 的 流 程 。 下 图 是 CGI 运 作 流 程 的
示 意 图 ∶
如 果 现 在 要 让 WWW Server 与 其 它 的 系 统 结 合 , 则 程 式 会扮
演 中 介 的 角 色 , 将 接 收 到 的 参 数 转 换 成 所 要 结 合 系 统能
识 别 的 形 式 , 并 处 理 其 传 回 的 资 讯 , 再 送 回 至 Server 让
使 用 者 看 到 。 下 图 是 结 合 其 它 系 统 之 後 CGI 运 作 流 程 的
示意 图 ∶
接 下 来 这 二 张 图 是 以 MicroSoft SQL Server 为 例 , 结 合 WWW Ser
ver 之 後 CGI 运 作 流 程 的 示 意 图 ∶
4-2 CGI 传 递 资 料 的 方 法
在 CGI 整 个 传 递 资 料 的 过 程 中 , 为 了 要 从 Server 传 递 有 关
输 入 资 料 给 CGI 程 式 ,Server 将 不 同 的 资 料 转 换 为 各 种 环
境变 数 以 供 CGI 程 式 使 用 。 这 些 环 境 变 数 是 在 Server 执 行
CGI 程 式 时 被 设 定 。 我 们 在 下 一 小 节 , 将 会 介 绍 各 环 境
变 数, 在 这 里 我 们 将 重 点 放 在 , CGI 如 何 将 使 用 者 经 FORM
所 输入 的 资 料 会 被 如 何 处 理 再 送 到 CGI 程 式 中 。 这 是 CGI
的 关键 所 在 , 有 了 这 项 资 料 才 能 正 确 的 收 到 并 处 理 使 用
者 输入 的 资 料 。
在 FORM 中 , 每 一 资 料 输 入 栏 中 必 须 设 定 NAME 之 参 数 。当 资
料 被 送 出 时 , NAME 参 数 的 值 会 和 其 相 对 应 的 VALUE 参数 之
值 , 被 转 换 为 “NAME=VALUE” 的 形 式 。 不 同 的 资 料 输 入 栏,
中 间 会 以 “&” 作 分 隔 , 亦 即 会 形 成 “NAME1=VALUE1&NAME2=VALUE2”
的 形 式 。 如 果 各 参 数 值 中 间 有 空 白 的 话 会 以 “+” 代 替 ,
有特 殊 字 元 则 以 “%XX” 代 替 , 其 中 “XX” 为 特 殊 字 元 的 16 进
位 ASCII 码 。 这 些 特 殊 字 元 包 括 了 “&” 、 “=” 、 中 文 以 及 A
SCII 码 为 128 以 上 的 字 元 。
资 料 经 过 这 样 的 包 装 後 , 如 果 METHOD 是 设 定 为 POST 的 话,
资 料 会 以 STDIN 的 方 式 送 入 CGI 程 式 中 ; 如 果 METHOD 是 设定
为 GET 的 话 , 资 料 会 被 送 入 QUERY_STRING 的 环 境 变 数 中 ,以
供 程 式 读 取 。
在 前 面 的 小 节 曾 说 过 , CGI 的 程 式 可 以 用 链 结 的 方 式起 动
, 此 时 资 料 须 以 上 述 的 方 法 包 装 後 , 加 在 程 式 名 称的 後
方 , 最 前 面 要 有 一 “?” 符 号 与 程 式 名 称 分 隔 。 以 下 是一
简 单 的 范 例 ∶
<A HREF=”/CGI-BIN/TEST?NAME1=AA+BB&NAME2=CC%3DDD”>按这里
接 著 , 我 们 分 别 就 不 同 的 传 输 METHOD 做 出 的 小 范 例 , 来
比较 不 同 的 METHOD , 在 读 取 环 境 变 数 时 有 何 不 同 ∶
<FORM METHOD=POST ACTION=”/CGI-BIN/TEST”>
栏位 #1: <INPUT NAME=”NAME1″ VALUE=”AA BB”><BR>
栏位 #2: <INPUT NAME=”NAME2″ VALUE=”CC&DD”><p>
<INPUT TYPE=”SUBMIT” VALUE=”执行”>
<INPUT TYPE=”RESET” VALUE=”取消”>
</FORM>
以 上 是 以 METHOD POST 的 方 式 传 输 资 料 , 所 应 参 考 的 环 境 变
数 如 下 ∶
CONTENT_LENGTH = 25
CONTENT_TYPE = application/x-www-form-urlencoded
REQUEST_METHOD = POST
SCRIPT_NAME = /CGI-BIN/TEST
上 面 环 境 变 数 中 , 较 值 得 注 意 的 是 CONTENT_LENGTH , 这 个 环
境 变 数 代 表 的 是 输 入 资 料 的 长 度 , 以 供 CGI 程 式 参 考 。
其计 算 的 方 式 是 以 包 装 过 後 的 实 际 长 度 为 其 值 , 所 以 上
例的 输 入 资 料 为 “NAME1=AA+BB&NAME2=CC%3DDD” , 长 度 25 个 字 元。
接 下 来 , 我 们 看 看 METHOD GET 的 范 例 ∶
<FORM METHOD=GET ACTION=”/CGI-BIN/TEST”>
栏位 #1: <INPUT NAME=”NAME1″ VALUE=”AA BB”><BR>
栏位 #2: <INPUT NAME=”NAME2″ VALUE=”CC&DD”><p>
<INPUT TYPE=”SUBMIT” VALUE=”执行”>
<INPUT TYPE=”RESET” VALUE=”取消”>
</FORM>
以 上 是 以 METHOD GET 的 方 式 传 输 资 料 , 所 应 参 考 的 环 境 变
数 如 下 ∶
PATH_INFO = /CGI-BIN/TEST
PATH_TRANSLATED = /document_root/CGI-BIN/TEST
QUERY_STRING = NAME1=AA+BB&NAME2=CC%3DDD REQUEST_METHOD = GET
由 上 面 的 例 子 可 以 看 出 , 不 同 资 料 的 传 输 方 式 , 所 参 考
的 环 境 变 数 并 不 一 样 。 所 以 程 式 在 发 展 时 , 要 注 意 与 输
入 介 面 上 设 定 的 传 输 方 式 一 致 , 不 同 的 程 式 不 应 该 混 用
, 以 避 免 产 生 不 必 要 的 错 误 。
4-3 CGI 的 参 数
在 这 一 小 节 所 列 示 的 环 境 变 数 仅 供 参 考 , 并 不 见 得 会 适
用 於 每 一 个 WWW Server 。 所 以 , 您 在 使 用 这 些 环 境 变 数 时
, 请 先 阅 读 过 您 的 WWW Server 手 册 , 以 免 产 生 不 必 要 的 错
误 !
下 列 环 境 变 数 不 是 用 在 特 别 需 求 上 , 而 是 用 在 所 有 的需
求 上 ∶
· GATEWAY_INTERFACE
此 变 数 是 用 来 传 送 CGI 的 修 订 版 给 Server 。
格 式 ∶ CGI/revision
· SERVER_NAME
此 变 数 是 用 来 传 送 Server 的 名 字 , Domain Name Server, 或 IP
Address 。
· SERVER_SOFTWARE
此 变 数 是 用 来 传 送 Server 的 软 体 名 字 和 版 本 。
格 式 ∶ name/version
下 面 的 环 境 变 数 是 给 CGI 程 式 专 用 ∶
· AUTH_TYPE
如 果 Server 提 供 使 用 者 查 核 , 而 且 程 式 是 有 保 护 的 。这 是
一 种 辨 认 使 用 者 身 份 方 法 的 一 种 协 定 。
· CONTENT_LENGTH
这 是 使 用 者 输 入 资 料 的 长 度 。
· CONTENT_TYPE
这 是 使 用 者 输 入 资 料 的 MIME 型 态 。
· PATH_INFO
此 变 数 是 用 来 传 送 来 自 客 户 端 额 外 的 路 径 资 讯 , 换 句话
说 , 程 式 可 以 藉 著 真 实 的 路 径 , 加 上 路 径 尾 巴 的 额 外资
讯 来 被 执 行 。 这 额 外 资 讯 传 给 PATH_INFO 。 如 果 它 的 URL 必
须 先 经 过 CGI 程 式 码 时 , 则 要 由 Server 解 码 。
· PATH_TRANSLATED
此 变 数 是 由 Server 提 供 PATH_INFO 的 翻 译 版 本 。
· QUERY_STRING
此 变 数 是 传 送 使 用 者 输 入 的 资 料 。 在 任 何 的 版 本 下 不会
被 解 码 。 只 要 有 使 用 者 输 入 的 资 料 , 此 变 数 就 会 被 设定
, 不 管 命 令 列 的 解 码 。
· REMOTE_ADDR
产 生 请 求 的 远 方 主 机 的 IP 位 址 。
· REMOTE_HOST
产 生 请 求 的 远 方 主 机 名 字 。 如 果 Server 没 有 此 资 讯 ,则 设
定 REMOTE_ADDR , 并 且 不 设 定 此 一 变 数 。
· REMOTE_IDENT
如 果 Server 提 供 RFC 931 的 认 证 , 则 这 个 变 数 会 从 远 端 的 S
erver 取 得 使 用 者 名 字 。 这 个 变 数 应 只 使 用 在 限 制 使 用 者
登 录 上 。
· REMOTE_USER
如 果 Server 提 供 使 用 者 查 核 , 而 且 程 式 是 有 保 护 的 ,此 变
数 是 用 来 传 送 想 要 通 过 认 证 的 使 用 者 名 字 。
· REQUEST_METHOD
此 变 数 是 用 来 传 送 使 用 那 一 种 方 法 传 输 资 料 , 以 超 本文
传 输 协 定 (HTTP) 而 言 是 “GET” 、 “POST” 以 及 “HEAD” 三 种 方 法。
· SCRIPT_NAME
被 执 行 的 程 式 实 质 路 径 即 代 表 自 己 的 URL 。
· SERVER_PORT
此 变 数 是 用 来 传 送 那 一 个 埠 是 用 来 传 输 要 求 。
· SERVER_PROTOCOL
此 变 数 是 用 来 传 送 PROTCOL 的 名 字 和 版 本 。
格 式 ∶ protocol/revision
除 此 之 外 , 如 果 有 一 行 以 上 的 档 头 (HEADER) 从 客 户 端 接 收
到 , 则 会 被 WWW Server 在 档 头 名 称 前 面 加 上 “HTTP_” 的 开 头
之後 被 当 成 环 境 变 数 。 在 档 头 中 如 果 有 任 何 “-” 字 元 , 将
会被 转 成 “_” 字 元 。 另 外 Server 会 除 去 任 何 已 处 理 的 开 头
,像 是 Authorization 、 content-type 、 content-length 。 如 果 放 入
这些 档 头 会 超 过 系 统 环 境 限 制 , Server 会 选 择 去 删 除 全
部 或一 些 开 头 。
五 、 CGI 的 输 出 介 面
资 料 输 出 是 CGI 流 程 的 最 後 一 部 分 , 由 於 送 出 的 资 料 不
只一 种 型 态 。 为 了 使 WWW Server 能 够 辨 认 不 同 的 资 料 型 态
,於 是 在 送 出 资 料 前 , 必 须 先 送 出 特 定 的 额 外 资 讯 以 做
为辨 的 依 据 。
接 下 来 , 要 介 绍 的 就 是 这 些 额 外 资 讯 的 格 式 , 以 及 在程
式 实 作 上 , 如 何 去 达 成 输 入 和 输 出 的 工 作 !
5-1 CGI 输 出 格 式
当 程 式 完 成 工 作 後 , 如 果 要 输 出 资 讯 回 馈 给 使 用 者 , 则
程 式 必 须 将 结 果 以 资 料 流 的 方 式 传 回 给 Server 。 Server 负
责 把 资 料 流 以 超 本 文 传 输 协 定 (HTTP) 的 形 式 包 装 起 来 ,
并利 用 HTTP1 将 资 料 流 转 换 给 客 户 端 的 浏 览 程 式 (Browser)。
这表 示 , Server 通 常 会 将 需 要 的 超 本 文 传 输 协 定 (HTTP) 档
头 (HEADER) 加 入 CGI 程 式 输 出 的 结 果 中 。
输 出 的 资 料 流 中 包 含 两 大 部 份 。 第 一 是 简 短 档 头 , 用来
告 诉 Server 一 些 和 程 式 执 行 结 果 有 关 的 讯 息 。 第 二 就 是
程 式 执 行 完 的 结 果 , Server 并 不 会 解 译 或 更 改 这 一 部 份
的资 料 , 也 就 是 客 户 端 的 浏 览 程 式 (Browser)会 完 全 接 收 到
这一 部 份 的 资 料 。 这 两 个 部 份 之 间 要 有 一 个 以 上 的 空 白
行作 区 隔 。
程 式 执 行 完 的 结 果 是 依 您 程 式 目 的 不 同 而 有 不 同 , 而档
头 却 有 几 种 固 定 的 形 式 。 当 Server 接 到 无 法 认 定 的 档 头
时 会 原 封 不 动 地 送 给 客 户 端 的 浏 览 程 式 (Browser), 所 以 C
GI 程 式 应 避 免 送 出 不 合 超 本 文 传 输 协 定 (HTTP) 标 准 的 档
头 ,以 免 发 生 错 误 的 动 作 。
档 头 跟 MIME 或 MAIL 的 开 头 相 似 。 它 包 含 数 行 , 每 一 行代 表
一 个 项 目 以 及 其 参 数 , 项 目 及 参 数 以 “:” 作 区 隔 。 以下
是 各 档 头 及 其 介 绍 ∶
Content-type: type/subtype
告 诉 Server 要 输 出 的 资 料 是 属 於 何 种 MIME 型 态 的 资 料 , t
ype/subtype 的 值 必 须 是 MIME 承 认 的 型 态 之 一 。
举 例 来 说 , 如 果 要 输 出 的 是 超 本 文 标 示 语 言 (HTML) 文件 则
type/subtype 应 改 为 text/html 。 如 果 要 输 出 的 是 JPEG 标 准的
图 形 档 , 则 type/subtype 应 改 为 image/jpeg 。 有 关 MIME 的 资料
请 自 行 参 考 相 关 资 料 。 以 下 有 一 简 单 的 范 例 以 供 参 考 ∶
— 开 始 —
Content-type: text/html <== 内 容 的 MIME type
Status: 200 OK <== 超 本 文 传 输 协 定 (HTTP) 状 态
(非 必 要)
<== 档 头 和 内 容 的 分 隔 空 白 行
<HTML> <== 内 容 开 始
<HEAD>
<TITLE>范 例 文 件</TITLE>
</HEAD>
<BODY>
<H1>范 例 文 件</H1>
[… etc.]
</BODY>
<HTML>
— 结 束 —
Status:
说 明 CGI 执 行 的 况 状 , 其 值 必 须 是 超 本 文 传 输 协 定 (HTTP)
所 认 可 的 。 如 果 CGI 程 式 传 回 的 结 果 中 , 并 未 包 含 此 一
档头 的 话 , Server 会 认 定 CGI 已 成 功 的 完 成 了 工 作 , 并 且
Server 会 自 行 产 生 “200 OK” 的 Status 值 。 关 於 超 本 文 传 输 协
定 (HTTP) Status 值 的 设 定 , 请 自 行 参 考 相 关 资 料 。
URI: <value>
在 两 个 角 括 号 中 间 的 值 可 以 是 完 整 的 URL , 或 是 相 对 位
址指 向 某 一 档 案 , 则 这 一 档 案 的 内 容 将 会 取 代 CGI 程 式 输
出的 结 果 。 如 果 值 是 区 域 性 的 档 案 , Server 会 将 档 案 内
容 直接 送 到 客 户 端 。 如 果 是 完 整 的 URL 则 Server 传 回 “401 r
edirect” 的 讯 息 , 让 浏 览 程 式 (Browser)自 行 抓 取 指 定 的 档 案
。
Locantion:
与 URI 同 , 但 其 後 之 值 不 必 在 角 括 号 中 间 。 以 下 是 一 简
短范 以 供 参 考 ∶
— 开 始 —
Location: http://crc.yzit.edu.tw/intro.htm <== 指 定 之 URL
<== 空 白 行
— 结 束 —
如 果 CGI 程 式 所 送 出 的 结 果 不 希 望 经 过 Server 的 包 装 , 而
希 望 直 接 送 到 客 户 端 的 浏 览 程 式 (Browser), 则 程 式 必 须 负
责 送 出 完 整 的 超 本 文 传 输 协 定 (HTTP) 讯 息 封 包 (Message Pac
kaged) 。 当 Server 收 到 CGI 程 式 输 出 的 结 果 时 , 会 先 检 查 是
否 有 “HTTP/1.0” 的 讯 息 。 如 果 有 则 Server 会 认 为 以 下 的 讯
息 已 经包 含 了 完 整 的 超 本 文 传 输 协 定 (HTTP) 回 应 , 并 将 其
直 接 送至 客 户 端 的 浏 览 程 式 (Browser)。 以 下 是 一 简 短 的 范
例 ∶
— 开 始 —
HTTP/1.0 200 OK <== 超 本 文 传 输 协 定 (HTTP) 档 头
开 始
Date: Tuesday, 31-May-94 19:04:30 GMT
Server: WebSite 2.0
MIME-version: 1.0
Content-type: text/html
Last-modified: Sunday, 15-May-94 02:12:32 GMT
Content-length: 4109
<== 档 头 和 内 容 的 分 隔 空 白 行
<HTML> <HEAD>
<TITLE>范 例 文 件</TITLE>
[… etc.]
— 结 束 —
5-2 基 本 程 式 范 例
在 程 式 的 实 作 上 , 第 一 步 是 要 先 读 取 环 境 变 数 REQUEST_ME
THOD 的 值 , 以 分 辨 资 料 传 输 的 方 式 。 接 著 是 依 不 同 传 输
方 式, 接 收 使 用 输 入 资 料 ━ POST METHOD 以 STDIN 的 方 式 读 入
资 料; GET METHOD 则 从 环 境 变 数 QUERY_STRING 中 读 取 客 户 端 输
入 的资 料 。 第 三 步 是 将 这 个 包 装 过 的 资 料 以 反 方 向 拆 解
开 ,分 别 置 入 不 同 的 变 数 中 。 在 处 理 过 这 些 变 数 和 完 成
所 要的 工 作 之 後 , 输 出 资 料 回 馈 给 使 用 者 , 是 程 式 流 程
上 的最 後 一 个 步 骤 。 输 出 的 资 依 上 一 小 节 所 介 绍 的 格 式
以 STDOUT 的 方 式 送 出 後 , 程 式 到 此 之 後 可 以 算 是 大 功 告
成 ! 下 面是 CGI 程 式 流 程 的 简 单 示 意 图 ∶
以 下 是 不 同 程 式 语 言 如 何 接 收 使 用 者 输 入 的 资 料 并 且输
出 的 简 单 范 例 以 及 接 收 资 料 的 FORM ∶
———————————————————————-
———-
输 入 栏 1:
输 入 栏 2:
———————————————————————-
———-
以 上 的 FORM 并 未 指 定 其 METHOD 以 及 ACTION , 乃 因 以 下 的 范例
包 含 两 种 METHOD 之 故 。
执 行 的 结 果 如 下 ∶
———————————————————————-
———-
查 询 结 果
您 输 入 的 查 询 值 如 下 ∶
Input1 = ABCD
Input2 = EFGH
———————————————————————-
———-
5-2-1 Perl
在 这 一 小 节 为 您 示 范 的 是 Perl 的 程 式 。 虽 然 , 在 本 章 的
重 点 是 以 C 语 言 为 主 干 , 但 Perl 的 程 式 由 於 处 理 档 案 时
较 C 语 言 简 洁 且 为 直 译 式 语 言 , 所 以 在 CGI 中 有 极 为 广 泛
的应 用 。 是 故 , 我 们 增 加 了 Perl 的 范 例 , 让 您 可 以 对 如
何用 Perl 来 写 CGI 有 初 步 的 认 识 !
这 个 程 式 主 要 的 目 的 是 接 收 并 且 输 出 资 料 。 接 著 我 们就
开 始 逐 步 介 绍 程 式 中 的 重 点 部 分 。 首 先 我 们 看 的 是 利用
STDOUT 输 出 档 头 , 告 知 Server 何 种 内 容 将 会 送 出 ∶
print “Content-type: text/html/n/n”;
从 上 面 的 程 式 可 看 出 , 程 式 接 著 要 输 出 的 内 容 将 会 是 超
本 文 标 示 语 言 (HTML) 的 文 件 。 事 实 上 , 档 头 的 输 并 不 一
定要 放 在 程 式 的 开 头 处 , 但 一 定 要 在 内 容 输 出 前 , 这 点
请特 别 注 意 。 而 且 , 在 看 看 这 一 行 程 式 的 最 後 有 两 个 “
/n” 符 号 , 为 的 是 要 再 加 上 一 行 空 白 , 以 便 和 接 著 输 出
的 内容 做 区 隔 !
输 出 档 头 之 後 是 辨 认 传 输 的 方 式 以 及 读 入 使 用 者 输 入的
资 料 ∶
if ($ENV{‘REQUEST_METHOD’} eq “POST”) {
read(STDIN, $buffer, $ENV{‘CONTENT_LENGTH’});
} elsif ($ENV{‘REQUEST_METHOD’} eq “GET”) {
$buffer=$ENV{‘QUERY_STRING’};
}
读 者 可 以 由 上 方 的 程 式 中 看 出 , 不 同 的 METHOD 读 取 使 用
者输 入 资 料 的 方 式 并 不 相 同 , 请 勿 混 用 !
完 成 了 资 料 读 取 的 动 作 之 後 , 接 下 来 则 是 重 头 戏 ━ 分解
资 料 。
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(“C”, hex($1))/eg;
$A{$name} = $value;
print ”
- <code>$name = $value</code>/n/n”;
}
事 实 上 , 本 范 例 并 未 将 不 同 的 资 料 置 入 不 同 的 变 数 中 ,
而 是 直 接 输 出 。 如 果 您 想 要 对 资 料 做 进 一 步 的 处 理 , 可
以 将 程 式 加 以 修 改 、 扩 充 。 请 注 意 , 在 输 出 变 数 之 前 已
先 输 出 部 分 的 超 本 文 标 示 语 言 (HTML) 文 件 的 内 容 。
print “<H1>查 询 结 果</H1>”;
print “您 输 入 的 查 询 值 如 下 ∶ <p>/n”;
print ”-
- /n”;
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack(“C”, hex($1))/eg;
$A{$name} = $value;
print ” - <code>$name = $value</code>/n/n”;
}print “
- %c”,10);
for(x=0; x <= m; x++)
printf(” - <code>%s = %s</code>%c”,entries[x].name,
entries[x].val,10);
printf(“
- %c”,10);
for(x=0; x <= m; x++)
printf(” - <code>%s = %s</code>%c”,entries[x].name,
entries[x].val,10);
printf(“
- %c”,10);
for(x=0; x <= m; x++)
printf(” - <code>%s = %s</code>%c”,entries[x].name,
entries[x].val,10);
printf(“
- /n”;
- /n”;
由 上 可 见 , 用 程 式 输 出 超 本 文 标 示 语 言 (HTML) 文 件 和 一
般建 立 超 本 文 标 示 语 言 (HTML) 的 格 式 并 无 差 异 , 不 同 的 只
是建 立 者 是 人 与 程 式 的 分 别 !
以 下 是 完 整 的 程 式 列 表 ∶———————————————————————-
———-#!/usr/local/bin/perl
$| = 1;
print “Content-type: text/html/n/n”;if ($ENV{‘REQUEST_METHOD’} eq “POST”) {
read(STDIN, $buffer, $ENV{‘CONTENT_LENGTH’});
} elsif ($ENV{‘REQUEST_METHOD’} eq “GET”) {
$buffer=$ENV{‘QUERY_STRING’};
}print “<H1>查 询 结 果</H1>”;
print “您 输 入 的 查 询 值 如 下 ∶ <p>/n”;
print ” /n”———————————————————————-
———-上 面 的 程 式 是 一 个 「 麻 雀 虽 小 , 五 脏 俱 全 」 的 程 式 。只
要 将 其 适 当 的 位 置 加 上 所 需 的 程 式 就 可 以 达 到 预 定 的功
能 , 相 信 能 对 您 有 所 助 益 。5-2-2 C for POST METHOD
C 语 言 ━ 本 节 的 主 角 登 场 ! 这 是 一 个 使 用 C 语 言 以 接 收
POST METHOD 为 目 的 的 CGI BACKEND 程 式 。 就 如 同 上 面 的 范 例 ,
虽 然只 是 简 单 的 输 出 使 用 者 输 入 的 资 料 。 但 经 过 改 造 之
後 ,功 能 将 不 可 同 日 而 语 ! 现 在 就 让 我 们 开 始 逐 步 分 解
程 式的 内 容 。
一 开 始 我 们 看 到 的 是 档 头 的 输 出 , 如 同 上 一 个 范 例 。printf(“Content-type: text/html%c%c”,10,10);
同 样 的 , 我 们 也 可 以 见 到 在 这 一 行 程 式 的 尾 端 送 出 了 两
个 ASCII 码 为 10 的 字 元 , 来 产 生 与 输 出 内 容 分 隔 的 空 白 行
。
if(strcmp(getenv(“REQUEST_METHOD”),”POST”)) {
printf(“This script should be referenced with a METHOD of POST./n”
);
exit(1);
}
if(strcmp(getenv(“CONTENT_TYPE”),”application/x-www-form-urlencoded”))
{
printf(“This script can only be used to decode form results. /n”);exit(1);
}
这 段 程 式 是 辨 认 传 输 的 方 式 。 因 为 这 范 例 程 式 只 做 为 单
一 传 输 方 式 使 用 , 是 故 和 上 一 个 范 例 有 些 许 的 差 距 。for(x=0;cl && (!feof(stdin));x++) {
m=x;
entries[x].val = fmakeword(stdin,’&’,&cl);
plustospace(entries[x].val);
unescape_url(entries[x].val);
entries[x].name = makeword(entries[x].val,’=’);
}
接 下 来 的 程 式 就 是 读 入 使 用 者 输 入 的 资 料 , 及 将 使 用 者
输 入 的 资 料 拆 解 开 。 注 意 ! 这 个 范 例 是 将 资 料 分 别 置 入
不 同 的 阵 列 元 素 中 , 与 上 一 个 例 子 并 不 相 同 。
printf(“<H1>查 询 结 果</H1>”);
printf(“您 输 入 的 查 询 值 如 下 ∶ <p>%c”,10);
printf(” %c”,10);
到 了 这 里 就 是 程 式 的 最 後 一 部 分 ━ 输 出 回 的 资 讯 。
以 下 是 完 整 的 程 式 列 表 ∶———————————————————————-
———-#include <stdio.h>
#include <stdlib.h>
#define MAX_ENTRIES 50
#define LF 10
#define CR 13typedef struct {
char *name;
char *val;
} entry;char *makeword(char *line, char stop);
char *fmakeword(FILE *f, char stop, int *len);
char x2c(char *what);
void unescape_url(char *url);
void plustospace(char *str);main(int argc, char *argv[]) {
entry entries[MAX_ENTRIES];
register int x,m=0;
int cl;printf(“Content-type: text/html%c%c”,10,10);
if(strcmp(getenv(“REQUEST_METHOD”),”POST”)) {
printf(“This script should be referenced with a METHOD of POST
./n”);
exit(1);
}
if(strcmp(getenv(“CONTENT_TYPE”),”application/x-www-form-urlencode
d”)) {
printf(“This script can only be used to decode form results. /
n”);
exit(1);
}
cl = atoi(getenv(“CONTENT_LENGTH”));for(x=0;cl && (!feof(stdin));x++) {
m=x;
entries[x].val = fmakeword(stdin,’&’,&cl);
plustospace(entries[x].val);
unescape_url(entries[x].val);
entries[x].name = makeword(entries[x].val,’=’);
}printf(“<H1>查 询 结 果</H1>”);
printf(“您 输 入 的 查 询 值 如 下 ∶ <p>%c”,10);
printf(” %c”,10);}
char *makeword(char *line, char stop) {
int x = 0,y;
char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));for(x=0;((line[x]) && (line[x] != stop));x++)
word[x] = line[x];word[x] = ‘/0’;
if(line[x]) ++x;
y=0;while(line[y++] = line[x++]);
return word;
}char *fmakeword(FILE *f, char stop, int *cl) {
int wsize;
char *word;
int ll;wsize = 102400;
ll=0;
word = (char *) malloc(sizeof(char) * (wsize + 1));while(1) {
word[ll] = (char)fgetc(f);
if(ll==wsize) {
word[ll+1] = ‘/0’;
wsize+=102400;
word = (char *)realloc(word,sizeof(char)*(wsize+1));
}
–(*cl);
if((word[ll] == stop) || (feof(f)) || (!(*cl))) {
if(word[ll] != stop) ll++;
word[ll] = ‘/0’;
return word;
}
++ll;
}
}char x2c(char *what) {
register char digit;digit = (what[0] >= ‘A’ ? ((what[0] & 0xdf) – ‘A’)+10 : (what[0] –
‘0’));
digit *= 16;
digit += (what[1] >= ‘A’ ? ((what[1] & 0xdf) – ‘A’)+10 : (what[1]
– ‘0’));
return(digit);
}void unescape_url(char *url) {
register int x,y;for(x=0,y=0;url[y];++x,++y) {
if((url[x] = url[y]) == ‘%’) {
url[x] = x2c(&url[y+1]);
y+=2;
}
}
url[x] = ‘/0’;
}void plustospace(char *str) {
register int x;for(x=0;str[x];x++) if(str[x] == ‘+’) str[x] = ‘ ‘;
}———————————————————————-
———-5-2-3 C for GET METHOD
本 节 的 最 後 一 个 范 例 是 以 C 语 言 做 一 个 接 收 GET METHOD 资
料的 简 单 范 例 。 基 本 上 , 这 个 范 例 与 上 一 个 范 例 没 有 太
多的 差 异 , 主 要 的 目 的 是 让 您 比 较 在 C 语 言 中 , 这 两 种
传输 方 式 在 程 式 写 法 上 有 何 不 同 。 以 下 只 就 有 差 异 的 部
分作 介 绍 。
if(strcmp(getenv(“REQUEST_METHOD”),”GET”)) {
printf(“This script should be referenced with a METHOD of GET./n”)
;
exit(1);
}cl = getenv(“QUERY_STRING”);
if(cl == NULL) {
printf(“No query information to decode./n”);
exit(1);
}
这 段 程 式 最 大 的 差 异 在 读 取 资 料 是 从 QUERY_STRING 取 得 ,
而非 从 STDIN 取 得 。
for(x=0;cl[0] != ‘/0’;x++) {
m=x;
getword(entries[x].val,cl,’&’);
plustospace(entries[x].val);
unescape_url(entries[x].val);
getword(entries[x].name,entries[x].val,’=’);
}
再 者 , 是 分 解 资 料 时 使 的 函 式 有 所 不 同 。 但 这 并 不 会 影
向 程 式 的 执 行 , 因 为 两 个 范 例 所 附 的 函 式 都 是 独 立 的 。
且 这 些 程 式 都 已 确 认 过 可 执 行 , 只 要 不 更 动 函 式 部 分 程
式 就 可 以 正 常 的 执 行 。
以 下 是 完 整 的 程 式 列 表 ∶———————————————————————-
———-#include <stdio.h>
#include <stdlib.h>typedef struct {
char name[128];
char val[128];
} entry;void getword(char *word, char *line, char stop);
char x2c(char *what);
void unescape_url(char *url);
void plustospace(char *str);main(int argc, char *argv[]) {
entry entries[50];
register int x,m=0;
char *cl;printf(“Content-type: text/html%c%c”,10,10);
if(strcmp(getenv(“REQUEST_METHOD”),”GET”)) {
printf(“This script should be referenced with a METHOD of GET.
/n”);
exit(1);
}cl = getenv(“QUERY_STRING”);
if(cl == NULL) {
printf(“No query information to decode./n”);
exit(1);
}
for(x=0;cl[0] != ‘/0’;x++) {
m=x;
getword(entries[x].val,cl,’&’);
plustospace(entries[x].val);
unescape_url(entries[x].val);
getword(entries[x].name,entries[x].val,’=’);
}printf(“<H1>查 询 结 果</H1>”);
printf(“您 输 入 的 查 询 值 如 下 ∶ <p>%c”,10);
printf(” %c”,10);
}void getword(char *word, char *line, char stop) {
int x = 0,y;for(x=0;((line[x]) && (line[x] != stop));x++)
word[x] = line[x];word[x] = ‘/0’;
if(line[x]) ++x;
y=0;while(line[y++] = line[x++]);
}char x2c(char *what) {
register char digit;digit = (what[0] >= ‘A’ ? ((what[0] & 0xdf) – ‘A’)+10 : (what[0] –
‘0’));
digit *= 16;
digit += (what[1] >= ‘A’ ? ((what[1] & 0xdf) – ‘A’)+10 : (what[1]
– ‘0’));
return(digit);
}void unescape_url(char *url) {
register int x,y;for(x=0,y=0;url[y];++x,++y) {
if((url[x] = url[y]) == ‘%’) {
url[x] = x2c(&url[y+1]);
y+=2;
}
}
url[x] = ‘/0’;
}void plustospace(char *str) {
register int x;for(x=0;str[x];x++) if(str[x] == ‘+’) str[x] = ‘ ‘;
}
-
今天的文章CGI 程 式 设 计分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/64083.html