util.debug: Remove 'white' from boundary style (leave at default colour)
[prosody.git] / util / dataforms.lua
index 5626172e15fc614e62ab99d568b32c4e684b8a9b..d4a1865c806aca39aa2a8dfafea35e440065b747 100644 (file)
@@ -1,6 +1,6 @@
 -- Prosody IM
--- Copyright (C) 2008-2009 Matthew Wild
--- Copyright (C) 2008-2009 Waqas Hussain
+-- Copyright (C) 2008-2010 Matthew Wild
+-- Copyright (C) 2008-2010 Waqas Hussain
 -- 
 -- This project is MIT/X11 licensed. Please see the
 -- COPYING file in the source package for more information.
@@ -8,9 +8,10 @@
 
 local setmetatable = setmetatable;
 local pairs, ipairs = pairs, ipairs;
-local tostring, type = tostring, type;
+local tostring, type, next = tostring, type, next;
 local t_concat = table.concat;
 local st = require "util.stanza";
+local jid_prep = require "util.jid".prep;
 
 module "dataforms"
 
@@ -23,8 +24,8 @@ function new(layout)
        return setmetatable(layout, form_mt);
 end
 
-function form_t.form(layout, data)
-       local form = st.stanza("x", { xmlns = xmlns_forms, type = "form" });
+function form_t.form(layout, data, formtype)
+       local form = st.stanza("x", { xmlns = xmlns_forms, type = formtype or "form" });
        if layout.title then
                form:tag("title"):text(layout.title):up();
        end
@@ -67,9 +68,25 @@ function form_t.form(layout, data)
                                        form:tag("value"):text(line):up();
                                end
                        elseif field_type == "list-single" then
+                               local has_default = false;
                                for _, val in ipairs(value) do
                                        if type(val) == "table" then
                                                form:tag("option", { label = val.label }):tag("value"):text(val.value):up():up();
+                                               if val.default and (not has_default) then
+                                                       form:tag("value"):text(val.value):up();
+                                                       has_default = true;
+                                               end
+                                       else
+                                               form:tag("option", { label= val }):tag("value"):text(tostring(val)):up():up();
+                                       end
+                               end
+                       elseif field_type == "list-multi" then
+                               for _, val in ipairs(value) do
+                                       if type(val) == "table" then
+                                               form:tag("option", { label = val.label }):tag("value"):text(val.value):up():up();
+                                               if val.default then
+                                                       form:tag("value"):text(val.value):up();
+                                               end
                                        else
                                                form:tag("option", { label= val }):tag("value"):text(tostring(val)):up():up();
                                        end
@@ -88,23 +105,43 @@ function form_t.form(layout, data)
 end
 
 local field_readers = {};
+local field_verifiers = {};
 
 function form_t.data(layout, stanza)
        local data = {};
-       
-       for field_tag in stanza:childtags() do
-               local field_type = field_tag.attr.type;
-               
-               local reader = field_readers[field_type];
-               if reader then
-                       data[field_tag.attr.var] = reader(field_tag);
+       local errors = {};
+
+       for _, field in ipairs(layout) do
+               local tag;
+               for field_tag in stanza:childtags() do
+                       if field.name == field_tag.attr.var then
+                               tag = field_tag;
+                               break;
+                       end
                end
-               
+
+               if not tag then
+                       if field.required then
+                               errors[field.name] = "Required value missing";
+                       end
+               else
+                       local reader = field_readers[field.type];
+                       local verifier = field.verifier or field_verifiers[field.type];
+                       if reader then
+                               data[field.name] = reader(tag);
+                               if verifier then
+                                       errors[field.name] = verifier(data[field.name], tag, field.required);
+                               end
+                       end
+               end
+       end
+       if next(errors) then
+               return data, errors;
        end
        return data;
 end
 
-field_readers["text-single"] = 
+field_readers["text-single"] =
        function (field_tag)
                local value = field_tag:child_with_name("value");
                if value then
@@ -112,13 +149,33 @@ field_readers["text-single"] =
                end
        end
 
-field_readers["text-private"] = 
+field_verifiers["text-single"] =
+       function (data, field_tag, required)
+               if ((not data) or (#data == 0)) and required then
+                       return "Required value missing";
+               end
+       end
+
+field_readers["text-private"] =
        field_readers["text-single"];
 
+field_verifiers["text-private"] =
+       field_verifiers["text-single"];
+
 field_readers["jid-single"] =
        field_readers["text-single"];
 
-field_readers["jid-multi"] = 
+field_verifiers["jid-single"] =
+       function (data, field_tag, required)
+               if ((not data) or (#data == 0)) and required then
+                       return "Required value missing";
+               end
+               if not jid_prep(data) then
+                       return "Invalid JID";
+               end
+       end
+
+field_readers["jid-multi"] =
        function (field_tag)
                local result = {};
                for value_tag in field_tag:childtags() do
@@ -129,7 +186,20 @@ field_readers["jid-multi"] =
                return result;
        end
 
-field_readers["text-multi"] = 
+field_verifiers["jid-multi"] =
+       function (data, field_tag, required)
+               if #data == 0 and required then
+                       return "Required value missing";
+               end
+
+               for _, jid in ipairs(data) do
+                       if not jid_prep(jid) then
+                               return "Invalid JID";
+                       end
+               end
+       end
+
+field_readers["text-multi"] =
        function (field_tag)
                local result = {};
                for value_tag in field_tag:childtags() do
@@ -140,10 +210,34 @@ field_readers["text-multi"] =
                return t_concat(result, "\n");
        end
 
+field_verifiers["text-multi"] =
+       field_verifiers["text-single"];
+
 field_readers["list-single"] =
        field_readers["text-single"];
 
-field_readers["boolean"] = 
+field_verifiers["list-single"] =
+       field_verifiers["text-single"];
+
+field_readers["list-multi"] =
+       function (field_tag)
+               local result = {};
+               for value_tag in field_tag:childtags() do
+                       if value_tag.name == "value" then
+                               result[#result+1] = value_tag[1];
+                       end
+               end
+               return result;
+       end
+
+field_verifiers["list-multi"] =
+       function (data, field_tag, required)
+               if #data == 0 and required then
+                       return "Required value missing";
+               end
+       end
+
+field_readers["boolean"] =
        function (field_tag)
                local value = field_tag:child_with_name("value");
                if value then
@@ -152,16 +246,32 @@ field_readers["boolean"] =
                        else
                                return false;
                        end
-               end             
+               end
        end
 
-field_readers["hidden"] = 
+field_verifiers["boolean"] =
+       function (data, field_tag, required)
+               data = field_readers["text-single"](field_tag);
+               if ((not data) or (#data == 0)) and required then
+                       return "Required value missing";
+               end
+               if data ~= "1" and data ~= "true" and data ~= "0" and data ~= "false" then
+                       return "Invalid boolean representation";
+               end
+       end
+
+field_readers["hidden"] =
        function (field_tag)
                local value = field_tag:child_with_name("value");
                if value then
                        return value[1];
                end
        end
+
+field_verifiers["hidden"] =
+       function (data, field_tag, required)
+               return nil;
+       end
        
 return _M;