This file is indexed.

/usr/share/lua/5.1/cgilua/post.lua is in lua-cgi 5.2~alpha2-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
----------------------------------------------------------------------------
-- Process POST data.
-- This library depends on some functions that read POST data and other
-- HTTP information.  A beginning is:
--	require"post"
--	local params = {}
--	post.parsedata {
--		read = ap.get_client_block or io.input,
--		discardinput = ap.discard_request_body,
--		content_type = ap.get_header"content-type" or os.getenv"CONTENT_TYPE",
--		content_length = ap.get_header"content-length" or os.getenv"CONTENT_LENGTH",
--		maxinput = 1024 * 1024,
--		maxfilesize = 512 * 1024,
--		args = params,
--	}
--
-- @release $Id: post.lua,v 1.17 2008/04/03 21:55:28 mascarenhas Exp $
----------------------------------------------------------------------------

local iterate = require"cgilua.readuntil".iterate
local urlcode = require"cgilua.urlcode"
local tmpfile = require"cgilua".tmpfile

local assert, error, pairs, tonumber, tostring, type = assert, error, pairs, tonumber, tostring, type
local getn, tinsert = table.getn, table.insert
local format, gsub, strfind, strlower, strlen = string.format, string.gsub, string.find, string.lower, string.len
local min = math.min
--local iterate = cgilua.readuntil.iterate
--local urlcode = cgilua.urlcode
--local tmpfile = cgilua.tmpfile

-- environment for processing multipart/form-data input
local boundary = nil      -- boundary string that separates each 'part' of input
local maxfilesize = nil   -- maximum size for file upload
local maxinput = nil      -- maximum size of total POST data
local inputfile = nil     -- temporary file for inputting form-data
local bytesleft = nil     -- number of bytes yet to be read
local content_type = nil  -- request's content-type
-- local functions
local discardinput = nil  -- discard all remaining input
local readuntil = nil     -- read until delimiter
local read = nil          -- basic read function


--
-- Extract the boundary string from CONTENT_TYPE metavariable
--
local function getboundary ()
  local _,_,boundary = strfind (content_type, "boundary%=(.-)$")
  return  "--"..boundary 
end

--
-- Create a table containing the headers of a multipart/form-data field
--
local function breakheaders (hdrdata)
  local headers = {}
  gsub (hdrdata, '([^%c%s:]+):%s+([^\n]+)', function(type,val)
    type = strlower(type)
    headers[type] = val
  end)
  return headers
end

--
-- Read the headers of the next multipart/form-data field 
--
--  This function returns a table containing the headers values. Each header
--  value is indexed by the corresponding header "type". 
--  If end of input is reached (no more fields to process) it returns nil.
--
local function readfieldheaders ()
	local EOH = "\r\n\r\n" -- <CR><LF><CR><LF>
	local hdrdata = ""
	local out = function (str) hdrdata = hdrdata..str end
	if readuntil (EOH, out) then
		-- parse headers
		return breakheaders (hdrdata)
	else
		-- no header found
		return nil
	end
end

--
-- Extract a field name (and possible filename) from its disposition header
--
local function getfieldnames (headers)
  local disposition_hdr = headers["content-disposition"]
  local attrs = {}
  if disposition_hdr then
    gsub(disposition_hdr, ';%s*([^%s=]+)="(.-)"', function(attr, val)
	   attrs[attr] = val
         end)
  else
    error("Error processing multipart/form-data."..
          "\nMissing content-disposition header")
  end
  return attrs.name, attrs.filename
end

--
-- Read the contents of a 'regular' field to a string
--
local function readfieldcontents ()
	local value = ""
	local boundaryline = "\r\n"..boundary
	local out = function (str) value = value..str end
	if readuntil (boundaryline, out) then
		return value
	else
		error("Error processing multipart/form-data.\nUnexpected end of input\n")
	end
end

--
-- Read the contents of a 'file' field to a temporary file (file upload)
--
local function fileupload (filename)
	-- create a temporary file for uploading the file field
	local file, err = tmpfile()
	if file == nil then
		discardinput(bytesleft)
		error("Cannot create a temporary file.\n"..err)
	end      
	local bytesread = 0
	local boundaryline = "\r\n"..boundary
	local out = function (str)
		local sl = strlen (str)
		if bytesread + sl > maxfilesize then
			discardinput (bytesleft)
			error (format ("Maximum file size (%d kbytes) exceeded while uploading `%s'", maxfilesize / 1024, filename))
		end
		file:write (str)
		bytesread = bytesread + sl
	end
	if readuntil (boundaryline, out) then
		file:seek ("set", 0)
		return file, bytesread
	else
		error (format ("Error processing multipart/form-data.\nUnexpected end of input while uploading %s", filename))
	end
end

--
-- Compose a file field 'value' 
--
local function filevalue (filehandle, filename, filesize, headers)
  -- the temporary file handle
  local value = { file = filehandle,
                  filename = filename,
                  filesize = filesize }
  -- copy additional header values
  for hdr, hdrval in pairs(headers) do
    if hdr ~= "content-disposition" then
      value[hdr] = hdrval
    end
  end
  return value
end

--
-- Process multipart/form-data 
--
-- This function receives the total size of the incoming multipart/form-data, 
-- the maximum size for a file upload, and a reference to a table where the 
-- form fields should be stored.
--
-- For every field in the incoming form-data a (name=value) pair is 
-- inserted into the given table. [[name]] is the field name extracted
-- from the content-disposition header.
--
-- If a field is of type 'file' (i.e., a 'filename' attribute was found
-- in its content-disposition header) a temporary file is created 
-- and the field contents are written to it. In this case,
-- [[value]] has a table that contains the temporary file handle 
-- (key 'file') and the file name (key 'filename'). Optional headers
-- included in the field description are also inserted into this table,
-- as (header_type=value) pairs.
--
-- If the field is not of type 'file', [[value]] contains the field 
-- contents.
--
local function Main (inputsize, args)

	-- create a temporary file for processing input data
	local inputf,err = tmpfile()
	if inputf == nil then
		discardinput(inputsize)
		error("Cannot create a temporary file.\n"..err)
	end

	-- set the environment for processing the multipart/form-data
	inputfile = inputf
	bytesleft = inputsize
	maxfilesize = maxfilesize or inputsize 
	boundary = getboundary()

	while true do
		-- read the next field header(s)
		local headers = readfieldheaders()
		if not headers then break end	-- end of input

		-- get the name attributes for the form field (name and filename)
		local name, filename = getfieldnames(headers)

		-- get the field contents
		local value
		if filename then
			local filehandle, filesize = fileupload(filename)
			value = filevalue(filehandle, filename, filesize, headers)
		else
			value = readfieldcontents()
		end

		-- insert the form field into table [[args]]
		urlcode.insertfield(args, name, value)
	end
end

--
-- Initialize the library by setting the dependent functions:
--	content_type            = value of "Content-type" header
--	content_length          = value of "Content-length" header
--	read                    = function that can read POST data
--	discardinput (optional) = function that discard POST data
--	maxinput (optional)     = limit of POST data (in bytes)
--	maxfilesize (optional)  = limit of uploaded file(s) (in bytes)
--
local function init (defs)
	assert (defs.read)
	read = defs.read
	readuntil = iterate (function ()
        if bytesleft then
            if bytesleft <= 0 then return nil end
            local n = min (bytesleft, 2^13) -- 2^13 == 8192
            local bytes = read (n)
            bytesleft = bytesleft - #bytes
            return bytes
        end
	end)
	if defs.discard_function then
		discardinput = defs.discardinput
	else
		discardinput = function (inputsize)
			readuntil ('\0', function()end)
		end
	end
	content_type = defs.content_type
	if defs.maxinput then
		maxinput = defs.maxinput
	end
	if defs.maxfilesize then
		maxfilesize = defs.maxfilesize
	end
end

----------------------------------------------------------------------------
-- Parse the POST REQUEST incoming data according to its "content type"
-- as defined by the metavariable CONTENT_TYPE (RFC CGI)
--
--  An error is issued if the "total" size of the incoming data
--   (defined by the metavariable CONTENT_LENGTH) exceeds the
--   maximum input size allowed
----------------------------------------------------------------------------
return {
	parsedata = function (defs)
		assert (type(defs.args) == "table", "field `args' must be a table")
		init (defs)
		-- get the "total" size of the incoming data
		local inputsize = tonumber(defs.content_length) or 0
		if inputsize > maxinput then
			-- some Web Servers (like IIS) require that all the incoming data is read 
			bytesleft = inputsize
			discardinput(inputsize)
			error(format("Total size of incoming data (%d KB) exceeds configured maximum (%d KB)",
				inputsize /1024, maxinput / 1024))
		end

		-- process the incoming data according to its content type
		local contenttype = content_type
		if not contenttype then
			error("Undefined Media Type") 
		end
		if strfind(contenttype, "x-www-form-urlencoded", 1, true) then
			urlcode.parsequery (read (inputsize), defs.args)
		elseif strfind(contenttype, "multipart/form-data", 1, true) then
			Main (inputsize, defs.args)
		elseif strfind (contenttype, "application/xml", 1, true) or strfind (contenttype, "text/xml", 1, true) or strfind (contenttype, "text/plain", 1, true) then
			tinsert (defs.args, read (inputsize))
		else
			error("Unsupported Media Type: "..contenttype)
		end
	end,
}