--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0//EN"\r
+ "http://www.w3.org/TR/REC-html40/strict.dtd">\r
+<html>\r
+ <head>\r
+ <title>PostableFrame.java</title>\r
+ <meta name="Author" content="Benoit Mahe">\r
+ <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">\r
+ <meta name="Generator" content="*emacs: emacs-css">\r
+\r
+ <link rel="Stylesheet" media="screen" type="text/css" href="default-html.css">\r
+ </head>\r
+ <body>\r
+\r
+ <pre>\r
+<span class="comment">// PostableFrame.java\r
+// $Id: PostableFrame.html,v 1.1 2010/06/15 12:20:07 smhuang Exp $\r
+// (c) COPYRIGHT MIT and INRIA, 1996.\r
+// Please first read the full copyright statement in file COPYRIGHT.html\r
+</span>\r
+<span class="keyword">package</span> <span class="reference">org</span>.<span class="reference">w3c</span>.<span class="reference">jigsaw</span>.<span class="type">frames</span> ;\r
+\r
+<span class="keyword">import</span> <span class="reference">java</span>.<span class="reference">io</span>.* ;\r
+<span class="keyword">import</span> <span class="reference">java</span>.<span class="reference">util</span>.*;\r
+\r
+<span class="keyword">import</span> <span class="reference">org</span>.<span class="reference">w3c</span>.<span class="reference">tools</span>.<span class="reference">resources</span>.*;\r
+<span class="keyword">import</span> <span class="reference">org</span>.<span class="reference">w3c</span>.<span class="reference">jigsaw</span>.<span class="reference">forms</span>.*;\r
+<span class="keyword">import</span> <span class="reference">org</span>.<span class="reference">w3c</span>.<span class="reference">www</span>.<span class="reference">mime</span>.* ;\r
+<span class="keyword">import</span> <span class="reference">org</span>.<span class="reference">w3c</span>.<span class="reference">www</span>.<span class="reference">http</span>.* ;\r
+<span class="keyword">import</span> <span class="reference">org</span>.<span class="reference">w3c</span>.<span class="reference">jigsaw</span>.<span class="reference">http</span>.* ;\r
+<span class="keyword">import</span> <span class="reference">org</span>.<span class="reference">w3c</span>.<span class="reference">jigsaw</span>.<span class="reference">html</span>.<span class="type">HtmlGenerator</span> ;\r
+\r
+<span class="comment">/**\r
+ * Handle POST.\r
+ */</span>\r
+<span class="reference">public</span> <span class="keyword">class</span> <span class="function-name">PostableFrame</span> <span class="keyword">extends</span> <span class="type">HTTPFrame</span> {\r
+ <span class="string">private</span> <span class="type">static</span> <span class="type">HttpTokenList</span> <span class="variable-name">_post_allowed</span> = <span class="keyword">null</span>; \r
+ <span class="string">private</span> <span class="type">static</span> <span class="type">HttpTokenList</span> <span class="variable-name">_put_allowed</span> = <span class="keyword">null</span>; \r
+ <span class="type">static</span> {\r
+ <span class="type">String</span> <span class="variable-name">post_allowed</span>[] = { "<span class="string">GET</span>", "<span class="string">HEAD</span>", "<span class="string">OPTIONS</span>", "<span class="string">POST</span>", "<span class="string">TRACE</span>" } ;\r
+ _post_allowed = HttpFactory.makeStringList(post_allowed);\r
+ <span class="type">String</span> <span class="variable-name">put_allowed</span>[] = { "<span class="string">GET</span>", "<span class="string">HEAD</span>", "<span class="string">OPTIONS</span>", "<span class="string">PUT</span>",\r
+ "<span class="string">POST</span>", "<span class="string">TRACE</span>" } ;\r
+ _put_allowed = HttpFactory.makeStringList(put_allowed);\r
+ }\r
+ \r
+ <span class="string">private</span> <span class="type">static</span> <span class="type">MimeType</span> <span class="variable-name">type</span> = MimeType.APPLICATION_X_WWW_FORM_URLENCODED ;\r
+ <span class="comment">/**\r
+ * Attribute index - Should we override form values when multiple ?\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">static</span> <span class="type">int</span> <span class="variable-name">ATTR_OVERIDE</span> = -1 ;\r
+ <span class="comment">/**\r
+ * Attribute index - Should we silently convert GET to POST methods ?\r
+ */</span>\r
+ <span class="preprocessor">protected</span> <span class="type">static</span> <span class="type">int</span> <span class="variable-name">ATTR_CONVERT_GET</span> = -1 ;\r
+ \r
+ <span class="type">static</span> {\r
+ <span class="type">Attribute</span> <span class="variable-name">a</span> = <span class="keyword">null</span> ;\r
+ <span class="type">Class</span> <span class="variable-name">cls</span> = <span class="keyword">null</span> ;\r
+ <span class="keyword">try</span> {\r
+ cls = Class.forName("<span class="string">org.w3c.jigsaw.frames.PostableFrame</span>") ;\r
+ } <span class="keyword">catch</span> (<span class="type">Exception</span> <span class="variable-name">ex</span>) {\r
+ ex.printStackTrace() ;\r
+ System.exit(1) ;\r
+ }\r
+ <span class="comment">// The override attribute:\r
+</span> a = <span class="keyword">new</span> <span class="type">BooleanAttribute</span>("<span class="string">override</span>",\r
+ Boolean.FALSE,\r
+ Attribute.EDITABLE);\r
+ ATTR_OVERIDE = AttributeRegistry.registerAttribute(cls, a) ;\r
+ <span class="comment">// The convert get attribute:\r
+</span> a = <span class="keyword">new</span> <span class="type">BooleanAttribute</span>("<span class="string">convert-get</span>",\r
+ Boolean.TRUE,\r
+ Attribute.EDITABLE) ;\r
+ ATTR_CONVERT_GET = AttributeRegistry.registerAttribute(cls, a) ;\r
+ }\r
+ \r
+ <span class="comment">/**\r
+ * Get the 'convert GET to POST' flag.\r
+ */</span>\r
+ \r
+ <span class="reference">public</span> <span class="type">boolean</span> <span class="function-name">getConvertGetFlag</span>() {\r
+ <span class="keyword">return</span> getBoolean(ATTR_CONVERT_GET, <span class="keyword">false</span>) ;\r
+ }\r
+ \r
+ <span class="comment">/**\r
+ * Get the 'override multiple form field value' flag.\r
+ */</span>\r
+ \r
+ <span class="reference">public</span> <span class="type">boolean</span> <span class="function-name">getOverrideFlag</span>() {\r
+ <span class="keyword">return</span> getBoolean(ATTR_OVERIDE, <span class="keyword">true</span>) ;\r
+ }\r
+\r
+\r
+ <span class="comment">/**\r
+ * Catch setValue, to maintain cached header values correctness.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">idx</span><span class="comment"> The index of the attribute to be set.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">value</span><span class="comment"> The new value for the attribute.\r
+ */</span>\r
+ \r
+ <span class="reference">public</span> <span class="type">synchronized</span> <span class="type">void</span> <span class="function-name">setValue</span>(<span class="type">int</span> <span class="variable-name">idx</span>, <span class="type">Object</span> <span class="variable-name">value</span>) {\r
+ <span class="reference">super</span>.setValue(idx, value);\r
+ <span class="keyword">if</span> (idx == ATTR_PUTABLE) {\r
+ <span class="keyword">if</span> (value == Boolean.TRUE)\r
+ allowed = _put_allowed;\r
+ <span class="keyword">else</span> \r
+ allowed = _post_allowed;\r
+ }\r
+ }\r
+ \r
+ \r
+ <span class="comment">/**\r
+ * Get this resource body.\r
+ * If we are allowed to convert GET requests to POST, than we first\r
+ * check to see if there is some search string in the request, and continue\r
+ * with normal POST request processing.\r
+ * <p>If there is no search string, or if we are not allowed to convert\r
+ * GETs to POSTs, than we just invoke our <code>super</code> method,\r
+ * which will perform the appropriate job.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> The request to handle.\r
+ * </span><span class="keyword">@exception </span><span class="type">ProtocolException</span><span class="comment"> If request couldn't be processed.\r
+ */</span>\r
+ <span class="reference">public</span> <span class="type">Reply</span> <span class="function-name">get</span> (<span class="type">Request</span> <span class="variable-name">request</span>) \r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="comment">// Check if we should handle it (is it a POST disguised in GET ?)\r
+</span> <span class="keyword">if</span> ((! getConvertGetFlag()) || ( ! request.hasState("<span class="string">query</span>")))\r
+ <span class="keyword">return</span> <span class="reference">super</span>.get (request) ;\r
+ <span class="comment">// Get the request entity, and decode it:\r
+</span> <span class="type">String</span> <span class="variable-name">query</span> = request.getQueryString() ;\r
+ <span class="type">InputStream</span> <span class="variable-name">in</span> = <span class="keyword">new</span> <span class="type">StringBufferInputStream</span>(query) ;\r
+ <span class="type">URLDecoder</span> <span class="variable-name">d</span> = <span class="keyword">new</span> <span class="type">URLDecoder</span> (in, getOverrideFlag()) ;\r
+ <span class="keyword">try</span> {\r
+ d.parse () ;\r
+ } <span class="keyword">catch</span> (<span class="type">URLDecoderException</span> <span class="variable-name">e</span>) {\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.BAD_REQUEST) ;\r
+ error.setContent("<span class="string">Invalid request:unable to decode form data.</span>");\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error) ;\r
+ } <span class="keyword">catch</span> (<span class="type">IOException</span> <span class="variable-name">e</span>) {\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.BAD_REQUEST) ;\r
+ error.setContent("<span class="string">Invalid request: unable to read form data.</span>");\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error) ;\r
+ }\r
+ <span class="keyword">return</span> handle (request, d) ;\r
+ }\r
+ \r
+ <span class="reference">public</span> <span class="type">Reply</span> <span class="function-name">post</span> (<span class="type">Request</span> <span class="variable-name">request</span>)\r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span>, <span class="type">NotAProtocolException</span>\r
+ {\r
+ <span class="comment">// Check that we are dealing with an application/x-www-form-urlencoded:\r
+</span> <span class="keyword">if</span> ((! request.hasContentType())\r
+ || (type.match(request.getContentType()) < 0) ) {\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.UNSUPPORTED_MEDIA_TYPE) ;\r
+ error.setContent("<span class="string">Invalid request content type.</span>");\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error) ;\r
+ }\r
+ <span class="comment">// Get and decode the request entity:\r
+</span> <span class="type">URLDecoder</span> <span class="variable-name">dec</span> = <span class="keyword">null</span>;\r
+ <span class="keyword">try</span> {\r
+ <span class="type">InputStream</span> <span class="variable-name">in</span> = request.getInputStream() ;\r
+ <span class="comment">// Notify the client that we are willing to continue processing:\r
+</span> <span class="type">Client</span> <span class="variable-name">client</span> = request.getClient();\r
+ <span class="keyword">if</span> ( client != <span class="keyword">null</span> ) \r
+ client.sendContinue();\r
+ dec = <span class="keyword">new</span> <span class="type">URLDecoder</span> (in, getOverrideFlag()) ;\r
+ dec.parse () ;\r
+ } <span class="keyword">catch</span> (<span class="type">URLDecoderException</span> <span class="variable-name">e</span>) {\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.BAD_REQUEST) ;\r
+ error.setContent("<span class="string">Invalid request: unable to decode form data.</span>") ;\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">HTTPException</span> (error) ;\r
+ } <span class="keyword">catch</span> (<span class="type">IOException</span> <span class="variable-name">ex</span>) {\r
+ <span class="type">Reply</span> <span class="variable-name">error</span> = request.makeReply(HTTP.BAD_REQUEST) ;\r
+ error.setContent("<span class="string">Invalid request: unable to read form data.</span>") ;\r
+ <span class="keyword">throw</span> <span class="keyword">new</span> <span class="type">ClientException</span>(request.getClient(), ex) ;\r
+ }\r
+ <span class="comment">// Handle the stuff:\r
+</span> <span class="keyword">return</span> handle (request, dec) ;\r
+ }\r
+ \r
+ <span class="comment">/**\r
+ * Handle the form submission, after posted data parsing.\r
+ * <p>This method ought to be abstract, but for reasonable reason, it\r
+ * will just dump (parsed) the form content back to the client, so that it\r
+ * can be used for debugging.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">request</span><span class="comment"> The request proper.\r
+ * </span><span class="keyword">@param </span><span class="variable-name">data</span><span class="comment"> The parsed data content.\r
+ * </span><span class="keyword">@exception </span><span class="type">ProtocolException</span><span class="comment"> If form data processing failed.\r
+ * </span><span class="keyword">@see </span><span class="function-name">org.w3c.jigsaw.forms.URLDecoder</span><span class="comment">\r
+ */</span>\r
+ \r
+ <span class="reference">public</span> <span class="type">Reply</span> <span class="function-name">handle</span> (<span class="type">Request</span> <span class="variable-name">request</span>, <span class="type">URLDecoder</span> <span class="variable-name">data</span>)\r
+ <span class="keyword">throws</span> <span class="type">ProtocolException</span> \r
+ {\r
+ <span class="comment">// Now we just dump back the variables we got:\r
+</span> <span class="type">Enumeration</span> <span class="variable-name">e</span> = data.keys() ;\r
+ <span class="type">HtmlGenerator</span> <span class="variable-name">g</span> = <span class="keyword">new</span> <span class="type">HtmlGenerator</span> ("<span class="string">Form decoded values</span>") ;\r
+ g.append ("<span class="string"><p>List of variables and values:</p><ul></span>") ;\r
+ <span class="keyword">while</span> ( e.hasMoreElements () ) {\r
+ <span class="type">String</span> <span class="variable-name">name</span> = (<span class="type">String</span>) e.nextElement() ;\r
+ g.append ("<span class="string"><li><em></span>"+\r
+ name+"<span class="string"></em> = <b></span>"+\r
+ data.getValue(name)+\r
+ "<span class="string"></b></li></span>");\r
+ }\r
+ g.append ("<span class="string"></ul></span>") ;\r
+ <span class="type">Reply</span> <span class="variable-name">reply</span> = request.makeReply(HTTP.OK) ;\r
+ reply.setStream (g) ;\r
+ <span class="keyword">return</span> reply ;\r
+ }\r
+}\r
+\r
+ </pre>\r
+ </body>\r
+</html>\r