webmcp
changeset 1:985024b16520 v1.0.1
Version 1.0.1
New feature: JSON requests
Changes in ui.paginate: Current page setting is directly fetched from CGI params, instead of view params
Changed behavior of load methods of atom library to accept nil as input
Bugfixes in mondelefant_atom_connector timestamp(tz) loaders
Added global constant _WEBMCP_VERSION containing a version string
New feature: JSON requests
Changes in ui.paginate: Current page setting is directly fetched from CGI params, instead of view params
Changed behavior of load methods of atom library to accept nil as input
Bugfixes in mondelefant_atom_connector timestamp(tz) loaders
Added global constant _WEBMCP_VERSION containing a version string
author | jbe |
---|---|
date | Tue Nov 17 12:00:00 2009 +0100 (2009-11-17) |
parents | 9fdfb27f8e67 |
children | 72860d232f32 |
files | LICENSE doc/autodoc-header.htmlpart framework/cgi-bin/webmcp.lua framework/env/encode/json.lua framework/env/request/__init.lua framework/env/request/get_json_request_slots.lua framework/env/request/is_ajax.lua framework/env/request/set_allowed_json_request_slots.lua framework/env/ui/paginate.lua libraries/atom/atom.lua libraries/mondelefant/mondelefant_atom_connector.lua |
line diff
1.1 --- a/LICENSE Sun Oct 25 12:00:00 2009 +0100 1.2 +++ b/LICENSE Tue Nov 17 12:00:00 2009 +0100 1.3 @@ -1,4 +1,4 @@ 1.4 -Copyright (c) 2009 Public Software Group e. V., Berlin 1.5 +Copyright (c) 2009 Public Software Group e. V., Berlin, Germany 1.6 1.7 Permission is hereby granted, free of charge, to any person obtaining a 1.8 copy of this software and associated documentation files (the "Software"),
2.1 --- a/doc/autodoc-header.htmlpart Sun Oct 25 12:00:00 2009 +0100 2.2 +++ b/doc/autodoc-header.htmlpart Tue Nov 17 12:00:00 2009 +0100 2.3 @@ -55,10 +55,10 @@ 2.4 color: #505050; 2.5 } 2.6 </style> 2.7 - <title>WebMCP 1.0.0 Documentation</title> 2.8 + <title>WebMCP 1.0.1 Documentation</title> 2.9 </head> 2.10 <body> 2.11 - <h1>WebMCP 1.0.0 Documentation</h1> 2.12 + <h1>WebMCP 1.0.1 Documentation</h1> 2.13 <p> 2.14 WebMCP is a completely new web development framework, and has not been extensively tested yet. The API might change at any time, but in future releases there will be a list of all changes, which break downward compatibility. 2.15 </p>
3.1 --- a/framework/cgi-bin/webmcp.lua Sun Oct 25 12:00:00 2009 +0100 3.2 +++ b/framework/cgi-bin/webmcp.lua Tue Nov 17 12:00:00 2009 +0100 3.3 @@ -1,5 +1,7 @@ 3.4 #!/usr/bin/env lua 3.5 3.6 +_WEBMCP_VERSION = "1.0.1" 3.7 + 3.8 -- include "../lib/" in search path for libraries 3.9 do 3.10 package.path = '../lib/?.lua;' .. package.path 3.11 @@ -430,16 +432,14 @@ 3.12 cgi.set_status(http_status) 3.13 end 3.14 3.15 - -- ajax 3.16 - if request.is_ajax() then 3.17 - cgi.set_content_type('text/html') 3.18 - for i, slot_ident in ipairs{'main', 'actions', 'title', 'topnav', 'sidenav', 'debug', 'notice', 'warning', 'error'} do 3.19 - local html = slot.get_content(slot_ident) 3.20 - if html then 3.21 - cgi.send_data("document.getElementById('" .. slot_ident .. "').innerHTML=" .. encode.json(html or ' ') .. ";") 3.22 - end 3.23 + local json_request_slots = request.get_json_request_slots() 3.24 + if json_request_slots then 3.25 + cgi.set_content_type('application/json') 3.26 + local data = {} 3.27 + for idx, slot_ident in ipairs(json_request_slots) do 3.28 + data[slot_ident] = slot.get_content(slot_ident) 3.29 end 3.30 - -- oder ganz herkoemmlich 3.31 + cgi.send_data(encode.json(data)) 3.32 else 3.33 cgi.set_content_type(slot.get_content_type()) 3.34 cgi.send_data(slot.render_layout())
4.1 --- a/framework/env/encode/json.lua Sun Oct 25 12:00:00 2009 +0100 4.2 +++ b/framework/env/encode/json.lua Tue Nov 17 12:00:00 2009 +0100 4.3 @@ -5,9 +5,12 @@ 4.4 ) 4.5 4.6 This function encodes any native datatype or atom in JavaScript object notation (JSON). 4.7 +TODO: can't distinguish unambiguously between empty object and empty list! 4.8 4.9 --]]-- 4.10 4.11 +-- TODO: check if numeric representations are JSON compatible 4.12 + 4.13 function encode.json(obj) 4.14 if obj == nil then 4.15 return "null"; 4.16 @@ -15,20 +18,49 @@ 4.17 return tostring(obj) 4.18 elseif atom.has_type(obj, atom.number) then 4.19 return tostring(obj) 4.20 + elseif type(obj) == "table" then 4.21 + local parts = {} 4.22 + local first = true 4.23 + if #obj > 0 then 4.24 + parts[#parts+1] = "[" 4.25 + for idx, value in ipairs(obj) do 4.26 + if first then 4.27 + first = false 4.28 + else 4.29 + parts[#parts+1] = "," 4.30 + end 4.31 + parts[#parts+1] = tostring(value) 4.32 + end 4.33 + parts[#parts+1] = "]" 4.34 + else 4.35 + parts[#parts+1] = "{" 4.36 + for key, value in pairs(obj) do 4.37 + if first then 4.38 + first = false 4.39 + else 4.40 + parts[#parts+1] = "," 4.41 + end 4.42 + parts[#parts+1] = encode.json(key) 4.43 + parts[#parts+1] = ":" 4.44 + parts[#parts+1] = encode.json(value) 4.45 + end 4.46 + parts[#parts+1] = "}" 4.47 + end 4.48 + return table.concat(parts) 4.49 else 4.50 return 4.51 - "'" .. 4.52 + '"' .. 4.53 string.gsub(atom.dump(obj), ".", 4.54 function (char) 4.55 - if char == "\r" then return "\\r" end 4.56 - if char == "\n" then return "\\n" end 4.57 - if char == "\\" then return "\\\\" end 4.58 - if char == "'" then return "\\'" end 4.59 - if char == "/" then return "\\/" end -- allowed according to RFC4627, needed for </script> 4.60 + if char == '\r' then return '\\r' end 4.61 + if char == '\n' then return '\\n' end 4.62 + if char == '\\' then return '\\\\' end 4.63 + if char == '"' then return '\\"' end 4.64 + if char == '/' then return '\\/' end -- allowed according to RFC4627, needed for </script> 4.65 local byte = string.byte(char) 4.66 if byte < 32 then return string.format("\\u%04x", byte) end 4.67 end 4.68 ) .. 4.69 - "'" 4.70 + '"' 4.71 end 4.72 end
5.1 --- a/framework/env/request/__init.lua Sun Oct 25 12:00:00 2009 +0100 5.2 +++ b/framework/env/request/__init.lua Tue Nov 17 12:00:00 2009 +0100 5.3 @@ -7,6 +7,7 @@ 5.4 request._force_absolute_baseurl = false 5.5 request._perm_params = {} 5.6 request._csrf_secret = nil 5.7 +request._json_requests_allowed = false 5.8 5.9 local depth 5.10 if cgi then -- if-clause to support interactive mode
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/framework/env/request/get_json_request_slots.lua Tue Nov 17 12:00:00 2009 +0100 6.3 @@ -0,0 +1,15 @@ 6.4 +--[[-- 6.5 +slot_idents = -- list of names of slots to be returned as JSON data 6.6 +request.get_json_request_slots() 6.7 + 6.8 +If the current request is no JSON request, this function returns nil, otherwise a list of names of all slots to be returned in JSON format. This function also throws an error, if JSON data was requested, but request.set_allowed_json_request_slots(...) has not been called. 6.9 + 6.10 +--]]-- 6.11 + 6.12 +function request.get_json_request_slots(slot_idents) 6.13 + local slot_idents = cgi.params["_webmcp_json_slots[]"] 6.14 + if slot_idents and not request._json_requests_allowed then 6.15 + error("JSON requests have not been allowed using request.set_allowed_json_request_slots(...).") 6.16 + end 6.17 + return slot_idents 6.18 +end
7.1 --- a/framework/env/request/is_ajax.lua Sun Oct 25 12:00:00 2009 +0100 7.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 7.3 @@ -1,3 +0,0 @@ 7.4 -function request.is_ajax() 7.5 - return cgi.params['ajax'] == '1' 7.6 -end 7.7 \ No newline at end of file
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/framework/env/request/set_allowed_json_request_slots.lua Tue Nov 17 12:00:00 2009 +0100 8.3 @@ -0,0 +1,23 @@ 8.4 +--[[-- 8.5 +request.set_allowed_json_request_slots( 8.6 + slot_idents -- list of names of slots which can be requested in JSON format 8.7 +) 8.8 + 8.9 +This function enables JSON requests. The given list of names of slots selects, which slots may be requestd in JSON format (without layout). 8.10 + 8.11 +--]]-- 8.12 + 8.13 +function request.set_allowed_json_request_slots(slot_idents) 8.14 + local hash = {} 8.15 + for idx, slot_ident in ipairs(slot_idents) do 8.16 + hash[slot_ident] = true 8.17 + end 8.18 + if cgi.params["_webmcp_json_slots[]"] then 8.19 + for idx, slot_ident in ipairs(cgi.params["_webmcp_json_slots[]"]) do 8.20 + if not hash[slot_ident] then 8.21 + error('Requesting slot "' .. slot_ident .. '" is forbidden.') 8.22 + end 8.23 + end 8.24 + end 8.25 + request._json_requests_allowed = true 8.26 +end
9.1 --- a/framework/env/ui/paginate.lua Sun Oct 25 12:00:00 2009 +0100 9.2 +++ b/framework/env/ui/paginate.lua Tue Nov 17 12:00:00 2009 +0100 9.3 @@ -3,12 +3,14 @@ 9.4 selector = selector, -- a selector for items from the database 9.5 per_page = per_page, -- items per page, defaults to 10 9.6 name = name, -- name of the CGI get variable, defaults to "page" 9.7 + page = page, -- directly specify a page, and ignore 'name' parameter 9.8 content = function() 9.9 ... -- code block which should be encapsulated with page selection links 9.10 end 9.11 } 9.12 9.13 -This function preceeds and appends the output of the given 'content' function with page selection links. The passed selector will be modified to show only a limited amount ('per_page') of items. 9.14 +This function preceeds and appends the output of the given 'content' function with page selection links. The passed selector will be modified to show only a limited amount ('per_page') of items. The currently displayed page will be determined directly by cgi.params, and not via the param.get(...) function, in order to pass page selections automatically to sub-views. 9.15 + 9.16 --]]-- 9.17 9.18 function ui.paginate(args) 9.19 @@ -22,7 +24,7 @@ 9.20 count_selector:single_object_mode() 9.21 local count = count_selector:exec().count 9.22 local page_count = math.floor((count - 1) / per_page) + 1 9.23 - local current_page = param.get(name, atom.integer) or 1 9.24 + local current_page = atom.integer:load(cgi.params[name]) or 1 9.25 selector:limit(per_page) 9.26 selector:offset((current_page - 1) * per_page) 9.27 local id = param.get_id_cgi()
10.1 --- a/libraries/atom/atom.lua Sun Oct 25 12:00:00 2009 +0100 10.2 +++ b/libraries/atom/atom.lua Tue Nov 17 12:00:00 2009 +0100 10.3 @@ -212,10 +212,10 @@ 10.4 10.5 --]]-- 10.6 function boolean:load(str) 10.7 - if type(str) ~= "string" then 10.8 + if str == nil or str == "" then 10.9 + return nil 10.10 + elseif type(str) ~= "string" then 10.11 error("String expected") 10.12 - elseif str == "" then 10.13 - return nil 10.14 elseif string.find(str, "^[TtYy1]") then 10.15 return true 10.16 elseif string.find(str, "^[FfNn0]") then 10.17 @@ -244,7 +244,9 @@ 10.18 10.19 --]]-- 10.20 function _M.string:load(str) 10.21 - if type(str) ~= "string" then 10.22 + if str == nil then 10.23 + return nil 10.24 + elseif type(str) ~= "string" then 10.25 error("String expected") 10.26 else 10.27 return str 10.28 @@ -270,10 +272,10 @@ 10.29 10.30 --]]-- 10.31 function integer:load(str) 10.32 - if type(str) ~= "string" then 10.33 + if str == nil or str == "" then 10.34 + return nil 10.35 + elseif type(str) ~= "string" then 10.36 error("String expected") 10.37 - elseif str == "" then 10.38 - return nil 10.39 else 10.40 local num = tonumber(str) 10.41 if is_integer(num) then return num else return not_a_number end 10.42 @@ -308,10 +310,10 @@ 10.43 10.44 --]]-- 10.45 function number:load(str) 10.46 - if type(str) ~= "string" then 10.47 + if str == nil or str == "" then 10.48 + return nil 10.49 + elseif type(str) ~= "string" then 10.50 error("String expected") 10.51 - elseif str == "" then 10.52 - return nil 10.53 else 10.54 return tonumber(str) or not_a_number 10.55 end 10.56 @@ -463,8 +465,10 @@ 10.57 10.58 --]]-- 10.59 function fraction:load(str) 10.60 - if str == "" then 10.61 + if str == nil or str == "" then 10.62 return nil 10.63 + elseif type(str) ~= "string" then 10.64 + error("String expected") 10.65 else 10.66 local sign, int = string.match(str, "^(%-?)([0-9]+)$") 10.67 if sign == "" then return fraction:new(tonumber(int)) 10.68 @@ -877,8 +881,10 @@ 10.69 10.70 --]]-- 10.71 function date:load(str) 10.72 - if str == "" then 10.73 + if str == nil or str == "" then 10.74 return nil 10.75 + elseif type(str) ~= "string" then 10.76 + error("String expected") 10.77 else 10.78 local year, month, day = string.match( 10.79 str, "^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$" 10.80 @@ -1197,8 +1203,10 @@ 10.81 10.82 --]]-- 10.83 function timestamp:load(str) 10.84 - if str == "" then 10.85 + if str == nil or str == "" then 10.86 return nil 10.87 + elseif type(str) ~= "string" then 10.88 + error("String expected") 10.89 else 10.90 local year, month, day, hour, minute, second = string.match( 10.91 str, 10.92 @@ -1418,8 +1426,10 @@ 10.93 10.94 --]]-- 10.95 function time:load(str) 10.96 - if str == "" then 10.97 + if str == nil or str == "" then 10.98 return nil 10.99 + elseif type(str) ~= "string" then 10.100 + error("String expected") 10.101 else 10.102 local hour, minute, second = string.match( 10.103 str,
11.1 --- a/libraries/mondelefant/mondelefant_atom_connector.lua Sun Oct 25 12:00:00 2009 +0100 11.2 +++ b/libraries/mondelefant/mondelefant_atom_connector.lua Tue Nov 17 12:00:00 2009 +0100 11.3 @@ -100,12 +100,15 @@ 11.4 output_converters.date = function(str) return atom.date:load(str) end 11.5 11.6 local timestamp_loader_func = function(str) 11.7 - local hour, minute, second = string.match( 11.8 + local year, month, day, hour, minute, second = string.match( 11.9 str, 11.10 - "^([0-9]?[0-9]):([0-9][0-9]):([0-9][0-9])" 11.11 + "^([0-9][0-9][0-9][0-9])%-([0-9][0-9])%-([0-9][0-9]) ([0-9]?[0-9]):([0-9][0-9]):([0-9][0-9])" 11.12 ) 11.13 - if hour then 11.14 + if year then 11.15 return atom.timestamp{ 11.16 + year = tonumber(year), 11.17 + month = tonumber(month), 11.18 + day = tonumber(day), 11.19 hour = tonumber(hour), 11.20 minute = tonumber(minute), 11.21 second = tonumber(second) 11.22 @@ -118,15 +121,12 @@ 11.23 output_converters.timestamptz = timestamp_loader_func 11.24 11.25 local time_loader_func = function(str) 11.26 - local year, month, day, hour, minute, second = string.match( 11.27 + local hour, minute, second = string.match( 11.28 str, 11.29 - "^([0-9][0-9][0-9][0-9])%-([0-9][0-9])%-([0-9][0-9]) ([0-9]?[0-9]):([0-9][0-9]):([0-9][0-9])" 11.30 + "^([0-9]?[0-9]):([0-9][0-9]):([0-9][0-9])" 11.31 ) 11.32 - if year then 11.33 + if hour then 11.34 return atom.time{ 11.35 - year = tonumber(year), 11.36 - month = tonumber(month), 11.37 - day = tonumber(day), 11.38 hour = tonumber(hour), 11.39 minute = tonumber(minute), 11.40 second = tonumber(second)