12. // IP address of the client side
echo("REMOTE_ADDR: ".$REMOTE_ADDR. "<br/>n");
// Port at the client side
echo("REMOTE_PORT: ".$REMOTE_PORT. "<br/>n");
// Name of authenticated user
echo("REMOTE_USER: ".$REMOTE_USER. "<br/>n");
// Gateway Interface type
echo("GATEWAY_INTERFACE: ".$GATEWAY_INTERFACE. "<br/>n");
// Protocol used by the server
echo("SERVER_PROTOCOL: ".$SERVER_PROTOCOL. "<br/>n");
// Request Method
echo("REQUEST_METHOD: ".$REQUEST_METHOD. "<br/>n");
// Connection type
echo("HTTP_CONNECTION: ".$HTTP_CONNECTION. "<br/>n");
// Host it connected via (proxy)
echo("HTTP_VIA: ".$HTTP_VIA. "<br/>n");
?>
</p>
</card>
</wml>
Henrik Gemal (gemal@dk.net)也有一个在线的基于 WML 的工具 BrowserSpy,来显示更多关于 HTTP
头的信息、服务器环境和用户的浏览器等等。有关这个工具的详细情况可以浏览 http://wap.gemal.dk/
Werner Forkel 提交了一个 Perl 的脚本,可以显示电话号码(如果有)。可以在以下位置测试:
http://wap.colorline.no/wap-faq/apps/subnotest.wml,同样也收集在:
http://wap.colorline.no/demos.html.
这些程序只适合某个网关。如果要测试其他的网关,可能就显示不出电话号码。因此电话号码不能作
为 ID 号来处理。至少因为不是一个全球的标准。
34. 有没有办法连接到电话号码?
在某些情况下,当在显示了一连串的号码之后,需要中断功能连接到一个电话号码上并拨号。例如:
执行一个 dial:12345678 就非常像 mailt 标签。
越来越多的浏览器都支持这个功能,但还不是所有。Phone.com, Mitsubishi 和 Ericsson 已经在浏
览器中集成了这个基于 Wireless Telephony Interface specifications (WTAI)的功能。 WTAI 将允许
以下的 URL 将关闭连接并且拨号:
<go href="wtai://wp/mc;+4712345678">Make a call to +47-12345678</go>
Nokia 7110 已经有个功能叫做“Use Number”。它可以通过 WML 卡片查找一个类似于电话号码的列
表,然后用户可以选择进行呼叫。注意用户必须分离这些数字以便它能正常工作。
35. 使用 GET 或者 POST 方式能传送多少字符?
使用 GET 或者 POST 方式所能传送的字符数目,不同的设备有不同的限制。 一个 GET 通过 UTL 传送变量,
能传送的数据总量比使用 POST 方式所能传送的数据要小。例如,Nokia 7110 似乎对每个 GET 限制在 512
个字节左右,但是 POST 最大可以达到一个编译后卡片的大小(约 1300 字节)。UP.SDK 4.0 将 GET 请求限
制在 970 左右,最大可以达到一个编译后卡片的大小。
显然,卡片有时候保存了要发送给服务器的参数的内容,既然编译后的卡片大小有限制,那么肯定
第 12 页 共 23 页
13. 要影响到整个所能传输的数据。
在 POST 和 GET 之间没有太多的区别。比如这个没有很好地使用 GET 的例子。
<input type="text" name="var1" format="*N"/>
<p>
<anchor>Send it
<go href="somescript.cgi?variable=$(var1)" method="get"/>
</anchor>
</p>
下面仍然是一个使用 GET 的请求,但是使用了<postfield>来传送参数。这个代码就漂亮多了。既然可
以定义为 GET,同样也很容易转成 POST。
<input type="text" name="var1" format="*N"/>
<p>
<anchor>Send it
<go href="somescript.cgi" method="get">
<postfield name="variable" value="$(var1)"/>
</go>
</anchor>
</p>
直接改为 POST:
<input type="text" name="var1" format="*N"/>
<p>
<anchor>Send it
<go href="somescript.cgi" method="post">
<postfield name="variable" value="$(var1)"/>
</go>
</anchor>
</p>
最好是做测试找到到底能传输多少数据。这里有个测试程序:
http://wap.colorline.no/wap-faq/apps/putsize.php3。
这个程序也可以在下面的 URL 中找到:http://wap.colorline.no/demos.html。
该程序将产生一个卡片包含一个变量,里面包含了一定数量的字符 X。用户可以选择传输是使用 GET
还是 POST。在传输之后,脚本将要显示接收到的字符个数。
脚本生成一个页面来测试使用 GET 或者 POST 方式到底能发送多少个字符:
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<head>
<meta forua="true" http-equiv="Cache-Control" content="max-age=0"/>
<meta forua="true" http-equiv="Cache-Control" content="must-revalidate"/>
第 13 页 共 23 页
14. </head>
<card>
<do type="prev" label="Back">
<go href="putsize.php3"/>
</do>
<p>
<anchor>GET data
<go method="get" href="putsize.php3">
<postfield name="a"
value="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"/>
</go>
</anchor>
</p>
</card>
</wml>
36. 如何同 HTML 站点一样 POST/CGI,返回表单数据到服务器?
如果使用:
<go method="post" href="mycgi.cgi">
并且使用:
<postfield name="fieldname" value="$NameOfInputField"/>
就可以 POST 数据给 CGI 程序了。
37. POST 无法工作是怎么回事?
有很多说 POST 参数将会丢失的流言,特别是在 Nokia 7110。就笔者所知,还没有哪个 Nokia 7110 有
这样的问题。这个问题主要是存在于网关或接收方。
测试显示 Nokia SDK 2.18,当使用内建网关的时候,使用 POST 会出现问题。甚至当 method 设置成
“POST”的时候,服务器那边还是将 POST 请求作为 GET。
当使用 POST 的 URL 时 ,Nokia SDK 将会崩溃。在某些情况下 URL 的最后的字符将被删除。
POST Test 页面将简单的 POST 的两个变量叫做“var1”和“var2”来显示整个变量的内容和 HTTP 头
的内容。如果不能看到正确的变量内容,肯定有问题。检查 HTTP 头中的 application/x-www-form-
urlencoded(注意!需要在变量中输入一些内容)。
这个方法解决了 Nokia SDK 2.18 的问题,可以把它配置到任意的公共网关来测试。笔者推荐使用
wapHQ 网关。
在其他的情况下,POST 确实不工作,问题可能是 HTTP 头在服务器端解释的时候有问题。脚本语言,
例如:ASP、Java 或是 CGI 等等都是通过查看在 HTTP 头中的 application/x-www-form-urlencoded 完全
匹配的字符串。 在某些情况下字符串可能有附加的数据,例如:charset="utf8" 。 既然服务器端不是精确
的匹配,它就不会查看 HTTP 头,因此 POST 就变量丢失了。
注意这不是浏览器的问题,在 HTTP 头加入字符集描述,将造成脚本语言方面的错误。
为了检测有关网关或浏览器的问题,仍使用上面的 POST Test 页面来测试。 同样查看 application/x-
www-form-urlencoded 的输出,检查有没有附加的字符在结尾部分,如果有,那么这就是服务器端的问
题。
解决这个问题的方案很复杂,它随用户使用的脚本描述语言不同而不同,而且需要操作原代码。简单
第 14 页 共 23 页
15. 地说,解决方案就是需要人工读取 HTTP 头,不要使用脚本语言已经写好的读取方式。
这里有一个用 ASP 编写的解决方法。它显示了如何在 POST 中抓取数据。用户需要从二进制数据中发现
需要的变量。
Dim lngToalByteCount
Dim vntRequestData
lngTotalByteCount = Request.TotalBytes
vntRequestData = Request.BinaryRead(lngTotalByteCount)
全部的代码,就应该像下面的代码:
<%@ Language=VBScript %>
<%
Dim Temp, i, sPost, sWMLDeck
'Converts the binary data to a string.
For i = 1 To Request.TotalBytes
Temp = Request.BinaryRead(1)
sPost = sPost & Chr(AscB(Temp))
Next
'Parses out the values of the POSTED variables (in this
'example myvar1 and myvar2).
Dim sVar1, sVar2
sVar1 = getVar("myvar1", sPost)
sVar2 = getVar("myvar2", sPost)
'Writes the WML Deck displaying the POSTED Variables
sWMLDeck = "<?xml version=""1.0""?>" & vbCrLf
sWMLDeck = sWMLDeck & "<!DOCTYPE wml PUBLIC ""-//WAPFORUM//DTD WML 1.1//EN"" "
sWMLDeck = sWMLDeck & """http://www.wapforum.org/DTD/wml_1.1.xml"">" & vbCrLf
sWMLDeck = sWMLDeck & vbCrLf & "<wml>" & vbCrLf & vbTab
sWMLDeck = sWMLDeck & "<card id=""main"" title=""POST TEST"">" & vbCrLf
sWMLDeck = sWMLDeck & vbTab & vbTab & "<p>" & vbCrLf
sWMLDeck = sWMLDeck & vbTab & vbTab & vbTab & "myVar1: " & sVar1 & "<br/>" & vbCrLf
sWMLDeck = sWMLDeck & vbTab & vbTab & vbTab & "myVar2: " & sVar2 & vbCrLf
sWMLDeck = sWMLDeck & vbTab & vbTab & "</p>" & vbCrLf & vbTab
sWMLDeck = sWMLDeck & "</card>" & vbCrLf & ">/wml>"
Response.ContentType = "text/vnd.wap.wml"
Response.Write(sWMLDeck)
'Quick function for picking out the values of the POSTed variables.
'sKey is the variable name, sRaw is the POST string.
Private Function getVar(sKey, sRaw)
Dim sRetVal
If InStr(sRaw, sKey) Then
sRetVal = Mid(sRaw, InStr(sRaw, sKey) + Len(sKey) + 1)
第 15 页 共 23 页
16. If InStr(sRetVal, "&") Then
sRetVal = Mid(sRetVal, 1, InStr(sRetVal, "&") - 1)
End If
End If
getVar = sRetVal
End Function
%>
38. 为什么 META 标签不工作?
浏览器不支持默认的 meta 标签,例如:
<meta http-equiv="refresh" content="1;http://somewhere.com/">
虽然有少量网关支持非常有限的 META 标记。 但是测试显示,如果使用了它们,网关就会出问题。 例如
某网关不支持普通的 HTTP Cache 控制,如果要实现 Cache 控制只好使用特殊的 META 标记。显然从其他网
关来的用户就可能不支持这个 META。注意:不要使用 META tags。肯定有其他的方式来完成你的想法。
最常使用的 META 是:
<meta http-equiv="refresh" content="1;http://somewhere.com/">
这个告诉浏览器重新装入指定的 WML 页面。WML 中已经包含了一个<ontimer>。
39. 为什么服务器接收不到用户发送的参数?
用户输入的参数或者其他参数可以像在 HTML 中一样通过提交方式发送到服务器。在 HTML 中这个是
<FORM>,POST 或者 GET。
首先知道要知道 POST 和 GET 的区别。对于 POST 浏览器将生成一个数据包将变量名和它们的内容捆绑
在一起,并发送到服务器。对于 GET,它其实是一个 URL 请求,变量名和内容都包含在 URL 中。
对于 WAP 环境,要求是非常严格的,必须要根据协议来操作。虽然以下的 URL
"/cgi-bin/somescript?username=john&telephone=123-123-1234&occupation=banana+bender"
可以在 HTML 环境中工作,但是在 WAP 环境中无法工作。 以上的部分编码将使得保护的变量内容被误解。
特殊的空格(在 banana 和 bender )被转成 “+”。 URL 就根本没有空格。
以上的 URL 在 WAP 中无法工作的主要原因是用来分割每个变量和变量内容的 & (与号)没有转义。 正
确的格式应该是:
"/cgi-bin/somescript?
username=john&telephone=123-123-1234&occupation=banana+bender"
在这里 & 被名字实体所替换。为了解释更清楚些,请看下面的代码:
<card id="input" title="Gimme some data">
<p><input type="text" name="username" format="M*m"/></p>
<p><input type="text" name="occupation" format="M*m"/></p>
<p>
<anchor>Send this
第 16 页 共 23 页
19. 下面是它的 PHP 代码。 一个标准的 PHP setcookie() 函数只有在这种脚本语言中才会出现。函数只是
简单地设置 cookie,并且 PHP 变量 $HTTP_COOKIE_VARS 用来读取 cookie。
<?
if(isset($HTTP_COOKIE_VARS["TestCookie"]))
{// Check if TestCookie is set
$cookieset = "set";
// Read the Cookie
$cookieid = $HTTP_COOKIE_VARS["TestCookie"];
// and increase its value
$cookieid++;
}
else {
// cookie was not set
$cookieset = "not set";
// start counter at zero
$cookieid = 0;
}
// apply the Cookie to the HTTP header
setcookie("TestCookie",$cookieid);
// set the content type for WML
header("Content-type: text/vnd.wap.wml");
// disable ALL caching
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
echo("<?xml version="1.0"?>n");
echo("<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">nn");
echo("<!-- This application attempts to test the capabilities of a WAP gateway to support
cookies -->n");
echo("<!-- App by Espen.Lyngaas@colorline.no (c) 2000 -->n");
// Generate random value for reload forcing
$random = mt_rand(100000,999999);
?>
<wml>
<head>
// Even more cache disabling
<meta forua="true" http-equiv="Cache-Control" content="must-revalidate"/>
</head>
<card id="init" title="CookieTest">
<p>
Cookie "TestCookie" was <?echo($cookieset)?>.
Value is currently "<?echo($cookieid)?>"
第 19 页 共 23 页
20. </p>
<p>
<anchor>
Increase value
<go method="get" href="<?echo($PHP_SELF)?>?random=<?echo($random)?>"/>
</anchor>
</p>
<p>Gateway:
<?
if(isset($HTTP_VIA))
{ // Is there something in the HTTP_VIA variable?
echo($HTTP_VIA);
}
else {
if(isset($HTTP_USER_AGENT))
{ // Is there something in the HTTP_USER_AGENT variable?
echo($HTTP_USER_AGENT);
}
else {
// Absolutely no identifier was found
echo("Unknown");
}
}
?>
</p>
</card>
</wml>
47. 如何使用 WAP 设备发送 E-Mail?
在 HTML 中有一个默认的 E-Mail 机制:“ mailt” 。但在 WML 中不好使,因此 E-Mails 必须通过 WML
表单来解决。例如:
<wml>
<card id="edit" title="Email Editor">
<p>From: <input type="text" name="from" format="*M"/></p>
<p>T <input type="text" name="to" format="*M"/></p>
<p>Subject: <input type="text" name="subject" format="*M"/></p>
<p>Message body: <input type="text" name="body" format="*M"/></p>
<p>
<anchor>Send this mail
<go method="post" href="http://some.host/mailhandler"?action=send/">
<postfield name="from" value="$(from)"/>
<postfield name="to" value="$(to)"/>
<postfield name="subject" value="$(subject)"/>
<postfield name="body" value="$(body)"/>
</go>
</anchor>
第 20 页 共 23 页
21. </p>
</card>
</wml>
在代码中的 http://some.host/mailhandler 是一个 CGI 程序,它是服务端的脚本程序,将提交的表
单转换成 E-Mail 格式并发送出去。
如果想使用一个类似于发信的过程,就需要编辑变量名。另外发送的数据是有限的,长信息可能需要
打断。
为了演示它是如何工作的,下面的 PHP 脚本可以用来处理 Mail。它将格式化 WML 页面,告诉用户是
否发出信件。在真实的应用中,应该加入检测,例如:E-Mail 的合法格式。
<?
// Tell the client that this is a WML deck
header("Content-type: text/vnd.wap.wml");
echo("<?xml version="1.0"?>n");
echo("<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">n");
// The name of your mail server
$mailer = "wap.colorline.no";
// Format the from field
$from = $from." (WAP user at ".$mailer.")";
// Add the from field and some character handling to the extra headers
$extraheaders = $from."nContent-Type: text/plain;
charset=iso-8859-1nContent-Transfer-Encoding: 8bit";
// Start sending out the WML deck
echo("<wml>n");
if(mail($to,$subject,$body,$extraheaders))
{// Use PHP's internal mail functionality
// Mail was successfully sent
echo("<card id="sent" title="Mail sent">n");
echo("<p>Mail was sent successfully</p>n");
echo("</card>n");
}
else {
// The mail could not be sent
echo("<card id="notsent" title="Mail failed">n");
echo("<p>Unable to send mail</p>n");
echo("</card>n");
}
echo("</wml>n");
?>
因为安全性的原因,以上的代码没有演示程序。
48. 可以在模拟器上操作本地的页面,却没有办法访问 Internet 上的,有什么问题吗?
第 21 页 共 23 页