The problem was what I consider to be an obscure bug in the content
sent by the Palm for a blank password input element. If a, b, and c
are the names of three input elements, and b is a password input
element (<input type="password" name="b" value="">
),
then, if the password is left blank (displays on the Palm as
"-Unassigned-" surrounded by a dotted-line rectangle), the Palm sends
a string similar to the following for the
"application/x-www-form-urlencoded
" form data:
a=v1&b&c=v2
Note that there is no equal sign ("=") after the b. This is contrary
to my reading of the spec at
http://www.w3.org/MarkUp/html-spec/html-spec_8.html#SEC8.2.1.
As it happens, the Jetty servlet engine interprets this to mean that b
should have a blank value. Tomcat, due to its use of Sun's
HttpUtils.parseQueryString()
method, signals an error,
which returns a 500 error code to the Palm.
The Palm should instead send:
a=v1&b=&c=v2
or leave out the b value entirely:
a=v1&c=v2
Of course it would also be nice for Tomcat to be a little more
forgiving here, like Jetty. That's how I fixed the problem, by
patching the parseQueryString()
method.
How did I figure this out?
I looked at a bunch of protocol sniffers, none of which quite did the job, especially since the only way I can get the proxy to browse my web server is via a phone line; the office firewall defeats both the emulator going out and the Palm proxy coming back in. Since the protocol sniffers I found seem to work only on the ethernet card, they don't work for me. They're tough to use, too.
Yesterday I came on the idea of using a simple proxy. There is a nice page of proxies at http://www.ijs.co.nz/sorm.htm. I used a Java proxy called TCP Reflector: http://locutus.kingwoodcable.com/jfd/java/tcp/tcp.html. This proxy allows you to set up a server on one TCP port that will pass all traffic through to another machine and port. You can optionally echo all the traffic on the console. I set it to map port 80 to port 8080 on the same machine, and configured Tomcat to serve on port 8080 (Tomcat is a web server as well as a servlet engine). Presto! Within 10 minutes I had generated the following transcript, which led me right to the problem.
<HTML><HEAD><TITLE>Login</TITLE> <META NAME="PalmComputingPlatform" CONTENT="true"> </HEAD> <BODY > <FORM ACTION="/uim/UIM_s200011141659153/uthlogin.p" METHOD="POST"><TABLE><TR><TD >User name:</TD ><TD><input type="text" name="a" size="10" maxlength="10" value="shaker"></TD ></TR ><TR><TD>Password:</TD ><TD><input type="password" name="b" size="12" maxlength="12" value=""></TD ></TR ><TR><TD>Database:</TD ><TD><SELECT NAME="c"><OPTION VALUE="0">a1 - Valley's database<OPTION VALUE="1">a9<OPTION VALUE="2">b1 - BBL's database for testing (Mine U)<OPTION VALUE="3">b7 - Brinderson<OPTION VALUE="4">bu - Butler's Accounting Db for QA (MU)<OPTION VALUE="5">d0 - Empty Master - Do not delete or update!<OPTION VALUE="6">d1 - SingCO, No Div, No Ctr<OPTION VALUE="7">d6 - Grand Construction<OPTION VALUE="8">d8 - Accounting database connected to summary files db<OPTION VALUE="9">d9<OPTION VALUE="10">e1 - Ecker testing database<OPTION VALUE="11">e3 - testing Energysystems<OPTION VALUE="12">g1 - Gale Work Order QA - << DO NOT USE >><OPTION VALUE="13">h3 - hooper co 3<OPTION VALUE="14">j2 - Butler's Accounting DB<OPTION VALUE="15">k2 - Aspen Demo DB<OPTION VALUE="16">p1 - Web Application test database<OPTION SELECTED VALUE="17">p2 - Pike's scaled down p1 db for EIS demo<OPTION VALUE="18">q6 - QA Database - copy of d6<OPTION VALUE="19">r1 - Dicks ARGON Test DB<OPTION VALUE="20">s1 - Master sales database<OPTION VALUE="21">s9<OPTION VALUE="22">t1</SELECT ></TD ></TR ></TABLE > <br> <TABLE><TR></TR ><TR><TD><input type="submit" name="d" value="OK"></TD ><TD><input type="submit" name="e" value="Cancel"></TD ></TR ></TABLE ></FORM ></BODY></HTML> ######################################################################## # Thu Dec 14 16:59:21 EST 2000 # TCPReflector # Removing connection from: 209.247.202.105/209.247.202.105:80 # To : localhost/127.0.0.1:8080 ######################################################################## ######################################################################## # Thu Dec 14 16:59:31 EST 2000 # TCPReflector # Connection initiated from: 209.247.202.105/209.247.202.105 ######################################################################## ######################################################################## # Thu Dec 14 16:59:31 EST 2000 # TCPReflector # Connection established from: 209.247.202.105/209.247.202.105:80 # To : localhost/127.0.0.1:8080 ######################################################################## [src => dest, (355 bytes)] POST /uim/UIM_s200011141659153/uthlogin.p HTTP/1.0 user-agent: Mozilla/2.0 (compatible; Elaine/1.1) Accept: text/html, image/jpeg, image/gif Content-Type: application/x-www-form-urlencoded X-Forwarded-For: 192.168.166.5 Host: 205.231.148.68 Content-Length: 20 Via: 1.1 wp01dlsvl (NetCache 4.0R4D11) Connection: Keep-Alive a=shaker&b&c=17&d=OK [dest => src, (202 bytes)] HTTP/1.0 500 Internal Server Error Content-Type: text/html Servlet-Engine: Tomcat Web Server/3.2 (final) (JSP 1.1; Servlet 2.2; Java 1.3.0; Windows 2000 5.0 x86; java.vendor=Sun Microsystems Inc.) [dest => src, (1596 bytes)] <h1>Error: 500</h1> <h2>Location: /uim/UIM_s200011141659153/uthlogin.p</h2><b>Internal Servlet Error :</b><br><pre>java.lang.IllegalArgumentException [9]at javax.servlet.http.HttpUtils.parseQueryString(HttpUtils.java:151) [9]at javax.servlet.http.HttpUtils.parsePostData(HttpUtils.java:254) ...