comparison mod_vjud/mod_vjud.lua @ 927:a9dfa7232d88

Merge
author Matthew Wild <mwild1@gmail.com>
date Tue, 12 Mar 2013 12:10:25 +0000
parents 4939788a47ea
children b1a92a87309c
comparison
equal deleted inserted replaced
926:f88381a39c56 927:a9dfa7232d88
4 local usermanager = require "core.usermanager"; 4 local usermanager = require "core.usermanager";
5 local dataforms_new = require "util.dataforms".new; 5 local dataforms_new = require "util.dataforms".new;
6 local jid_split = require "util.jid".prepped_split; 6 local jid_split = require "util.jid".prepped_split;
7 local vcard = module:require "vcard"; 7 local vcard = module:require "vcard";
8 local rawget, rawset = rawget, rawset; 8 local rawget, rawset = rawget, rawset;
9 local s_lower = string.lower;
10 local s_find = string.find;
9 11
10 local st = require "util.stanza"; 12 local st = require "util.stanza";
11 local template = require "util.template"; 13 local template = require "util.template";
12 14
13 local get_reply = template[[ 15 local get_reply = template[[
26 <nick>{nick}</nick> 28 <nick>{nick}</nick>
27 <email>{email}</email> 29 <email>{email}</email>
28 </item> 30 </item>
29 ]]; 31 ]];
30 32
33 local search_mode = module:get_option_string("vjud_mode", "opt-in");
34 local allow_remote = module:get_option_boolean("allow_remote_searches", search_mode ~= "all");
31 local base_host = module:get_option_string("vjud_search_domain", 35 local base_host = module:get_option_string("vjud_search_domain",
32 module:get_host_type() == "component" 36 module:get_host_type() == "component"
33 and module.host:gsub("^[^.]+%.","") 37 and module.host:gsub("^[^.]+%.","")
34 or module.host); 38 or module.host);
35 39
36 module:depends"disco"; 40 module:depends"disco";
37 module:add_feature("jabber:iq:search"); 41 module:add_feature("jabber:iq:search");
38 42
39 local opted_in;
40 function module.load()
41 opted_in = dm_load(nil, module.host, "user_index") or {};
42 end
43 function module.unload()
44 dm_store(nil, module.host, "user_index", opted_in);
45 end
46
47 local opt_in_layout = dataforms_new{
48 title = "Search settings";
49 instructions = "Do you want to appear in search results?";
50 {
51 name = "searchable",
52 label = "Appear in search results?",
53 type = "boolean",
54 },
55 };
56 local vCard_mt = { 43 local vCard_mt = {
57 __index = function(t, k) 44 __index = function(t, k)
58 if type(k) ~= "string" then return nil end 45 if type(k) ~= "string" then return nil end
59 for i=1,#t do 46 for i=1,#t do
60 local t_i = rawget(t, i); 47 local t_i = rawget(t, i);
75 end 62 end
76 end 63 end
77 64
78 local at_host = "@"..base_host; 65 local at_host = "@"..base_host;
79 66
67 local users; -- The user iterator
68
80 module:hook("iq/host/jabber:iq:search:query", function(event) 69 module:hook("iq/host/jabber:iq:search:query", function(event)
81 local origin, stanza = event.origin, event.stanza; 70 local origin, stanza = event.origin, event.stanza;
71
72 if not (allow_remote or origin.type == "c2s") then
73 origin.send(st.error_reply(stanza, "cancel", "not-allowed"))
74 return true;
75 end
82 76
83 if stanza.attr.type == "get" then 77 if stanza.attr.type == "get" then
84 origin.send(st.reply(stanza):add_child(get_reply)); 78 origin.send(st.reply(stanza):add_child(get_reply));
85 else -- type == "set" 79 else -- type == "set"
86 local query = stanza.tags[1]; 80 local query = stanza.tags[1];
87 local first, last, nick, email = 81 local first, last, nick, email =
88 (query:get_child_text"first" or false), 82 s_lower(query:get_child_text"first" or ""),
89 (query:get_child_text"last" or false), 83 s_lower(query:get_child_text"last" or ""),
90 (query:get_child_text"nick" or false), 84 s_lower(query:get_child_text"nick" or ""),
91 (query:get_child_text"email" or false); 85 s_lower(query:get_child_text"email" or "");
92 86
87 first = #first >= 2 and first;
88 last = #last >= 2 and last;
89 nick = #nick >= 2 and nick;
90 email = #email >= 2 and email;
93 if not ( first or last or nick or email ) then 91 if not ( first or last or nick or email ) then
94 origin.send(st.error_reply(stanza, "modify", "not-acceptable", "All fields were empty")); 92 origin.send(st.error_reply(stanza, "modify", "not-acceptable", "All fields were empty or too short"));
95 return true; 93 return true;
96 end 94 end
97 95
98 local reply = st.reply(stanza):query("jabber:iq:search"); 96 local reply = st.reply(stanza):query("jabber:iq:search");
99 97
108 nick = vCard.NICKNAME and vCard.NICKNAME[1] or username; 106 nick = vCard.NICKNAME and vCard.NICKNAME[1] or username;
109 email = vCard.EMAIL and vCard.EMAIL[1] or nil; 107 email = vCard.EMAIL and vCard.EMAIL[1] or nil;
110 }); 108 });
111 end 109 end
112 else 110 else
113 for username in pairs(opted_in) do 111 for username in users() do
114 local vCard = get_user_vcard(username); 112 local vCard = get_user_vcard(username);
115 if vCard and ( 113 if vCard
116 (vCard.N and vCard.N[2] == first) or 114 and ((first and vCard.N and s_find(s_lower(vCard.N[2]), first, nil, true))
117 (vCard.N and vCard.N[1] == last) or 115 or (last and vCard.N and s_find(s_lower(vCard.N[1]), last, nil, true))
118 (vCard.NICKNAME and vCard.NICKNAME[1] == nick) or 116 or (nick and vCard.NICKNAME and s_find(s_lower(vCard.NICKNAME[1]), nick, nil, true))
119 (vCard.EMAIL and vCard.EMAIL[1] == email)) then 117 or (email and vCard.EMAIL and s_find(s_lower(vCard.EMAIL[1]), email, nil, true))) then
120 reply:add_child(item_template.apply{ 118 reply:add_child(item_template.apply{
121 jid = username..at_host; 119 jid = username..at_host;
122 first = vCard.N and vCard.N[2] or nil; 120 first = vCard.N and vCard.N[2] or nil;
123 last = vCard.N and vCard.N[1] or nil; 121 last = vCard.N and vCard.N[1] or nil;
124 nick = vCard.NICKNAME and vCard.NICKNAME[1] or username; 122 nick = vCard.NICKNAME and vCard.NICKNAME[1] or username;
130 origin.send(reply); 128 origin.send(reply);
131 end 129 end
132 return true; 130 return true;
133 end); 131 end);
134 132
135 local function opt_in_handler(self, data, state) 133 if search_mode == "all" then
136 local username, hostname = jid_split(data.from); 134 function users()
137 if state then -- the second return value 135 return usermanager.users(base_host);
138 if data.action == "cancel" then 136 end
139 return { status = "canceled" }; 137 else -- if "opt-in", default
138 local opted_in;
139 function module.load()
140 opted_in = dm_load(nil, module.host, "user_index") or {};
141 end
142 function module.unload()
143 dm_store(nil, module.host, "user_index", opted_in);
144 end
145 function users()
146 return pairs(opted_in);
147 end
148 local opt_in_layout = dataforms_new{
149 title = "Search settings";
150 instructions = "Do you want to appear in search results?";
151 {
152 name = "searchable",
153 label = "Appear in search results?",
154 type = "boolean",
155 },
156 };
157 local function opt_in_handler(self, data, state)
158 local username, hostname = jid_split(data.from);
159 if state then -- the second return value
160 if data.action == "cancel" then
161 return { status = "canceled" };
162 end
163
164 if not username or not hostname or hostname ~= base_host then
165 return { status = "error", error = { type = "cancel",
166 condition = "forbidden", message = "Invalid user or hostname." } };
167 end
168
169 local fields = opt_in_layout:data(data.form);
170 opted_in[username] = fields.searchable or nil
171
172 return { status = "completed" }
173 else -- No state, send the form.
174 return { status = "executing", actions = { "complete" },
175 form = { layout = opt_in_layout, values = { searchable = opted_in[username] } } }, true;
140 end 176 end
177 end
141 178
142 if not username or not hostname or hostname ~= base_host then 179 local adhoc_new = module:require "adhoc".new;
143 return { status = "error", error = { type = "cancel", 180 local adhoc_vjudsetup = adhoc_new("Search settings", "vjudsetup", opt_in_handler);--, "self");-- and nil);
144 condition = "forbidden", message = "Invalid user or hostname." } }; 181 module:depends"adhoc";
145 end 182 module:provides("adhoc", adhoc_vjudsetup);
146 183
147 local fields = opt_in_layout:data(data.form);
148 opted_in[username] = fields.searchable or nil
149
150 return { status = "completed" }
151 else -- No state, send the form.
152 return { status = "executing", actions = { "complete" },
153 form = { layout = opt_in_layout, values = { searchable = opted_in[username] } } }, true;
154 end
155 end 184 end
156
157 local adhoc_new = module:require "adhoc".new;
158 local adhoc_vjudsetup = adhoc_new("Search settings", "vjudsetup", opt_in_handler);--, "self");-- and nil);
159 module:depends"adhoc";
160 module:provides("adhoc", adhoc_vjudsetup);
161