Sun, 14 Aug 2011 21:34:28 +0200
clix.vcard: Fix debug.
local t_insert, t_concat = table.insert, table.concat; local vCard_dtd = { VERSION = "ignore", --MUST be 3.0, so parsing is redundant FN = "text", N = { values = { "FAMILY", "GIVEN", "MIDDLE", "PREFIX", "SUFFIX", }, }, NICKNAME = "text", PHOTO = { props_verbatim = { ENCODING = { "b" } }, props = { "TYPE" }, value = "BINVAL", --{ "EXTVAL", }, }, BDAY = "text", ADR = { types = { "HOME", "WORK", "POSTAL", "PARCEL", "DOM", "INTL", "PREF", }, values = { "POBOX", "EXTADD", "STREET", "LOCALITY", "REGION", "PCODE", "CTRY", } }, LABEL = { types = { "HOME", "WORK", "POSTAL", "PARCEL", "DOM", "INTL", "PREF", }, value = "LINE", }, TEL = { types = { "HOME", "WORK", "VOICE", "FAX", "PAGER", "MSG", "CELL", "VIDEO", "BBS", "MODEM", "ISDN", "PCS", "PREF", }, value = "NUMBER", }, EMAIL = { types = { "HOME", "WORK", "INTERNET", "PREF", "X400", }, value = "USERID", }, JABBERID = "text", MAILER = "text", TZ = "text", GEO = { values = { "LAT", "LON", }, }, TITLE = "text", ROLE = "text", LOGO = "copy of PHOTO", AGENT = "text", ORG = { values = { behaviour = "repeat-last", "ORGNAME", "ORGUNIT", } }, CATEGORIES = { values = "KEYWORD", }, NOTE = "text", PRODID = "text", REV = "text", SORTSTRING = "text", SOUND = "copy of PHOTO", UID = "text", URL = "text", CLASS = { names = { -- The item.name is the value if it's one of these. "PUBLIC", "PRIVATE", "CONFIDENTIAL", }, }, KEY = { props = { "TYPE" }, value = "CRED", }, DESC = "text", }; vCard_dtd.LOGO = vCard_dtd.PHOTO; vCard_dtd.SOUND = vCard_dtd.PHOTO; --TODO BINVAL OR EXTVAL local function vCard_esc(s) return s:gsub("[,;\\]", "\\%1"):gsub("\n","\\n"); end local function vCard_prop(item) local prop_name = item.name; local prop_def = vCard_dtd[prop_name]; if not prop_def then return nil end local value, params = "", {}; if prop_def == "text" then value = item:get_text(); elseif type(prop_def) == "table" then if prop_def.value then --single item value = item:get_child_text(prop_def.value) or ""; elseif prop_def.values then --array local value_names = prop_def.values; value = {}; for i=1,#value_names do t_insert(value, item:get_child_text(value_names[i]) or ""); --TODO ORG with >1 sub items end elseif prop_def.names then local names = prop_def.names; for i=1,#names do if item:get_child(names[i]) then value = names[i]; break; end end end if prop_def.props_verbatim then for k,v in pairs(prop_def.props_verbatim) do params[k] = v; end end if prop_def.types then local types = prop_def.types; params.TYPE = {}; for i=1,#types do if item:get_child(types[i]) then t_insert(params.TYPE, types[i]:lower()); end end if #params.TYPE == 0 then params.TYPE = nil; end end if prop_def.props then local props = prop_def.props; for i=1,#props do local prop = props[i] local p = item:get_child_text(prop); if p then params[prop] = params[prop] or {}; t_insert(params[prop], p); end end end else return nil end if type(value) == "table" then for i=1,#value do value[i]=vCard_esc(value[i]); end value = t_concat(value, ";"); else value = vCard_esc(value); end if next(params) then local sparams = ""; for k,v in pairs(params) do sparams = sparams .. (";%s=%s"):format(k, t_concat(v,",")); end params = sparams; else params = ""; end --TODO: Split long lines return ("%s%s:%s"):format(item.name, params, value); end return function (opts, arg) if opts.short_help then print("Fetch someones vCard"); return; end if (#arg == 0 or opts.help) then return 0; end local function on_connect(conn) conn:add_plugin("vcard"); conn:get_vcard(arg[1], function(reply) local vCard = reply:get_child("vCard", "vcard-temp"); if vCard then print("BEGIN:VCARD"); print("VERSION:3.0"); for i = 1,#vCard do local item = vCard[i]; if item.name then local s = vCard_prop(item); if s then print(s); else conn:debug("Unhandled vCard field: %s", item.name); end end end print("END:VCARD"); end verse.quit(); end); end clix_connect(opts, on_connect); end