1.
開發(fā)WAP軟件需要哪些工具?
????
為了開發(fā)WAP應(yīng)用程序,需要一個(gè)WAP網(wǎng)關(guān)(注意:這里的網(wǎng)關(guān)可能是指支持WML的服務(wù)器。可以通過(guò)配置WWW服務(wù)器達(dá)到這個(gè)目的)和WAP工具包。工具包應(yīng)當(dāng)包括模擬器和能讓開發(fā)者瀏覽WML網(wǎng)頁(yè)。WML頁(yè)面的開發(fā)和HTML頁(yè)面的開發(fā)一樣,可以使用Notepad或者其他文本編輯器來(lái)進(jìn)行編輯。
2.
有哪些公司現(xiàn)在提供這樣的開發(fā)環(huán)境?
Nokia
、Ericsson、UpPhone和Motorola都提供免費(fèi)的WAP網(wǎng)關(guān)和工具包。
Nokia
:Nokia Toolkit和Nokia WAP Server。
Ericsson
:Ericsson R320和WapIDE。
UpPhone
:UpPhone SDK。
Motorola
:Motorola ADK。
3.
開發(fā)WAP應(yīng)用一定要有WAP手機(jī)嗎?
????
不是,當(dāng)開發(fā)WAP應(yīng)用的時(shí)候,不一定需要WAP手機(jī)。模擬器可以幫助開發(fā)者解決大部分的問(wèn)題。但是如果是開發(fā)商業(yè)網(wǎng)站,特別是想知道各種移動(dòng)電話在顯示WML頁(yè)面上的差別的時(shí)候,最好是配備一個(gè)。目前各種手機(jī)對(duì)WML標(biāo)記的支持和中文的支持狀況大不相同,因此WAP手機(jī)還是必要的。
4.
開發(fā)者需要一個(gè)WAP網(wǎng)關(guān)嗎?
????
不是很必要。如果只想進(jìn)行簡(jiǎn)單的WAP內(nèi)容服務(wù),可以使用現(xiàn)有的Web服務(wù)器(只需要修改MIME類型)。移動(dòng)電話會(huì)通過(guò)坐落在本地的網(wǎng)關(guān)連接到你的服務(wù)器上。
????
但是在網(wǎng)關(guān)上駐留開發(fā)者的程序有很多好處。既然開發(fā)者的程序是網(wǎng)關(guān)的一個(gè)部分,開發(fā)者就可以知道呼叫號(hào)碼、身份、位置等等。
5.
可以看到WML的源代碼么?
????
如果開發(fā)者使用SDK瀏覽的時(shí)候?qū)⒛軌蚩吹?span lang="EN-US">WML的代碼。如果只有一個(gè)HTML瀏覽器,可以訪問(wèn)“Fetch Page”服務(wù)(http://www.webcab.de)來(lái)取得代碼。這個(gè)可以顯示在Internet上的任何WML頁(yè)面中。
6.
可能在WML中加入applets嗎?
????
不能。
7.
可以使用HTML開發(fā)工具來(lái)開發(fā)WAP應(yīng)用嗎?
????
在大多數(shù)情況下開發(fā)工具是使用基于PC的瀏覽器。HTML、JavaScript和Java對(duì)于WAP開發(fā)來(lái)說(shuō)都沒(méi)有用處。但是,越來(lái)越多的開發(fā)工具在加入對(duì)WML的支持。
????Allair
的Cold Fusion 4.5 和 HomeSite已經(jīng)有WML支持,雖然Allair也許需要清除一些BUG。另外PHP和ASP在Coldfusion/HomeSite也能支持。
????
可以到 Marjolei Katsma的 HomeSite Help site 上得到更多的信息。
8.
可以通過(guò)WML頁(yè)面來(lái)操作數(shù)據(jù)庫(kù)嗎?
????
可以,與創(chuàng)建HTML頁(yè)面相同。任何相關(guān)的服務(wù)器端的技術(shù)都可以用來(lái)生成WML頁(yè)面。
9.
可以使用CGI生成WML頁(yè)面嗎?
????
當(dāng)然。可以用創(chuàng)建HTML同樣的方法來(lái)創(chuàng)建WML。如果想書寫一個(gè)CGI來(lái)創(chuàng)建WML,只要記住在頁(yè)面的開頭正確設(shè)置MIME類型。具體的形式根據(jù)所使用的語(yǔ)言不同而不同。例如在Perl中:
print ("Content-type:application/vnd.wap.wml \n\n\n");
????
注意至少要使用2個(gè)換行。
10.
如何使用Cold Fusion來(lái)生成頁(yè)面?
????
使用Cold Fusion只需要加上:
????<CFCONTENT type="text/vnd.wap.wml">
11.
如何使用PHP來(lái)書寫動(dòng)態(tài)的WML頁(yè)面?
????PHP
(和大多數(shù)其他服務(wù)端腳本語(yǔ)言一樣)可以被用來(lái)書寫動(dòng)態(tài)的WML內(nèi)容。只需要將輸出的標(biāo)記限制在WML微型瀏覽器可接受的范圍內(nèi)。
????
注意PHP有很多內(nèi)建的HTML功能,特別是錯(cuò)誤功能,這些功能WML微型瀏覽器可能無(wú)法識(shí)別。
????PHP
同樣可以在一個(gè)HTML文件中編寫出既適合于HTML,也適合于WML的內(nèi)容。PHP的源代碼對(duì)于客戶端來(lái)說(shuō)是不可見(jiàn)的。因此可以針對(duì)HTML瀏覽器輸出HTML頁(yè)面,針對(duì)WML瀏覽器輸出WML頁(yè)面。
????
可以在開發(fā)PHP編寫的WML頁(yè)面的時(shí)候把以下代碼加在開頭:
<?
// 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\n");
?>
????
基于PC的瀏覽器將忽略這些無(wú)法理解的WML標(biāo)記。但是如果想在WAP設(shè)備或者模擬器上測(cè)試的時(shí)候,只需要將"http://"去掉,頁(yè)面自動(dòng)變成WML頁(yè)面。
12.
使用PHP動(dòng)態(tài)輸出WML
????
這些例子生成一個(gè)非常有用的應(yīng)用叫做:PizzaCalc。它將輸入所有的pizza的帳單和人的數(shù)目,可以算出每個(gè)人的花費(fèi)。
????
應(yīng)用生成一個(gè)動(dòng)態(tài)的頁(yè)面叫做“calc”或者“input”。注意到所有的轉(zhuǎn)義字符例如雙引號(hào)。該頁(yè)顯示了一個(gè)簡(jiǎn)單的變量處理,和如何傳遞參數(shù)到另外的卡片:
????
使用WML瀏覽器就可以測(cè)試應(yīng)用程序:
????????http://wap.colorline.no/wap-faq/apps/pizzacalc.html
。
????
或者輸入:
????????http://wap.colorline.no/demos.html
選擇應(yīng)用。
<?
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\n");
echo("<!--The application PizzaCalc was originally made by The Crusaders
www.crusaders.no on the Commodore Amiga -->\n");
echo("<!-- It was unfortunately not possible to emulate the crap interger handling of the
original program -->\n");
?>
<wml>
<?
if($action == "calc") {
echo("<card id=\"result\" title=\"PizzaCalc\">\n");
echo("<do type=\"prev\" label=\"Back\">\n");
echo("<go href=\"pizzacalc.html#input\"/>\n");
echo("</do>\n");
echo("<p>\n");
echo("The cost per eater will be ".$total / $eaters."<br/>\n");
}
else {
echo("<card id=\"input\" title=\"PizzaCalc\">\n");
echo("<p>\n");
echo("<anchor>Split Pizza bill
<go href=\"pizzacalc.html?total=\$(total)&eaters=\$(eaters)&action=calc\"/>
</anchor>\n");
echo("<br/>\n");
echo("Total cost: <input type=\"text\" name=\"total\" format=\"*N\"/>\n");
echo("Eaters: <input type=\"text\" name=\"eaters\" format=\"*N\"/>\n");
}
?>
</p>
</card>
</wml>
13.
可以使用Java Servlet來(lái)生成WML頁(yè)面嗎?
????
當(dāng)然。可以使用創(chuàng)建HTML同樣的方法來(lái)創(chuàng)建WML。如果想書寫一個(gè)CGI來(lái)創(chuàng)建WML,只要記住在頁(yè)面的開頭正確設(shè)置MIME類型:
????response.setContentType("text/vnd.wap.wml");
14.
可以使用ASP、Perl等生成動(dòng)態(tài)的應(yīng)用嗎?
????
是的。可以使用任何服務(wù)器端的腳本語(yǔ)言來(lái)生成WAP應(yīng)用。
15.
如何使用ASP書寫WML內(nèi)容?
????ASP
(Active Server Pages)可以做到和PHP一樣,也可以用來(lái)書寫動(dòng)態(tài)的WML。如果需要一些好的例子請(qǐng)參考Luca Passani's WAP and ASP articles。或者查看Jean-Luc Praz's (jeanluc@corobori.com)。更多的ASP例子在:http://www.corobori.com/wap/。
16.
在使用ASP動(dòng)態(tài)輸出WML頁(yè)面的時(shí)候,已經(jīng)設(shè)置了Content-type,但是瀏覽器返回的仍然是text/html,有什么問(wèn)題嗎?
????
如果在ASP腳本中有一個(gè)錯(cuò)誤,那么診斷程序會(huì)發(fā)還一個(gè)HTML頁(yè)面,請(qǐng)檢查腳本。
17.
在使用ASP生成WML頁(yè)面的時(shí)候出現(xiàn)了錯(cuò)誤: <MIME type "text/html" is not supported>,會(huì)是什么問(wèn)題?
????
這個(gè)問(wèn)題是Web瀏覽器不知道WML的正確類型,修改ASP的第一行,加入:
????<Response.ContentType = "text/vnd.wap.wml">
????
后就可以工作了。
18.
下面的代碼有什么問(wèn)題嗎?
<%Response.ContentType = "text/vnd.WAP.WML"%>
<?xml version="1.0"?>
????
去掉<?xml version="1.0"?>之前的空格。XML解釋器希望在這行中沒(méi)有其他字符,甚至是空行。
19. ASP
代碼可以在模擬器上工作,在真正的瀏覽器上怎么不行?
????
在很多模擬器上沒(méi)有像真正的WML瀏覽器那么嚴(yán)格。這些對(duì)于那些沒(méi)有使用網(wǎng)關(guān)的模擬器(Nokia SDK/Toolkit)來(lái)說(shuō)更是這樣,有些就根本沒(méi)有使用網(wǎng)關(guān)(WinWAP、WapMAN)。
????
一個(gè)真正的WML瀏覽器應(yīng)該只讀取二進(jìn)制的數(shù)據(jù)(從WML編碼得來(lái)的)WMLC,對(duì)于網(wǎng)關(guān)應(yīng)該將文本WML轉(zhuǎn)換/編譯成WMLC。語(yǔ)法是非常嚴(yán)格的。ASP是為HTML瀏覽器設(shè)置的,但是HTML沒(méi)有WML那么嚴(yán)格。
????
這里在ASP生成動(dòng)態(tài)頁(yè)面的時(shí)候有一個(gè)微小的“bug”。它在WML瀏覽器上不允許有任何地方輸出白行(例如:空格,回車,換行)。注意到有些網(wǎng)關(guān)可能會(huì)修正這些問(wèn)題,但有的則不管(例如:CMG網(wǎng)關(guān))。
????
下面是一個(gè)常見(jiàn)的ASP代碼用來(lái)輸出WML頁(yè)面開頭的MIME類型:
<%Response.ContentType = "text/vnd.wap.wml"%>
<?xml version="1.0"?>
????
問(wèn)題就在ASP將會(huì)在 .wml"%> 和 <?xml vers 之間輸出換行和回車。這兩行就被分割了。這將打亂WML代碼的內(nèi)容。WML必須以“<”開頭,而且第一行是<?xml version="1.0"?>。就上面的WML頁(yè)面回車/換行將會(huì)出現(xiàn)問(wèn)題。
????
最簡(jiǎn)單的解決辦法是:
????<%Response.ContentType = "text/vnd.wap.wml"%><?xml version="1.0"?>
????
在XML定義正確的格式化以后,后面的部分WML對(duì)空格就沒(méi)有那么嚴(yán)格的要求。
????
要注意的是有些網(wǎng)關(guān)在輸出ASP的時(shí)候會(huì)有問(wèn)題,因此在WML代碼中最好使用 Response.Write 而不是<%=MyVar%>。
20.
如何使用Perl來(lái)生成WML內(nèi)容?
????
和其他Server端程序一樣。Perl也可以用來(lái)書寫漂亮的WAP應(yīng)用程序。
????
最常見(jiàn)的就是如何使用Perl輸出正確的MIME類型,下面的例子說(shuō)明了這一點(diǎn):
print "Content-type: text/vnd.wap.wml\n\n";
print "<?xml version=\"1.0\"?>\n";
print "<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\"
\"http://www.wapforum.org/DTD/wml_1.1.xml\">\n";
print "<wml>\n";
……
21.
應(yīng)當(dāng)如何下手書寫WAP應(yīng)用程序?
????
其實(shí)需要的只是Text編輯器。但是使用一個(gè)開發(fā)工具可以節(jié)約很多時(shí)間。
????
在這之前應(yīng)該瀏覽一下WAP的權(quán)威站點(diǎn):www.wapforum.com。
????
在Nokia WAP 開發(fā)論壇中進(jìn)行注冊(cè),并且下載Nokia WAP Developer Toolkit 。Toolkit中的PDF文件可以給出一定的WML和WMLScript指導(dǎo)。Nokia Toolkit需要JRE (Java Runtime Environment) v.1.2.2 或者更高版本。
????
雖然工具可以用來(lái)為WAP設(shè)備設(shè)計(jì)應(yīng)用,但是不是為專門的移動(dòng)電話。在WAP開發(fā)工具上所看到的并不代表用戶在手機(jī)上所看到的。為了確定想看到的事情,最好需要一個(gè)WAP設(shè)備,例如移動(dòng)電話,或者模擬器。
????Nokia WAP SDK 2
有一個(gè)7110的模擬器。模擬器是一個(gè)有效的檢測(cè)方式,能檢測(cè)程序中的bug。 Nokia SDK 同樣還包括一個(gè)小的WAP server讓開發(fā)者可以從本地或者HTTP服務(wù)器上下載WML頁(yè)面。
????
到 Phone.com 開發(fā)站點(diǎn)注冊(cè)后,Phone.com 提供UP.browser。這是最流行的瀏覽器,特別是在美國(guó),Phone.com 提供UP.SDK。 在注冊(cè)之后就可以下載。
????
對(duì)于Ericsson R320 和 R380是最近的事情。應(yīng)該注冊(cè)并查看Ericsson's Developer's Zone 來(lái)得到開發(fā)工具。R380是一個(gè)非常好的模擬器,在 Symbian 不需要注冊(cè)就可以下載。Ericsson 沒(méi)有公開的為R320的模擬器。
????Motorola
有一個(gè)平臺(tái)叫做 Mobile Internet eXchange 或者 MIX 。Mobile Application Development Kit 已經(jīng)開發(fā)出一個(gè)開發(fā)平臺(tái),即為WAP也為Motorola的 VoxML。在注冊(cè)后,可以在下面的網(wǎng)址找到數(shù)據(jù)包。
????http://www.motorola.com/MIMS/MSPG/cgi-bin/spn_madk.cgi.
????WAPmine
是一個(gè)獨(dú)立的應(yīng)用,叫做 WAPPage 是一個(gè)所見(jiàn)即所得的編輯工具。而且有一個(gè)XML樹型控件來(lái)編輯WML標(biāo)簽。
????
如果在開發(fā)公共應(yīng)用程序時(shí),想在很多設(shè)備上測(cè)試你的程序,就像在不同的瀏覽器上測(cè)試HTML頁(yè)面一樣。注意在不同的WML瀏覽器上的差別,可能比在不同的HTML瀏覽器上的差別要大。
22.
如何編寫和測(cè)試WML頁(yè)面?
????
現(xiàn)在有很多SDK。AnywhereYouGo.com有WAP SDK和IDE列表,可以下載一個(gè)來(lái)用。任何文本編輯器都可以書寫一個(gè)簡(jiǎn)單的WML頁(yè)面,當(dāng)然HTML編輯器也可以(特別是那些支持個(gè)人定義標(biāo)簽的),例如:Allaire Homesite (http://www.allaire.com )。可以使用SDK來(lái)做簡(jiǎn)單的測(cè)試,但是對(duì)于大的項(xiàng)目可能要困難些。AnywhereYouGo.com已經(jīng)建立一套基于Web的工具來(lái)幫助WAP測(cè)試。
23.
哪兒可以在找到WML的測(cè)試工具?
????
首先確定WML代碼是正確的,然后再使用WML測(cè)試工具。
????
有一個(gè)非常好的測(cè)試工具在Zygo Communications(http://wap.z-y-g-o.com/tools/),測(cè)試工具是用Perl寫的。里面還有其他的工具可供下載。
24.
如何操作WML頁(yè)面?
????
操作WML頁(yè)面或者卡片,最簡(jiǎn)單的辦法是通過(guò)現(xiàn)有的網(wǎng)關(guān)。大多數(shù)移動(dòng)電話提供者將功能都放在主頁(yè)上,在上面可以通過(guò)WAP設(shè)備操作。網(wǎng)關(guān)的鏈接一般叫做“Go to URL”。當(dāng)選擇以后,WAP設(shè)備將通過(guò)網(wǎng)關(guān)操作指定的普通IP或者URL。在這種情況下,網(wǎng)關(guān)讀取從WAP設(shè)備發(fā)送給網(wǎng)關(guān)的WML內(nèi)容,就像PC瀏覽器讀取內(nèi)容的過(guò)程一樣。
????
有些營(yíng)運(yùn)商選擇不讓他們的用戶操作其他的站點(diǎn)。這個(gè)就像Internet Service Provider只允許用戶操作ISP自己的站點(diǎn)。像這樣的做法是不明智的,這樣會(huì)發(fā)現(xiàn)自己的用戶去其他地方了。
????
如果要堅(jiān)持這種方法,可以通過(guò)ISP撥號(hào)或者使用一個(gè)公共的網(wǎng)關(guān)來(lái)取得其他的WAP資源。
25.
有沒(méi)有一個(gè)友好的方式來(lái)管理WML內(nèi)容?
????
還沒(méi)有。雖然Oracale正在開發(fā)數(shù)據(jù)庫(kù)驅(qū)動(dòng)的文檔服務(wù),被稱為Panama,可以支持WAP分發(fā)。
26.
如何防止用戶代理cache頁(yè)面?
????
如果用戶使用ASP,應(yīng)該加入一行<%Response.expires=-1%> ,這個(gè)將阻止Cache。
27.
怎樣防止從Cache中讀取WML頁(yè)面?
????
當(dāng)WML頁(yè)面下載到WAP設(shè)備后,它將保存在WAP設(shè)備內(nèi)存中一段時(shí)間,直到這個(gè)時(shí)間過(guò)期。在這之后,頁(yè)面將從服務(wù)器下載,而不是從WAP設(shè)備的緩存讀取。這個(gè)過(guò)程被稱做Cache。
????
但是有些時(shí)候不想讓頁(yè)面從緩存中讀取,而是從服務(wù)器端讀取。一個(gè)典型的例子就是當(dāng)服務(wù)器的內(nèi)容不斷在更新的時(shí)候,通過(guò)在HTTP頭中加入一定的cache信息,來(lái)告訴WAP設(shè)備該頁(yè)面將不存儲(chǔ)在緩存中。
????
可以在服務(wù)器端生成HTTP頭,或者使用PHP、ASP、Perl或者其他服務(wù)端開發(fā)語(yǔ)言。這一行不能被包括在頁(yè)面里,既然是HTTP的信息頭,就不是WML元素。
????
對(duì)于靜態(tài)頁(yè)面,或許沒(méi)有使用服務(wù)器端腳本語(yǔ)言,許多瀏覽器支持META標(biāo)簽來(lái)控制瀏覽器的Cache。看本部分的最后的例子。
????
將下面代碼加入到HTTP頭中,頁(yè)面將馬上過(guò)期:
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Last-Modified: DD. month YYYY HH:MM:SS GMT
Cache-Control: no-cache, must-revalidate
Pragma: no-cache
????
第一行告訴微型瀏覽器,頁(yè)面已經(jīng)過(guò)期一段時(shí)間了。第二行告訴瀏覽器頁(yè)面最后一次修改的時(shí)間。DD應(yīng)該換成當(dāng)天的日期,month YY HH MM SS等等類推。第三行和第四行有同樣的效果。告訴瀏覽器頁(yè)面不被Cache(第三行適用于 HTTP 1.1,第四行適用于HTTP 1.0)。
????
下面的是PHP的一個(gè)例子:
<?
// set the correct MIME type
header("Content-type: text/vnd.wap.wml");
// expires in the past
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
// Last modified, right now
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
// Prevent caching, HTTP/1.1
header("Cache-Control: no-cache, must-revalidate");
// Prevent caching, HTTP/1.0
header("Pragma: no-cache");
?>
????
下面是使用WebClasses(VB)的例子。使用"Response.Expires=-1",防止Cache。
Private Sub WebClass_Start()
'Set correct MIME type
Response.ContentType = "text/vnd.wap.wml"
'Make sure no caching
Response.Expires = -1
Response.AddHeader "Pragma", "no-cache"
Response.AddHeader "Cache-Control", "no-cache, must-revalidate"
'Use basicwml(my own) as template
Set NextItem = basicwml
End Sub
????
這里有一個(gè)ASP的例子,同樣使用“Response.Expires=-1”防止Cache。
<%
Response.ContentType = "text/vnd.wap.wml"
Response.Expires = -1
Response.AddHeader "Pragma", "no-cache"
Response.AddHeader "Cache-Control", "no-cache, must-revalidate"
%>
????
最后是使用META的例子:
<?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"/>
</head>
<card id="alway***pire">
<p>This deck will never be stored in the cache</p>
</card>
</wml>
????
下面的頁(yè)面是在經(jīng)過(guò)86400秒(24 hours)后過(guò)期。
<?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=86400"/>
</head>
<card id="expire1day">
<p>This card will live in the cache for a day</p>
</card>
</wml>
????
有些瀏覽器例如:UP.Simulator如果可以通過(guò)“返回”達(dá)到另外一個(gè)卡片,那么它將不會(huì)重新裝載卡片。為了強(qiáng)制這個(gè)更新動(dòng)作,用戶必須在META標(biāo)簽中使用must-revalidate 參數(shù)。
????<meta forua="true" http-equiv="Cache-Control" content="must-revalidate"/>
28.
如何防止變量被保存在Cache中?
????
變量保存在Cache中,這樣變量還可以再利用。例如當(dāng)用戶返回到上一個(gè)輸入卡片,他不需要重新輸入,只需要改變需要改變的地方。但是在某些情況下這會(huì)造成一些問(wèn)題。例如以WAP聊天系統(tǒng),有些變量用了一遍又一遍,但是需要不同的內(nèi)容。有些瀏覽器,例如:Nokia 7110,就會(huì)存在類似的在該清除的時(shí)候無(wú)法清除的問(wèn)題。
????
在WML中,<card>標(biāo)簽有一個(gè)參數(shù)叫做newcontext。
????
當(dāng)newcontext="true" 時(shí)清除所有的變量。但是這樣也清除了所有導(dǎo)航的歷史記錄,這意味著back按鈕不再工作。
????
為了清除變量,可以告訴瀏覽器將變量設(shè)為空:
<setvar name="one_variable" value=""/>
<setvar name="another_variable" value=""/>
????
但是,不是每個(gè)時(shí)候都有效果。在某些情況下必須使用一個(gè)難以想象的方法來(lái)清空變量。就是使用 onenterforward 事件。
<onevent type="onenterforward">
<refresh>
<setvar name="one_variable" value=""/>
<setvar name="another_variable" value=""/>
</refresh>
</onevent>
29.
怎么能夠知道請(qǐng)求是從WML瀏覽器來(lái)的還是HTML瀏覽器來(lái)的?
????
既然要利用已經(jīng)存在的為HTML瀏覽器編寫的代碼,就需要知道請(qǐng)求是從HTML瀏覽器還是從WML瀏覽器過(guò)來(lái)的。同樣地,如果想重新引導(dǎo)的HTML瀏覽器直接到相應(yīng)的HTML文檔上,WML瀏覽器到WML頁(yè)面上,以下的PHP代碼就可以做到這些。
<?
// Because this script sends out HTTP header information,
// the first characters in the file must be the <? PHP tag.
// relative URL to your HTML file
$htmlredirect = "/html/my_htmlpage.html";
// ABSOLUTE URL to your WML file
$wmlredirect = "http://wap.mysite.com/wml/my_wmldeck.wml";
if(strpos(strtoupper($HTTP_ACCEPT),"VND.WAP.WML") > 0)
{// Check whether the browser/gateway says it accepts WML.
$br = "WML";
}
else {
$browser=substr(trim($HTTP_USER_AGENT),0,4);
if($browser=="Noki" || // Nokia phones and emulators
$browser=="Eric" || // Ericsson WAP phones and emulators
$browser=="WapI" || // Ericsson WapIDE 2.0
$browser=="MC21" || // Ericsson MC218
$browser=="AUR " || // Ericsson R320
$browser=="R380" || // Ericsson R380
$browser=="UP.B" || // UP.Browser
$browser=="WinW" || // WinWAP browser
$browser=="UPG1" || // UP.SDK 4.0
$browser=="upsi" || // another kind of UP.Browser ??
$browser=="QWAP" || // unknown QWAPPER browser
$browser=="Jigs" || // unknown JigSaw browser
$browser=="Java" || // unknown Java based browser
$browser=="Alca" || // unknown Alcatel-BE3 browser (UP based?)
$browser=="MITS" || // unknown Mitsubishi browser
$browser=="MOT-" || // unknown browser (UP based?)
$browser=="My S" ||
// unknown Ericsson devkit browser ?
$browser=="WAPJ" || // Virtual WAPJAG www.wapjag.de
$browser=="fetc" || // fetchpage.cgi Perl script from www.wapcab.de
$browser=="ALAV" || // yet another unknown UP based browser ?
$browser=="Wapa") // another unknown browser (Web based "Wapalyzer"?)
{
$br = "WML";
}
else {
$br = "HTML";
}
}
if($br == "WML") {
// Force the browser to load the WML file instead
header("302 Moved Temporarily");
header("Location: ".$wmlredirect);
exit;
}
else {
// Force the browser to load the HTML file instead
header("302 Moved Temporarily");
header("Location: ".$htmlredirect);
exit;
}
?>
????
這個(gè)判斷是在服務(wù)端完成的, PHP代碼將首先查看網(wǎng)關(guān)是否接收text/vnd.wap.vml MIME類型。如果不是,將檢測(cè)前面的字符,查看是否為WML瀏覽器。如果不符合,那么就假設(shè)為HTML瀏覽器。如果有新的WML瀏覽器,那么ID字符串也要增加。
????
這個(gè)代碼基于Robert Whitinger(robert@wapsight.com)的代碼,使用了Don Amaro(donamaro.concepcion@nl.unisys.com)提供的列表。
????
注意:由于只需要四個(gè)字符串就可以辨別,因此例如:"WapIDE-SDK/2.0;(R320s(Arial))" 可以使用“WapI”來(lái)代替是可行的做法,也是足夠的。
????
同樣的功能也可以通過(guò)ASP來(lái)解決。先判斷請(qǐng)求的是“/index.wml” 或者 “/index.html” 和所需要的MIME類型。另外以下的腳本辨別的方式和上面不一樣。另外還需要網(wǎng)關(guān)告訴服務(wù)器它能接收 的text/vnd.wap.wml MIME類型。該例子如下所示:
<%
Response.Buffer = TRUE
Dim IsWap
httpAccept = LCase(Request.ServerVariables("HTTP_ACCEPT"))
if Instr(httpAccept,"wap") then
IsWap=1
Else Response.Redirect "/index.html" : Response.Flush : Response.End
End if
%>
<%Response.ContentType = "text/vnd.wap.wml"%><?xml version="1.0"?>
<%Response.Flush%>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
"http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
<card id="redirect">
<onevent type="onenterforward">
<go href="/index.wml"/>
</onevent>
<p>
<a href="/index.wml">enter</a>
</p>
</card>
</wml>
<%Response.Flush:Response.End%>
30.
如何判斷訪問(wèn)者是來(lái)自哪個(gè)瀏覽器或者移動(dòng)電話?
????
可以通過(guò)檢查HTTP_USER_AGENT標(biāo)簽來(lái)判斷。例如試著使用Microsoft Internet Explorer訪問(wèn)一個(gè)站點(diǎn)的時(shí)候,HTTP_USER_AGENT將返回:Mozilla/4.0 (compatible;MSIE 5.0; Windows 98);在同樣的情況下使用Nokia 7110訪問(wèn)這個(gè)站點(diǎn),HTTP_USER_AGENT就會(huì)是:Nokia7110/1.0(04.73)。據(jù)此可以判斷用戶代理是什么類型的。
31.
可以得到用戶代理的電話號(hào)碼嗎?
????
不可以,除非網(wǎng)關(guān)支持這個(gè)特點(diǎn),WAP沒(méi)有辦法知道用戶的電話號(hào)碼。
32.
可以通過(guò)WML使得可以用WAP設(shè)備進(jìn)行撥號(hào)嗎?
????WAP
的電話功能可以使用Wireless Telephony Application Interface(WTAI)。
????
例如:
????????WMLScript: WTAPublic.MakeCall("9287787");
????
但是第一代的WAP設(shè)備不支持這個(gè)功能。
33.
能夠從WAP設(shè)備中讀取數(shù)據(jù)嗎,例如:電話號(hào)碼?
????
這里有一些通過(guò)HTTP的信息,但是十分有限。既然只有網(wǎng)關(guān)發(fā)送過(guò)來(lái)少量的信息,像WAP設(shè)備的號(hào)碼可能無(wú)法讀取。同時(shí),在某些國(guó)家這還涉及到個(gè)人隱私的問(wèn)題。
????
基本上丟棄的內(nèi)容就是WAP網(wǎng)關(guān)傳送給HTTP服務(wù)器的內(nèi)容。這不同于WAP網(wǎng)關(guān)到網(wǎng)關(guān)。Phone.com的UP.Link網(wǎng)關(guān)是一個(gè)最好的例子。因?yàn)樗?span lang="EN-US">HTTP頭中返回一個(gè)字符串叫做 UP_X_SUBNO,里面包含了電話號(hào)碼。Ericsson網(wǎng)關(guān)將傳送一個(gè)辨別設(shè)備用的字符串,但是在明文中沒(méi)有電話號(hào)碼。
????
每次WAP設(shè)備向HTTP服務(wù)器請(qǐng)求一個(gè)URL,WAP網(wǎng)關(guān)就會(huì)將信息傳送給HTTP服務(wù)器。
????
以下的PHP腳本顯示了從網(wǎng)關(guān)過(guò)來(lái)的所有HTTP頭的信息。可以使用WML瀏覽器進(jìn)行測(cè)試。(http://wap.colorline.no/clientinfo.html)。其他的例子也可以在下面的UTL中找到:
http://wap.colorline.no/demos.html
????第一個(gè)部分是取得所有的標(biāo)準(zhǔn)HTTP頭信息。第二個(gè)部分是提取一個(gè)內(nèi)容。
<?
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\n");
echo("<!—Code written in Microsoft NOTEPAD.EXE à \n");
?>
<wml>
<card id="init" title="Client Info">
<p>
<?
// First part – standard HTTP stuff
$headers = getallheaders();
while (list($header, $value) = each($headers)) {
echo strtoupper($header). ": ". $value. "<br/>\n";
}
// Second part
// 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)也有一個(gè)在線的基于WML的工具BrowserSpy,來(lái)顯示更多關(guān)于HTTP頭的信息、服務(wù)器環(huán)境和用戶的瀏覽器等等。有關(guān)這個(gè)工具的詳細(xì)情況可以瀏覽
http://wap.gemal.dk/
????Werner Forkel 提交了一個(gè)Perl的腳本,可以顯示電話號(hào)碼(如果有)。可以在以下位置測(cè)試:http://wap.colorline.no/wap-faq/apps/subnotest.wml,同樣也收集在:
http://wap.colorline.no/demos.html.
????這些程序只適合某個(gè)網(wǎng)關(guān)。如果要測(cè)試其他的網(wǎng)關(guān),可能就顯示不出電話號(hào)碼。因此電話號(hào)碼不能作為ID號(hào)來(lái)處理。至少因?yàn)椴皇且粋€(gè)全球的標(biāo)準(zhǔn)。
34.
有沒(méi)有辦法連接到電話號(hào)碼?
????
在某些情況下,當(dāng)在顯示了一連串的號(hào)碼之后,需要中斷功能連接到一個(gè)電話號(hào)碼上并撥號(hào)。例如:執(zhí)行一個(gè) dial:12345678 就非常像 mailt 標(biāo)簽。
????
越來(lái)越多的瀏覽器都支持這個(gè)功能,但還不是所有。Phone.com, Mitsubishi 和 Ericsson 已經(jīng)在瀏覽器中集成了這個(gè)基于Wireless Telephony Interface specifications (WTAI)的功能。 WTAI將允許以下的URL將關(guān)閉連接并且撥號(hào):
<go href="wtai://wp/mc;+4712345678">Make a call to +47-12345678</go>
????Nokia 7110
已經(jīng)有個(gè)功能叫做“Use Number”。它可以通過(guò)WML卡片查找一個(gè)類似于電話號(hào)碼的列表,然后用戶可以選擇進(jìn)行呼叫。注意用戶必須分離這些數(shù)字以便它能正常工作。
35.
使用GET或者POST方式能傳送多少字符?
????
使用GET或者POST方式所能傳送的字符數(shù)目,不同的設(shè)備有不同的限制。一個(gè)GET通過(guò)UTL傳送變量,能傳送的數(shù)據(jù)總量比使用POST方式所能傳送的數(shù)據(jù)要小。例如,Nokia 7110似乎對(duì)每個(gè)GET 限制在512個(gè)字節(jié)左右,但是POST最大可以達(dá)到一個(gè)編譯后卡片的大小(約1300字節(jié))。UP.SDK 4.0將GET請(qǐng)求限制在970左右,最大可以達(dá)到一個(gè)編譯后卡片的大小。
????
顯然,卡片有時(shí)候保存了要發(fā)送給服務(wù)器的參數(shù)的內(nèi)容,既然編譯后的卡片大小有限制,那么肯定要影響到整個(gè)所能傳輸?shù)臄?shù)據(jù)。
????
在POST和GET之間沒(méi)有太多的區(qū)別。比如這個(gè)沒(méi)有很好地使用GET的例子。
<input type="text" name="var1" format="*N"/>
<p>
<anchor>Send it
<go href="somescript.cgi?variable=$(var1)" method="get"/>
</anchor>
</p>
????
下面仍然是一個(gè)使用GET的請(qǐng)求,但是使用了<postfield>來(lái)傳送參數(shù)。這個(gè)代碼就漂亮多了。既然可以定義為GET,同樣也很容易轉(zhuǎn)成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>
????
最好是做測(cè)試找到到底能傳輸多少數(shù)據(jù)。這里有個(gè)測(cè)試程序:
http://wap.colorline.no/wap-faq/apps/putsize.php3
。
????
這個(gè)程序也可以在下面的URL中找到:http://wap.colorline.no/demos.html。
????
該程序?qū)a(chǎn)生一個(gè)卡片包含一個(gè)變量,里面包含了一定數(shù)量的字符X。用戶可以選擇傳輸是使用GET還是POST。在傳輸之后,腳本將要顯示接收到的字符個(gè)數(shù)。
????
腳本生成一個(gè)頁(yè)面來(lái)測(cè)試使用GET或者POST方式到底能發(fā)送多少個(gè)字符:
<?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"/>
</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站點(diǎn)一樣POST/CGI,返回表單數(shù)據(jù)到服務(wù)器?
????
如果使用:
????????<go method="post" href="mycgi.cgi">
????
并且使用:
????????<postfield name="fieldname" value="$NameOfInputField"/>
????
就可以POST數(shù)據(jù)給CGI程序了。
37. POST
無(wú)法工作是怎么回事?
????
有很多說(shuō)POST參數(shù)將會(huì)丟失的流言,特別是在Nokia 7110。就筆者所知,還沒(méi)有哪個(gè)Nokia 7110有這樣的問(wèn)題。這個(gè)問(wèn)題主要是存在于網(wǎng)關(guān)或接收方。
????
測(cè)試顯示Nokia SDK 2.18,當(dāng)使用內(nèi)建網(wǎng)關(guān)的時(shí)候,使用POST會(huì)出現(xiàn)問(wèn)題。甚至當(dāng)method 設(shè)置成“POST”的時(shí)候,服務(wù)器那邊還是將POST請(qǐng)求作為 GET。
????
當(dāng)使用POST的URL時(shí) ,Nokia SDK 將會(huì)崩潰。在某些情況下URL的最后的字符將被刪除。
????POST Test
頁(yè)面將簡(jiǎn)單的POST的兩個(gè)變量叫做“var1”和“var2”來(lái)顯示整個(gè)變量的內(nèi)容和HTTP頭的內(nèi)容。如果不能看到正確的變量?jī)?nèi)容,肯定有問(wèn)題。檢查HTTP頭中的application/x-www-form-urlencoded(注意!需要在變量中輸入一些內(nèi)容)。
????
這個(gè)方法解決了Nokia SDK 2.18的問(wèn)題,可以把它配置到任意的公共網(wǎng)關(guān)來(lái)測(cè)試。筆者推薦使用 wapHQ 網(wǎng)關(guān)。
????
在其他的情況下,POST確實(shí)不工作,問(wèn)題可能是HTTP頭在服務(wù)器端解釋的時(shí)候有問(wèn)題。腳本語(yǔ)言,例如:ASP、Java或是CGI等等都是通過(guò)查看在HTTP頭中的 application/x-www-form-urlencoded 完全匹配的字符串。在某些情況下字符串可能有附加的數(shù)據(jù),例如:charset="utf8" 。既然服務(wù)器端不是精確的匹配,它就不會(huì)查看HTTP頭,因此POST就變量丟失了。
????
注意這不是瀏覽器的問(wèn)題,在HTTP頭加入字符集描述,將造成腳本語(yǔ)言方面的錯(cuò)誤。
????
為了檢測(cè)有關(guān)網(wǎng)關(guān)或?yàn)g覽器的問(wèn)題,仍使用上面的POST Test頁(yè)面來(lái)測(cè)試。同樣查看application/x-www-form-urlencoded 的輸出,檢查有沒(méi)有附加的字符在結(jié)尾部分,如果有,那么這就是服務(wù)器端的問(wèn)題。
????
解決這個(gè)問(wèn)題的方案很復(fù)雜,它隨用戶使用的腳本描述語(yǔ)言不同而不同,而且需要操作原代碼。簡(jiǎn)單地說(shuō),解決方案就是需要人工讀取HTTP頭,不要使用腳本語(yǔ)言已經(jīng)寫好的讀取方式。
????
這里有一個(gè)用ASP編寫的解決方法。它顯示了如何在POST中抓取數(shù)據(jù)。用戶需要從二進(jìn)制數(shù)據(jù)中發(fā)現(xiàn)需要的變量。
Dim lngToalByteCount
Dim vntRequestData
lngTotalByteCount = Request.TotalBytes
vntRequestData = Request.BinaryRead(lngTotalByteCount)
????
全部的代碼,就應(yīng)該像下面的代碼:
<%@ 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)
If InStr(sRetVal, "&") Then
sRetVal = Mid(sRetVal, 1, InStr(sRetVal, "&") - 1)
End If
End If
getVar = sRetVal
End Function
%>
38.
為什么META標(biāo)簽不工作?
????
瀏覽器不支持默認(rèn)的meta標(biāo)簽,例如:
????<meta http-equiv="refresh" content="1;http://somewhere.com/">
????
雖然有少量網(wǎng)關(guān)支持非常有限的META標(biāo)記。但是測(cè)試顯示,如果使用了它們,網(wǎng)關(guān)就會(huì)出問(wèn)題。例如某網(wǎng)關(guān)不支持普通的HTTP Cache控制,如果要實(shí)現(xiàn)Cache控制只好使用特殊的META標(biāo)記。顯然從其他網(wǎng)關(guān)來(lái)的用戶就可能不支持這個(gè)META。注意:不要使用META tags。肯定有其他的方式來(lái)完成你的想法。
????
最常使用的META是:
????<meta http-equiv="refresh" content="1;http://somewhere.com/">
????
這個(gè)告訴瀏覽器重新裝入指定的WML頁(yè)面。WML中已經(jīng)包含了一個(gè)<ontimer>。
39.
為什么服務(wù)器接收不到用戶發(fā)送的參數(shù)?
????
用戶輸入的參數(shù)或者其他參數(shù)可以像在HTML中一樣通過(guò)提交方式發(fā)送到服務(wù)器。在HTML中這個(gè)是<FORM>,POST或者GET。
????
首先知道要知道POST和GET的區(qū)別。對(duì)于POST瀏覽器將生成一個(gè)數(shù)據(jù)包將變量名和它們的內(nèi)容捆綁在一起,并發(fā)送到服務(wù)器。對(duì)于GET,它其實(shí)是一個(gè)URL請(qǐng)求,變量名和內(nèi)容都包含在URL中。
????
對(duì)于WAP環(huán)境,要求是非常嚴(yán)格的,必須要根據(jù)協(xié)議來(lái)操作。雖然以下的URL
????"/cgi-bin/somescript?username=john&telephone=123-123-1234&occupation=banana+bender"
????
可以在HTML環(huán)境中工作,但是在WAP環(huán)境中無(wú)法工作。以上的部分編碼將使得保護(hù)的變量?jī)?nèi)容被誤解。特殊的空格(在 banana 和 bender )被轉(zhuǎn)成 “+”。 URL就根本沒(méi)有空格。
????
以上的URL在WAP中無(wú)法工作的主要原因是用來(lái)分割每個(gè)變量和變量?jī)?nèi)容的 & (與號(hào))沒(méi)有轉(zhuǎn)義。正確的格式應(yīng)該是:
????"/cgi-bin/somescript?username=john&telephone=123-123-1234&occupation=banana+bender"
????
在這里 & 被名字實(shí)體所替換。為了解釋更清楚些,請(qǐng)看下面的代碼:
<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
<go href="/cgi-bin/somescript?username=$(username)
&occupation=$(occupation)"/>
</anchor>
</p>
????
注意這不是真正的WAP協(xié)議,專門的字符應(yīng)該轉(zhuǎn)義,否則將得到不可預(yù)料的結(jié)果。
40.
為什么在HTTP中的Referer看不見(jiàn)?
????
當(dāng)HTML瀏覽器從一個(gè)URL到另外一個(gè)URL的時(shí)候,它默認(rèn)地會(huì)發(fā)送一個(gè)叫做 Referer的 HTTP頭給服務(wù)器,告訴它在瀏覽這個(gè)頁(yè)面之前的那個(gè)頁(yè)面。這是一個(gè)非常有用的特點(diǎn),在WAP環(huán)境中同樣也有。但是既然這個(gè)信息來(lái)自用戶代理(瀏覽器)、WAP設(shè)備,通常為了節(jié)約帶寬和時(shí)間,就被省略了。
????
為了使用 Referer ,應(yīng)該使用新的URL標(biāo)簽例如: <a>,<go>等等,并且加入?yún)?shù):sendreferer。
????????<go href="/somedir/somedeck.wml" sendreferer="true"/>
????
這樣就會(huì)把參考的URL發(fā)送到服務(wù)器。
41.
如果沒(méi)有找到URL,有可能重新將用戶引導(dǎo)到另外一個(gè)WML卡片或者頁(yè)面嗎?
????
是的。但這是服務(wù)器端的特點(diǎn),與客戶端沒(méi)有關(guān)系。
42.
為什么普通的HTTP 302重新導(dǎo)向不好使?
????
這的確是一個(gè)事實(shí)。核心的問(wèn)題是在服務(wù)端的腳本語(yǔ)言,而不是在服務(wù)端語(yǔ)言和服務(wù)器之間。
????
所謂的302 Found HTTP反應(yīng)是指服務(wù)器告訴用戶代理,它所需要的資源在另外的地方可以找到。302反應(yīng)可能包括一個(gè)人們可理解的信息,如果在這種情況下“ Content-type: ”就被設(shè)置了。筆者所測(cè)試過(guò)的服務(wù)器,即使沒(méi)有內(nèi)容也都加了“Content-type:”。默認(rèn)的 “Content-type:” 是text/html。當(dāng)然有些網(wǎng)關(guān)不喜歡這個(gè)類型。
????
以下的例子已經(jīng)經(jīng)過(guò)測(cè)試,在Apache和Microsoft Internet Information Server都可以工作。如果使用其他的Web Server,或者其他的腳本語(yǔ)言,需要能轉(zhuǎn)換這些簡(jiǎn)單的腳本。關(guān)鍵的工作是十分簡(jiǎn)單的,除非需要,不用告訴服務(wù)器整個(gè)HTTP頭。大多數(shù)Web Server將自動(dòng)完成這個(gè)HTTP頭,使得用戶代理可以理解。
????
所有的代碼例子可以在線測(cè)試。如果它們能夠工作,用戶將被重新引導(dǎo)到http://wap.colorline.no/clientinfo.html ,在那兒將產(chǎn)生一個(gè)WML頁(yè)面來(lái)顯示所有的HTTP頭。
????PHP
代碼測(cè)試可以在 http://wap.colorline.no/wap-faq/apps/302test.php3中找到。
<?
header("Location: http://wap.colorline.no/clientinfo.html");
header("Content-type: text/vnd.wap.wml";
?>
????Perl
測(cè)試代碼可以在http://wap.colorline.no/cgi-bin/302test.pl中找到。
print "Location: http://wap.colorline.no/clientinfo.html\n";
print "Content-type: text/vnd.wap.wml\n";
????ASP
測(cè)試代碼可以在 http://www.colorline.no/302test.asp中找到。 (注意不同的URL):
<%
Response.Redirect = "http://wap.colorline.no/clientinfo.html";
Response.ContentType = "text/vnd.wap.wml";
Response.Flush
Response.End
%>
43.
可能在WML中實(shí)現(xiàn)ASP Session嗎?
????
不可能。可以把信息存儲(chǔ)在臨時(shí)變量中模擬Session。Session是保存在用戶PC上的“cookies”中。目前的WAP設(shè)備不支持“cookies”。不過(guò)下一代的設(shè)備和WML可能支持“cookies”。
44. WAP
支持Session嗎?
????
在HTML中,一個(gè)十分普遍的“處理”用戶的方法就是為每個(gè)用戶分配一個(gè)“session”。這個(gè)有時(shí)候是通過(guò)指定一個(gè)獨(dú)一無(wú)二的cookies來(lái)實(shí)現(xiàn)的。然而WAP的資源非常有限,因此session的處理必須以不同的方式來(lái)處理。
????Alex Kriegel
提供了一個(gè)安裝在 WAPlinks的Custom Session Object包。這個(gè)zip文件中包含了VB類的文件和編譯過(guò)的Dll文件,還有相關(guān)的文檔。這些可以在http://www.waplinks.com/customsessionobject.zip下載。
????
另外一種方法是使用 PHPlib ,它是使用 PHP 編寫的。
????Tarique (tarique@nagpur.dot.net.in)
提供了如何使用PHPlib來(lái)驗(yàn)證和處理每個(gè)WAP用戶。有相關(guān)的文件和注釋可以到下面地址下載:
????http://wap.colorline.no/wap-faq/archive/phplib_wml.zip
45.
可以在WAP中使用Cookies嗎?
????
在理論上是可以的,但不是所有的WAP設(shè)備都支持。另一個(gè)方法來(lái)管理會(huì)話是使用隱藏的fields(包含會(huì)話標(biāo)識(shí),無(wú)論是POST或者GET方式)。
46. WAP
支持Cookies嗎?
????
普通的HTTP Cookies是作為WAP的擴(kuò)展來(lái)實(shí)現(xiàn)的。無(wú)論你以前聽(tīng)到什么,Cookies的支持將越來(lái)越好。實(shí)際上Phone.com的 UP.Link網(wǎng)關(guān)已經(jīng)支持這個(gè)功能有一段時(shí)間了。
????
可以使用以下的腳本語(yǔ)言檢測(cè)Cookie-support,:
????????http://wap.colorline.no/wap-faq/apps/cookietest.php3
????
腳本在http://wap.colorline.no/demos.html也可以得到。
????
當(dāng)?shù)谝淮慰匆?jiàn)卡片的時(shí)候,記數(shù)器應(yīng)該為0。所有的Cache都被關(guān)閉。卡片通過(guò)在URL中隨機(jī)地加入變量來(lái)強(qiáng)制自己加載(筆者不推薦這種強(qiáng)制加載辦法)。當(dāng)點(diǎn)擊增加計(jì)數(shù)連接,頁(yè)面將重新加載,卡片就再次出現(xiàn),并且記數(shù)器變成1。
????
在腳本中,Cookie的名字被稱做 TestCookie,它有很長(zhǎng)的生命期,因此可以隔好幾天再來(lái)查看記數(shù)器,它將是上一次的數(shù)值。這要求你能使用與上一次訪問(wèn)所使用的WAP環(huán)境一樣,否則將把你的數(shù)值清0。
????
如果記數(shù)裝置一直都是0,那么cookie 就沒(méi)有能傳送到你的Web Server。這個(gè)腳本也能表示Cookie是否被傳送。
????
另外,這個(gè)腳本同樣還顯示HTTP頭中的HTTP_VIA 和 HTTP_USER_AGENT 。這些能夠得到所使用的網(wǎng)關(guān)和模式。一些網(wǎng)關(guān)使用HTTP_VIS標(biāo)識(shí)自己,而另外一些使用HTTP_USER_AGENT,還有一些則讓程序無(wú)法知道。
????
下面是它的PHP代碼。一個(gè)標(biāo)準(zhǔn)的 PHP setcookie() 函數(shù)只有在這種腳本語(yǔ)言中才會(huì)出現(xiàn)。函數(shù)只是簡(jiǎn)單地設(shè)置cookie,并且PHP變量 $HTTP_COOKIE_VARS 用來(lái)讀取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\">\n\n");
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)?>"
</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設(shè)備發(fā)送E-Mail?
????
在HTML中有一個(gè)默認(rèn)的E-Mail機(jī)制:“ mailt” 。但在WML中不好使,因此E-Mails必須通過(guò)WML表單來(lái)解決。例如:
<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" >
<postfield name="from" value="$(from)"/>
<postfield name="to" value="$(to)"/>
<postfield name="subject" value="$(subject)"/>
<postfield name="body" value="$(body)"/>
</go>
</anchor>
</p>
</card>
</wml>
????
在代碼中的http://some.host/mailhandler是一個(gè)CGI程序,它是服務(wù)端的腳本程序,將提交的表單轉(zhuǎn)換成E-Mail格式并發(fā)送出去。
????
如果想使用一個(gè)類似于發(fā)信的過(guò)程,就需要編輯變量名。另外發(fā)送的數(shù)據(jù)是有限的,長(zhǎng)信息可能需要打斷。
????
為了演示它是如何工作的,下面的 PHP 腳本可以用來(lái)處理Mail。它將格式化WML頁(yè)面,告訴用戶是否發(fā)出信件。在真實(shí)的應(yīng)用中,應(yīng)該加入檢測(cè),例如: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-1\nContent-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");
?>
????
因?yàn)榘踩缘脑颍陨系拇a沒(méi)有演示程序。
48.
可以在模擬器上操作本地的頁(yè)面,卻沒(méi)有辦法訪問(wèn)Internet上的,有什么問(wèn)題嗎?
????
大多數(shù)模擬器和工具都可以瀏覽Internet、Intranet和本機(jī)的頁(yè)面。但是在訪問(wèn)一些大公司頁(yè)面的時(shí)候,必須通過(guò)代理服務(wù)器來(lái)取得進(jìn)入Internet的權(quán)限。如果必須通過(guò)這個(gè)代理服務(wù)器來(lái)取得HTML頁(yè)面,那么你的WAP模擬器也會(huì)取得權(quán)限來(lái)訪問(wèn)Internet。
????
注意到有些模擬器不支持代理服務(wù)器,但是大多數(shù)是支持的。在模擬器里面設(shè)置這些是很簡(jiǎn)單的。用戶所做的只需要將代理主機(jī)的名字、IP地址和端口號(hào)輸入就可以了。如果沒(méi)有找到,你可以在 systems/network 管理器里面設(shè)置這些,也可以檢查 Netscape/IE的設(shè)置。
????
在某些情況下,代理服務(wù)器使用 userid 和 password 來(lái)取得進(jìn)入Internet的權(quán)限。有些模擬器支持用戶代理服務(wù)器,用戶應(yīng)該能告訴模擬器相關(guān)的代理配置。
????
在極少的情況下,使用代理服務(wù)器(如Microsoft Proxy Server,)的用戶會(huì)遇到更多的問(wèn)題。這個(gè)代理服務(wù)器只接受一種驗(yàn)證方式(userid/password)。這種驗(yàn)證被稱做 NTLM ,并且是某種 MS 的驗(yàn)證方式。幾乎很少有模擬器支持這種方式。因此最好是避免使用它,或者讓管理員使用“Basic Authentication”方式以避免更多的麻煩。
49.
什么是PUSHing,它是如何工作的?
????PUSH
被加入到WAP 1.2,而且只在WAP 1.2中才存在。簡(jiǎn)單地來(lái)說(shuō),PUSH提供了另外一種從服務(wù)器向用戶發(fā)送數(shù)據(jù)的方式。PULLing是從客戶端請(qǐng)求信息,然后接收它;PUSH意味著服務(wù)器可以向用戶發(fā)送數(shù)據(jù),而不需要用戶來(lái)請(qǐng)求。
????
內(nèi)容或者應(yīng)用服務(wù)器無(wú)法向用戶代理直接發(fā)送數(shù)據(jù),必須使用一種叫做Push Proxy 的網(wǎng)關(guān)。PPG 是基于Internet的Push Initiator (內(nèi)容或者應(yīng)用服務(wù)器) 與移動(dòng)用戶之間的。在Internet一邊,使用Push Access Protocol,在移動(dòng)網(wǎng)絡(luò)一邊使用Push Over-the-Air Protocol。
????
當(dāng)前只有 WAP 1.2 開發(fā)平臺(tái)支持 PUSH, 例如 Nokia Toolkit 2.0。 Nokia Toolkit 2.0 only 內(nèi)部支持PUSHing,意味著用戶可以從工具包的界面將消息推送到模擬器。如果想試著到一個(gè)外部的Push Proxy Gateway, 工具包就崩潰了。從readme文件中知道,PUSHing 還沒(méi)有經(jīng)過(guò)完整的測(cè)試。
50. WAP
模擬器說(shuō)text/html不支持,但是用戶的MIME設(shè)置是正確的,為什么?
????
當(dāng)使用服務(wù)端的腳本語(yǔ)言,例如ASP、PHP或者Perl,來(lái)生成WML輸出,或者從HTTP服務(wù)器提供WML頁(yè)面的時(shí)候。記住HTTP一般默認(rèn)的顯示是HTML,其MIME類型是text/html。
????
如果HTTP服務(wù)器或者服務(wù)器腳本有錯(cuò)誤,錯(cuò)誤的信息將使用HTML顯示,因此微型瀏覽器是不能顯示錯(cuò)誤信息的。
????
一個(gè)開發(fā)工具/模擬器可以讓用戶看到從HTTP服務(wù)器過(guò)來(lái)的代碼。例如,在Nokia SDK中,這個(gè)功能被稱做View Source。通過(guò)看代碼可以知道HTTP服務(wù)器到底發(fā)送了些什么內(nèi)容。也可以使用普通的瀏覽器來(lái)查看任何HTML格式的錯(cuò)誤信息。
51.
在哪兒有Visio移動(dòng)電話的模板庫(kù)?
????
目前唯一知道的就是它包含在 Nokia 7110 中。
52.
有沒(méi)有其他有用的WML內(nèi)容服務(wù)列表?
????
這里至少有一個(gè)。
????
對(duì)于Unix用戶, http://pwot.co.uk/wml/中有Thomas Neill (ponder@pwot.co.uk)提供的WML工具,包括WML二進(jìn)制編譯和反編譯。
????Angus
和 Zygo WAP(angus@z-y-g-o.com)已經(jīng)開發(fā)出了一個(gè)Perl工具包。它還在為管道式的WML編譯器工作。
53. XML
到XSL的轉(zhuǎn)換可以應(yīng)用到WML和WAP嗎?
????
既然WML實(shí)際上是XML,并且XSL將WML轉(zhuǎn)換成其他不同的XML文檔,那么問(wèn)題的答案是顯然的:XSL也可以應(yīng)用到WML。可以參考Luca Passani的文章《WebTechniques》。這個(gè)文章在網(wǎng)絡(luò)上的地址是:
????http://www.webtechniques.com/archives/2000/03/passani/
????
它推薦看一下叫做《在 Apache下Cocoon計(jì)劃的實(shí)現(xiàn)》這篇文章。“Cocoon 是一個(gè)依賴于新的W3C技術(shù)(例如DOM,XML,和XSL)框架。Cocoon計(jì)劃在于改變Wen信息創(chuàng)建,生成和提供的方式。文檔內(nèi)容、風(fēng)格和邏輯經(jīng)常因?yàn)閭€(gè)人或者工作組的不同而不同。 Cocoon目標(biāo)在于將這三層分離,允許三層次之間進(jìn)行獨(dú)立的設(shè)計(jì),創(chuàng)建和管理,減少相互之間的影響,增加工作的可復(fù)用性以及縮短上市的時(shí)間。Web內(nèi)容的產(chǎn)生大多數(shù)是基于HTML的,但是HTML并不能將三者分離開來(lái),混合著各種格式標(biāo)簽,程序邏輯等等。而Cocoon計(jì)劃將要改變這種情況,允許內(nèi)容,邏輯和風(fēng)格相互分離。使用XML來(lái)保存,但是使用XSL來(lái)將它們混合。
”
????基本上來(lái)說(shuō),Cocoon將解讀HTTP頭,判斷使用的是什么瀏覽器,然后使用不同的風(fēng)格來(lái)選擇正確的頁(yè)面,使用XSL進(jìn)行混合。
54.
想讓用戶只要簡(jiǎn)單地按下一個(gè)按鈕就能夠轉(zhuǎn)跳到其他卡片而不是通過(guò)選擇URL,這個(gè)可能嗎?
????
不,不可能。
55.
如何避免一個(gè)行的中斷以便可以在一行中輸入多個(gè)鏈接?
????
在
Nokia 7110
中,不可能做到這一點(diǎn),每個(gè)鏈接都占據(jù)自己的一行。
posted on 2007-01-22 18:05
交口稱贊 閱讀(3587)
評(píng)論(3) 編輯 收藏 所屬分類:
WAP