PageRenderTime 44ms CodeModel.GetById 15ms app.highlight 22ms RepoModel.GetById 1ms app.codeStats 0ms

/bin/std/neko/Web.hx

http://github.com/Yoomee/clippy
Haxe | 388 lines | 250 code | 29 blank | 109 comment | 52 complexity | 5c86783c4253b03a4737c3cb71a13b33 MD5 | raw file
  1/*
  2 * Copyright (c) 2005, The haXe Project Contributors
  3 * All rights reserved.
  4 * Redistribution and use in source and binary forms, with or without
  5 * modification, are permitted provided that the following conditions are met:
  6 *
  7 *   - Redistributions of source code must retain the above copyright
  8 *     notice, this list of conditions and the following disclaimer.
  9 *   - Redistributions in binary form must reproduce the above copyright
 10 *     notice, this list of conditions and the following disclaimer in the
 11 *     documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 16 * DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
 17 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 20 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 23 * DAMAGE.
 24 */
 25package neko;
 26
 27/**
 28	This class is used for accessing the local Web server and the current
 29	client request and informations.
 30**/
 31class Web {
 32
 33	/**
 34		Returns the GET and POST parameters.
 35	**/
 36	public static function getParams() {
 37		var p = _get_params();
 38		var h = new Hash<String>();
 39		var k = "";
 40		while( p != null ) {
 41			untyped k.__s = p[0];
 42			h.set(k,new String(p[1]));
 43			p = untyped p[2];
 44		}
 45		return h;
 46	}
 47
 48	/**
 49		Returns an Array of Strings built using GET / POST values.
 50		If you have in your URL the parameters [a[]=foo;a[]=hello;a[5]=bar;a[3]=baz] then
 51		[neko.Web.getParamValues("a")] will return [["foo","hello",null,"baz",null,"bar"]]
 52	**/
 53	public static function getParamValues( param : String ) : Array<String> {
 54		var reg = new EReg("^"+param+"(\\[|%5B)([0-9]*?)(\\]|%5D)=(.*?)$", "");
 55		var res = new Array<String>();
 56		var explore = function(data:String){
 57			if (data == null || data.length == 0)
 58				return;
 59			for (part in data.split("&")){
 60				if (reg.match(part)){
 61					var idx = reg.matched(2);
 62					var val = StringTools.urlDecode(reg.matched(4));
 63					if (idx == "")
 64						res.push(val);
 65					else
 66						res[Std.parseInt(idx)] = val;
 67				}
 68			}
 69		}
 70		explore(StringTools.replace(getParamsString(), ";", "&"));
 71		explore(getPostData());
 72		if (res.length == 0)
 73			return null;
 74		return res;
 75	}
 76
 77	/**
 78		Returns the local server host name
 79	**/
 80	public static function getHostName() {
 81		return new String(_get_host_name());
 82	}
 83
 84	/**
 85		Surprisingly returns the client IP address.
 86	**/
 87	public static function getClientIP() {
 88		return new String(_get_client_ip());
 89	}
 90
 91	/**
 92		Returns the original request URL (before any server internal redirections)
 93	**/
 94	public static function getURI() {
 95		return new String(_get_uri());
 96	}
 97
 98	/**
 99		Tell the client to redirect to the given url ("Location" header)
100	**/
101	public static function redirect( url : String ) {
102		_cgi_redirect(untyped url.__s);
103	}
104
105	/**
106		Set an output header value. If some data have been printed, the headers have
107		already been sent so this will raise an exception.
108	**/
109	public static function setHeader( h : String, v : String ) {
110		_cgi_set_header(untyped h.__s,untyped v.__s);
111	}
112
113	/**
114		Set the HTTP return code. Same remark as setHeader.
115	**/
116	public static function setReturnCode( r : Int ) {
117		_set_return_code(r);
118	}
119
120	/**
121		Retrieve a client header value sent with the request.
122	**/
123	public static function getClientHeader( k : String ) {
124		var v = _get_client_header(untyped k.__s);
125		if( v == null )
126			return null;
127		return new String(v);
128	}
129
130	/**
131		Retrieve all the client headers.
132	**/
133	public static function getClientHeaders() {
134		var v = _get_client_headers();
135		var a = new List();
136		while( v != null ) {
137			a.add({ header : new String(v[0]), value : new String(v[1]) });
138			v = cast v[2];
139		}
140		return a;
141	}
142
143	/**
144		Returns all the GET parameters String
145	**/
146	public static function getParamsString() {
147		return new String(_get_params_string());
148	}
149
150	/**
151		Returns all the POST data. POST Data is always parsed as
152		being application/x-www-form-urlencoded and is stored into
153		the getParams hashtable. POST Data is maximimized to 256K
154		unless the content type is multipart/form-data. In that
155		case, you will have to use [getMultipart] or [parseMultipart]
156		methods.
157	**/
158	public static function getPostData() {
159		var v = _get_post_data();
160		if( v == null )
161			return null;
162		return new String(v);
163	}
164
165	/**
166		Returns an hashtable of all Cookies sent by the client.
167		Modifying the hashtable will not modify the cookie, use setCookie instead.
168	**/
169	public static function getCookies() {
170		var p = _get_cookies();
171		var h = new Hash<String>();
172		var k = "";
173		while( p != null ) {
174			untyped k.__s = p[0];
175			h.set(k,new String(p[1]));
176			p = untyped p[2];
177		}
178		return h;
179	}
180
181
182	/**
183		Set a Cookie value in the HTTP headers. Same remark as setHeader.
184	**/
185	public static function setCookie( key : String, value : String, ?expire: Date, ?domain: String, ?path: String, ?secure: Bool ) {
186		var buf = new StringBuf();
187		buf.add(value);
188		if( expire != null ) addPair(buf, "expires=", DateTools.format(expire, "%a, %d-%b-%Y %H:%M:%S GMT"));
189		addPair(buf, "domain=", domain);
190		addPair(buf, "path=", path);
191		if( secure ) addPair(buf, "secure", "");
192		var v = buf.toString();
193		_set_cookie(untyped key.__s, untyped v.__s);
194	}
195
196	static function addPair( buf : StringBuf, name, value ) {
197		if( value == null ) return;
198		buf.add("; ");
199		buf.add(name);
200		buf.add(value);
201	}
202
203	/**
204		Returns an object with the authorization sent by the client (Basic scheme only).
205	**/
206	public static function getAuthorization() : { user : String, pass : String } {
207		var h = getClientHeader("Authorization");
208		var reg = ~/^Basic ([^=]+)=*$/;
209		if( h != null && reg.match(h) ){
210			var val = reg.matched(1);
211			untyped val = new String(_base_decode(val.__s,"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".__s));
212			var a = val.split(":");
213			if( a.length != 2 ){
214				throw "Unable to decode authorization.";
215			}
216			return {user: a[0],pass: a[1]};
217		}
218		return null;
219	}
220
221	/**
222		Get the current script directory in the local filesystem.
223	**/
224	public static function getCwd() {
225		return new String(_get_cwd());
226	}
227
228	/**
229		Set the main entry point function used to handle requests.
230		Setting it back to null will disable code caching.
231	**/
232	public static function cacheModule( f : Void -> Void ) {
233		_set_main(f);
234	}
235
236	/**
237		Get the multipart parameters as an hashtable. The data
238		cannot exceed the maximum size specified.
239	**/
240	public static function getMultipart( maxSize : Int ) : Hash<String> {
241		var h = new Hash();
242		var buf : haxe.io.BytesBuffer = null;
243		var curname = null;
244		parseMultipart(function(p,_) {
245			if( curname != null )
246				h.set(curname,neko.Lib.stringReference(buf.getBytes()));
247			curname = p;
248			buf = new haxe.io.BytesBuffer();
249			maxSize -= p.length;
250			if( maxSize < 0 )
251				throw "Maximum size reached";
252		},function(str,pos,len) {
253			maxSize -= len;
254			if( maxSize < 0 )
255				throw "Maximum size reached";
256			buf.addBytes(str,pos,len);
257		});
258		if( curname != null )
259			h.set(curname,neko.Lib.stringReference(buf.getBytes()));
260		return h;
261	}
262
263	/**
264		Parse the multipart data. Call [onPart] when a new part is found
265		with the part name and the filename if present
266		and [onData] when some part data is readed. You can this way
267		directly save the data on hard drive in the case of a file upload.
268	**/
269	public static function parseMultipart( onPart : String -> String -> Void, onData : haxe.io.Bytes -> Int -> Int -> Void ) : Void {
270		_parse_multipart(
271			function(p,f) { onPart(new String(p),if( f == null ) null else new String(f)); },
272			function(buf,pos,len) { onData(untyped new haxe.io.Bytes(__dollar__ssize(buf),buf),pos,len); }
273		);
274	}
275
276	/**
277		Flush the data sent to the client. By default on Apache, outgoing data is buffered so
278		this can be useful for displaying some long operation progress.
279	**/
280	public static function flush() : Void {
281		_flush();
282	}
283
284	/**
285		Get the HTTP method used by the client. This api requires Neko 1.7.1+
286	**/
287	public static function getMethod() : String {
288		return new String(_get_http_method());
289	}
290
291	/**
292		Write a message into the web server log file. This api requires Neko 1.7.1+
293	**/
294	public static function logMessage( msg : String ) {
295		_log_message(untyped msg.__s);
296	}
297
298	public static var isModNeko(default,null) : Bool;
299	public static var isTora(default,null) : Bool;
300
301	static var _set_main : Dynamic;
302	static var _get_host_name : Dynamic;
303	static var _get_client_ip : Dynamic;
304	static var _get_uri : Dynamic;
305	static var _cgi_redirect : Dynamic;
306	static var _cgi_set_header : Dynamic;
307	static var _set_return_code : Dynamic;
308	static var _get_client_header : Dynamic;
309	static var _get_params_string : Dynamic;
310	static var _get_post_data : Dynamic;
311	static var _get_params : Dynamic;
312	static var _get_cookies : Dynamic;
313	static var _set_cookie : Dynamic;
314	static var _get_cwd : Dynamic;
315	static var _parse_multipart : Dynamic;
316	static var _flush : Dynamic;
317	static var _get_client_headers : Dynamic;
318	static var _get_http_method : Dynamic;
319	static var _base_decode = Lib.load("std","base_decode",2);
320	static var _log_message : Dynamic;
321
322	static function __init__() {
323		var get_env = Lib.load("std","get_env",1);
324		var ver = untyped get_env("MOD_NEKO".__s);
325		untyped isModNeko = (ver != null);
326		if( isModNeko ) {
327			var lib = "mod_neko"+if( ver == untyped "1".__s ) "" else ver;
328			_set_main = Lib.load(lib,"cgi_set_main",1);
329			_get_host_name = Lib.load(lib,"get_host_name",0);
330			_get_client_ip = Lib.load(lib,"get_client_ip",0);
331			_get_uri = Lib.load(lib,"get_uri",0);
332			_cgi_redirect = Lib.load(lib,"redirect",1);
333			_cgi_set_header = Lib.load(lib,"set_header",2);
334			_set_return_code = Lib.load(lib,"set_return_code",1);
335			_get_client_header = Lib.load(lib,"get_client_header",1);
336			_get_params_string = Lib.load(lib,"get_params_string",0);
337			_get_post_data = Lib.load(lib,"get_post_data",0);
338			_get_params = Lib.load(lib,"get_params",0);
339			_get_cookies = Lib.load(lib,"get_cookies",0);
340			_set_cookie = Lib.load(lib,"set_cookie",2);
341			_get_cwd = Lib.load(lib,"cgi_get_cwd",0);
342			_get_http_method = Lib.loadLazy(lib,"get_http_method",0);
343			_parse_multipart = Lib.loadLazy(lib,"parse_multipart_data",2);
344			_flush = Lib.loadLazy(lib,"cgi_flush",0);
345			_get_client_headers = Lib.loadLazy(lib,"get_client_headers",0);
346			_log_message = Lib.loadLazy(lib,"log_message",1);
347			isTora = try Lib.load(lib,"tora_infos",0) != null catch( e : Dynamic) false;
348		} else {
349			var a0 = untyped __dollar__loader.args[0];
350			if( a0 != null ) a0 = new String(a0);
351			_set_main = function(f) { };
352			_get_host_name = function() { return untyped "localhost".__s; };
353			_get_client_ip = function() { return untyped "127.0.0.1".__s; };
354			_get_uri = function() {
355				return untyped (if( a0 == null ) "/" else a0).__s;
356			};
357			_cgi_redirect = function(v) { Lib.print("Location: "+v+"\n"); };
358			_cgi_set_header = function(h,v) { };
359			_set_return_code = function(i) { };
360			_get_client_header = function(h) { return null; };
361			_get_client_headers = function() { return null; };
362			_get_params_string = function() {
363				return untyped (if( a0 == null ) "" else a0).__s;
364			};
365			_get_post_data = function() { return null; };
366			_get_params = function() {
367				var l = null;
368				if( a0 == null )
369					return null;
370				for( p in a0.split(";") ) {
371					var k = p.split("=");
372					if( k.length == 2 )
373						l = untyped [k[0].__s,k[1].__s,l];
374				}
375				return l;
376			};
377			_get_cookies = function() { return null; }
378			_set_cookie = function(k,v) { };
379			_get_cwd = Lib.load("std","get_cwd",0);
380			_get_http_method = function() return untyped "GET".__s;
381			_parse_multipart = function(a,b) { throw "Not supported"; };
382			_flush = function() { };
383			_log_message = function(s) { };
384			isTora = false;
385		}
386	}
387
388}