[ create a new paste ] login | about

Link: http://codepad.org/YoKaGyjY    [ raw code | fork ]

arachneng - Lua, pasted on Aug 16:
-- windmill.mearie.org multiview emulation script
-- last updated on 2009-06-22
--
-- adapted (and heavily modified) from Svilen Spasov's:
--    http://blog.svilen.com/2009/04/using-modnegotiation-with-lighttpd.html
-- only implements Accept-Language detection, which is best used so far.

local EXTENSIONS = {'.php', '.html', '.js', '.css', '.xhtml', '.xml'}
local LANGUAGES = {'.en', '.ko', '.ja', ''}
local INDEXFILE = 'index'

function parse_acceptlang(spec)
	--print('Accept-Language was ' .. spec)

	spec = spec .. ','
	local exts = {}
	while spec ~= '' do
		-- extract first specification from the string.
		local lang, q, tail = spec:match('^%s*([%w%-]+)%s*;%s*q%s*=%s*([%d%.]+)%s*,%s*(.*)$')
		if not lang then
			lang, tail = spec:match('^%s*([%w%-]+)%s*,%s*(.*)$')
			if not lang then return false end -- invalid specification: stop parsing.
			q = 1.0 -- assume q=1.0
		else
			q = tonumber(q)
			if not q then return false end -- invalid q-value
		end

		-- for sake of simplicity, we assume implicit * at the end of specification.
		-- (so we don't have to return 406 Not Acceptable, but it is not complying)
		if lang ~= '*' then
			table.insert(exts, {'.' .. lang, q, #exts})
		end

		spec = tail
	end

	-- sort the list by q-value and relative order.
	table.sort(exts, function(lhs, rhs)
		return (lhs[2] > rhs[2] or (lhs[2] == rhs[2] and lhs[3] > rhs[3]))
	end)

	-- now replace LANGUAGES by new list.
	local newlangs = {}
	local used = {}
	for _, entry in ipairs(exts) do
		local ext = entry[1]
		if not used[ext] then
			table.insert(newlangs, ext)
			used[ext] = true
		end
	end
	for _, ext in ipairs(LANGUAGES) do
		if not used[ext] then
			table.insert(newlangs, ext)
		end
	end
	LANGUAGES = newlangs

	--print('replacing LANGUAGES with ' .. table.concat(newlangs, '/'))
end

function apply_constraint(filename, exts)
	for _, ext in ipairs(exts) do
		if ext ~= '' and filename:sub(-ext:len()) == ext then
			return filename:sub(1, -1-ext:len()), ext
		end
	end
	return filename, nil
end

local stat = lighty.stat(lighty.env['physical.path'])
if not stat or stat.is_dir then
	local path = lighty.env['physical.rel-path']
	local origpath = path
	local uri = lighty.env['request.uri']
	local docroot = lighty.env['physical.doc-root']

	while uri ~= '' do
		-- remove last directory/URI element from uri and path until URI is empty.
		uri = uri:match('^(.-)[/\\]+[^/\\]*$')
		local prevpath = path
		local part
		path, part = path:match('^(.-)[/\\]+([^/\\]*)$')
		if part == "" then
			-- since we are removing consecutive slashes at once, this case can
			-- only appear at the first time, i.e. stat.is_dir was true.
			part = INDEXFILE
		end

		local stat = lighty.stat(docroot .. path)
		if stat then
			-- if it is just a file, we may continue as is since lighty will
			-- split the original path correctly.
			if stat.is_dir then
				-- we now have to parse Accept-Language header if exists.
				if lighty.request['Accept-Language'] then
					parse_acceptlang(lighty.request['Accept-Language'])
				end

				-- apply possible constraints from the requested file name.
				local part, langext = apply_constraint(part, LANGUAGES)
				local part, typeext = apply_constraint(part, EXTENSIONS)
				if langext then LANGUAGES = {langext} end
				if typeext then EXTENSIONS = {typeext} end

				--print('final LANGUAGES: ' .. table.concat(LANGUAGES, '/'))
				--print('final EXTENSIONS: ' .. table.concat(EXTENSIONS, '/'))

				-- search for appropriate alternative path. ("path/part" didn't exist!)
				local newpath = path .. '/' .. part
				local rewritten = false
				for i, ext in ipairs(LANGUAGES) do
					local newpath = newpath .. ext
					for i, ext in ipairs(EXTENSIONS) do
						local newpath = newpath .. ext
						if lighty.stat(docroot .. newpath) then
							-- re-append stripped path elements. (lighty will split this
							-- correctly and treat it as PATH_INFO.)
							newpath = newpath .. origpath:sub(prevpath:len() + 1)

							lighty.env['physical.rel-path'] = newpath
							lighty.env['physical.path'] = docroot .. newpath
							rewritten = true
							break
						end
					end
					if rewritten then
						break
					end
				end
			end

			-- if the search has been failed, lighty will issue 404 correctly.
			break
		end
	end
end

-- vim: ts=4 sw=4


Create a new paste based on this one


Comments: