X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fluci.git;a=blobdiff_plain;f=modules%2Fluci-base%2Fluasrc%2Fhttp%2Fprotocol.lua;h=0a8b2fbab95e5058252d734e021733b4f3eb71a6;hp=6431b04031ed6917b86b4ec19a37dbfa124a1f64;hb=a441721d32d06d18368bf236ad127ffccad0bef8;hpb=1bb4822dca6113f73e3bc89e2acf15935e6f8e92 diff --git a/modules/luci-base/luasrc/http/protocol.lua b/modules/luci-base/luasrc/http/protocol.lua index 6431b0403..0a8b2fbab 100644 --- a/modules/luci-base/luasrc/http/protocol.lua +++ b/modules/luci-base/luasrc/http/protocol.lua @@ -1,19 +1,6 @@ ---[[ +-- Copyright 2008 Freifunk Leipzig / Jo-Philipp Wich +-- Licensed to the public under the Apache License 2.0. -HTTP protocol implementation for LuCI -(c) 2008 Freifunk Leipzig / Jo-Philipp Wich - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ - -]]-- - ---- LuCI http protocol class. -- This class contains several functions useful for http message- and content -- decoding and to retrive form data from raw http messages. module("luci.http.protocol", package.seeall) @@ -22,12 +9,7 @@ local ltn12 = require("luci.ltn12") HTTP_MAX_CONTENT = 1024*8 -- 8 kB maximum content size ---- Decode an urlencoded string - optionally without decoding -- the "+" sign to " " - and return the decoded string. --- @param str Input string in x-www-urlencoded format --- @param no_plus Don't decode "+" signs to spaces --- @return The decoded string --- @see urlencode function urldecode( str, no_plus ) local function __chrdec( hex ) @@ -45,15 +27,10 @@ function urldecode( str, no_plus ) return str end ---- Extract and split urlencoded data pairs, separated bei either "&" or ";" -- from given url or string. Returns a table with urldecoded values. -- Simple parameters are stored as string values associated with the parameter -- name within the table. Parameters with multiple values are stored as array -- containing the corresponding values. --- @param url The url or string which contains x-www-urlencoded form data --- @param tbl Use the given table for storing values (optional) --- @return Table containing the urldecoded parameters --- @see urlencode_params function urldecode_params( url, tbl ) local params = tbl or { } @@ -85,10 +62,6 @@ function urldecode_params( url, tbl ) return params end ---- Encode given string to x-www-urlencoded format. --- @param str String to encode --- @return String containing the encoded data --- @see urldecode function urlencode( str ) local function __chrenc( chr ) @@ -99,7 +72,7 @@ function urlencode( str ) if type(str) == "string" then str = str:gsub( - "([^a-zA-Z0-9$_%-%.%+!*'(),])", + "([^a-zA-Z0-9$_%-%.%~])", __chrenc ) end @@ -107,12 +80,8 @@ function urlencode( str ) return str end ---- Encode each key-value-pair in given table to x-www-urlencoded format, -- separated by "&". Tables are encoded as parameters with multiple values by -- repeating the parameter name with each value. --- @param tbl Table with the values --- @return String containing encoded values --- @see urldecode_params function urlencode_params( tbl ) local enc = "" @@ -134,9 +103,6 @@ end -- (Internal function) -- Initialize given parameter and coerce string into table when the parameter -- already exists. --- @param tbl Table where parameter should be created --- @param key Parameter name --- @return Always nil local function __initval( tbl, key ) if tbl[key] == nil then tbl[key] = "" @@ -148,13 +114,18 @@ local function __initval( tbl, key ) end -- (Internal function) +-- Initialize given file parameter. +local function __initfileval( tbl, key, filename, fd ) + if tbl[key] == nil then + tbl[key] = { file=filename, fd=fd, name=key, "" } + else + table.insert( tbl[key], "" ) + end +end + +-- (Internal function) -- Append given data to given parameter, either by extending the string value -- or by appending it to the last string in the parameter's value table. --- @param tbl Table containing the previously initialized parameter value --- @param key Parameter name --- @param chunk String containing the data to append --- @return Always nil --- @see __initval local function __appendval( tbl, key, chunk ) if type(tbl[key]) == "table" then tbl[key][#tbl[key]] = tbl[key][#tbl[key]] .. chunk @@ -167,12 +138,6 @@ end -- Finish the value of given parameter, either by transforming the string value -- or - in the case of multi value parameters - the last element in the -- associated values table. --- @param tbl Table containing the previously initialized parameter value --- @param key Parameter name --- @param handler Function which transforms the parameter value --- @return Always nil --- @see __initval --- @see __appendval local function __finishval( tbl, key, handler ) if handler then if type(tbl[key]) == "table" then @@ -271,10 +236,7 @@ process_states['headers'] = function( msg, chunk ) end ---- Creates a ltn12 source from the given socket. The source will return it's -- data line by line with the trailing \r\n stripped of. --- @param sock Readable network socket --- @return Ltn12 source function function header_source( sock ) return ltn12.source.simplify( function() @@ -301,9 +263,8 @@ function header_source( sock ) end ) end ---- Decode a mime encoded http message body with multipart/form-data -- Content-Type. Stores all extracted data associated with its parameter name --- in the params table withing the given message object. Multiple parameter +-- in the params table within the given message object. Multiple parameter -- values are stored as tables, ordinary ones as strings. -- If an optional file callback function is given then it is feeded with the -- file contents chunk by chunk and only the extracted file name is stored @@ -312,12 +273,6 @@ end -- o Table containing decoded (name, file) and raw (headers) mime header data -- o String value containing a chunk of the file data -- o Boolean which indicates wheather the current chunk is the last one (eof) --- @param src Ltn12 source function --- @param msg HTTP message object --- @param filecb File callback function (optional) --- @return Value indicating successful operation (not nil means "ok") --- @return String containing the error if unsuccessful --- @see parse_message_header function mimedecode_message_body( src, msg, filecb ) if msg and msg.env.CONTENT_TYPE then @@ -368,6 +323,22 @@ function mimedecode_message_body( src, msg, filecb ) __appendval( msg.params, field.name, field.file ) store = filecb + elseif field.name and field.file then + local nxf = require "nixio" + local fd = nxf.mkstemp(field.name) + __initfileval ( msg.params, field.name, field.file, fd ) + if fd then + store = function(hdr, buf, eof) + fd:write(buf) + if (eof) then + fd:seek(0, "set") + end + end + else + store = function( hdr, buf, eof ) + __appendval( msg.params, field.name, buf ) + end + end elseif field.name then __initval( msg.params, field.name ) @@ -461,15 +432,9 @@ function mimedecode_message_body( src, msg, filecb ) return ltn12.pump.all( src, snk ) end ---- Decode an urlencoded http message body with application/x-www-urlencoded -- Content-Type. Stores all extracted data associated with its parameter name --- in the params table withing the given message object. Multiple parameter +-- in the params table within the given message object. Multiple parameter -- values are stored as tables, ordinary ones as strings. --- @param src Ltn12 source function --- @param msg HTTP message object --- @return Value indicating successful operation (not nil means "ok") --- @return String containing the error if unsuccessful --- @see parse_message_header function urldecode_message_body( src, msg ) local tlen = 0 @@ -519,12 +484,8 @@ function urldecode_message_body( src, msg ) return ltn12.pump.all( src, snk ) end ---- Try to extract an http message header including information like protocol -- version, message headers and resulting CGI environment variables from the -- given ltn12 source. --- @param src Ltn12 source function --- @return HTTP message object --- @see parse_message_body function parse_message_header( src ) local ok = true @@ -594,19 +555,12 @@ function parse_message_header( src ) return msg end ---- Try to extract and decode a http message body from the given ltn12 source. -- This function will examine the Content-Type within the given message object -- to select the appropriate content decoder. -- Currently the application/x-www-urlencoded and application/form-data -- mime types are supported. If the encountered content encoding can't be -- handled then the whole message body will be stored unaltered as "content" -- property within the given message object. --- @param src Ltn12 source function --- @param msg HTTP message object --- @param filecb File data callback (optional, see mimedecode_message_body()) --- @return Value indicating successful operation (not nil means "ok") --- @return String containing the error if unsuccessful --- @see parse_message_header function parse_message_body( src, msg, filecb ) -- Is it multipart/mime ? if msg.env.REQUEST_METHOD == "POST" and msg.env.CONTENT_TYPE and @@ -631,14 +585,23 @@ function parse_message_body( src, msg, filecb ) -- If we have a file callback then feed it if type(filecb) == "function" then - sink = filecb - + local meta = { + name = "raw", + encoding = msg.env.CONTENT_TYPE + } + sink = function( chunk ) + if chunk then + return filecb(meta, chunk, false) + else + return filecb(meta, nil, true) + end + end -- ... else append to .content else msg.content = "" msg.content_length = 0 - sink = function( chunk, err ) + sink = function( chunk ) if chunk then if ( msg.content_length + #chunk ) <= HTTP_MAX_CONTENT then msg.content = msg.content .. chunk @@ -667,8 +630,6 @@ function parse_message_body( src, msg, filecb ) end end ---- Table containing human readable messages for several http status codes. --- @class table statusmsg = { [200] = "OK", [206] = "Partial Content",