/[smecontribs]/rpms/ejabberd/contribs7/ejabberd-captcha.patch
ViewVC logotype

Annotation of /rpms/ejabberd/contribs7/ejabberd-captcha.patch

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (hide annotations) (download)
Mon Aug 24 18:19:21 2009 UTC (15 years, 3 months ago) by slords
Branch: MAIN
CVS Tags: ejabberd-2_0_5-2_el4_sme, HEAD
New package import

1 slords 1.1 Binary files ejabberd-2.0.4/src/.DS_Store and ejabberd-2.0.4-new/src/.DS_Store differ
2     diff -urN ejabberd-2.0.4/src/ejabberd_captcha.erl ejabberd-2.0.4-new/src/ejabberd_captcha.erl
3     --- ejabberd-2.0.4/src/ejabberd_captcha.erl 1970-01-01 01:00:00.000000000 +0100
4     +++ ejabberd-2.0.4-new/src/ejabberd_captcha.erl 2009-03-14 07:27:05.000000000 +0100
5     @@ -0,0 +1,312 @@
6     +%%%-------------------------------------------------------------------
7     +%%% File : ejabberd_captcha.erl
8     +%%% Author : Evgeniy Khramtsov <xramtsov@gmail.com>
9     +%%% Description : CAPTCHA processing.
10     +%%%
11     +%%% Created : 26 Apr 2008 by Evgeniy Khramtsov <xramtsov@gmail.com>
12     +%%%-------------------------------------------------------------------
13     +-module(ejabberd_captcha).
14     +
15     +-behaviour(gen_server).
16     +
17     +%% API
18     +-export([start_link/0]).
19     +
20     +%% gen_server callbacks
21     +-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
22     + terminate/2, code_change/3]).
23     +
24     +-export([create_captcha/6, process_reply/1, process/2]).
25     +
26     +-include("jlib.hrl").
27     +-include("ejabberd.hrl").
28     +-include("web/ejabberd_http.hrl").
29     +
30     +-define(VFIELD(Type, Var, Value),
31     + {xmlelement, "field", [{"type", Type}, {"var", Var}],
32     + [{xmlelement, "value", [], [Value]}]}).
33     +
34     +-define(CAPTCHA_BODY(Lang, Room, URL),
35     + translate:translate(Lang, "Your messages to ") ++ Room
36     + ++ translate:translate(Lang, " are being blocked. To unblock them, visit ")
37     + ++ URL).
38     +
39     +-define(CAPTCHA_TEXT(Lang), translate:translate(Lang, "Enter the text you see")).
40     +-define(CAPTCHA_LIFETIME, 120000). % two minutes
41     +
42     +-record(state, {}).
43     +-record(captcha, {id, pid, key, tref, args}).
44     +
45     +-define(T(S),
46     + case catch mnesia:transaction(fun() -> S end) of
47     + {atomic, Res} ->
48     + Res;
49     + {_, Reason} ->
50     + ?ERROR_MSG("mnesia transaction failed: ~p", [Reason]),
51     + {error, Reason}
52     + end).
53     +
54     +%%====================================================================
55     +%% API
56     +%%====================================================================
57     +%%--------------------------------------------------------------------
58     +%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
59     +%% Description: Starts the server
60     +%%--------------------------------------------------------------------
61     +start_link() ->
62     + gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
63     +
64     +create_captcha(Id, SID, From, To, Lang, Args)
65     + when is_list(Id), is_list(Lang), is_list(SID),
66     + is_record(From, jid), is_record(To, jid) ->
67     + case create_image() of
68     + {ok, Type, Key, Image} ->
69     + B64Image = jlib:encode_base64(binary_to_list(Image)),
70     + JID = jlib:jid_to_string(From),
71     + CID = "sha1+" ++ sha:sha(Image) ++ "@bob.xmpp.org",
72     + Data = {xmlelement, "data",
73     + [{"xmlns", ?NS_BOB}, {"cid", CID},
74     + {"max-age", "0"}, {"type", Type}],
75     + [{xmlcdata, B64Image}]},
76     + Captcha =
77     + {xmlelement, "captcha", [{"xmlns", ?NS_CAPTCHA}],
78     + [{xmlelement, "x", [{"xmlns", ?NS_XDATA}, {"type", "form"}],
79     + [?VFIELD("hidden", "FORM_TYPE", {xmlcdata, ?NS_CAPTCHA}),
80     + ?VFIELD("hidden", "from", {xmlcdata, jlib:jid_to_string(To)}),
81     + ?VFIELD("hidden", "challenge", {xmlcdata, Id}),
82     + ?VFIELD("hidden", "sid", {xmlcdata, SID}),
83     + {xmlelement, "field", [{"var", "ocr"}],
84     + [{xmlelement, "media", [{"xmlns", ?NS_MEDIA}],
85     + [{xmlelement, "uri", [{"type", Type}],
86     + [{xmlcdata, "cid:" ++ CID}]}]}]}]}]},
87     + Body = {xmlelement, "body", [],
88     + [{xmlcdata, ?CAPTCHA_BODY(Lang, JID, get_url(Id))}]},
89     + OOB = {xmlelement, "x", [{"xmlns", ?NS_OOB}],
90     + [{xmlelement, "url", [], [{xmlcdata, get_url(Id)}]}]},
91     + Tref = erlang:send_after(?CAPTCHA_LIFETIME, ?MODULE, {remove_id, Id}),
92     + ?T(mnesia:write(#captcha{id=Id, pid=self(), key=Key,
93     + tref=Tref, args=Args})),
94     + {ok, [Body, OOB, Captcha, Data]};
95     + _Err ->
96     + error
97     + end.
98     +
99     +process_reply({xmlelement, "captcha", _, _} = El) ->
100     + case xml:get_subtag(El, "x") of
101     + false ->
102     + {error, malformed};
103     + Xdata ->
104     + Fields = jlib:parse_xdata_submit(Xdata),
105     + [Id | _] = proplists:get_value("challenge", Fields, [none]),
106     + [OCR | _] = proplists:get_value("ocr", Fields, [none]),
107     + ?T(case mnesia:read(captcha, Id, write) of
108     + [#captcha{pid=Pid, args=Args, key=Key, tref=Tref}] ->
109     + mnesia:delete({captcha, Id}),
110     + erlang:cancel_timer(Tref),
111     + if OCR == Key ->
112     + Pid ! {captcha_succeed, Args},
113     + ok;
114     + true ->
115     + Pid ! {captcha_failed, Args},
116     + {error, bad_match}
117     + end;
118     + _ ->
119     + {error, not_found}
120     + end)
121     + end;
122     +process_reply(_) ->
123     + {error, malformed}.
124     +
125     +process(_Handlers, #request{method='GET', lang=Lang, path=[_, Id]}) ->
126     + case mnesia:dirty_read(captcha, Id) of
127     + [#captcha{}] ->
128     + Form =
129     + {xmlelement, "div", [{"align", "center"}],
130     + [{xmlelement, "form", [{"action", get_url(Id)},
131     + {"name", "captcha"},
132     + {"method", "POST"}],
133     + [{xmlelement, "img", [{"src", get_url(Id ++ "/image")}], []},
134     + {xmlelement, "br", [], []},
135     + {xmlcdata, ?CAPTCHA_TEXT(Lang)},
136     + {xmlelement, "br", [], []},
137     + {xmlelement, "input", [{"type", "text"},
138     + {"name", "key"},
139     + {"size", "10"}], []},
140     + {xmlelement, "br", [], []},
141     + {xmlelement, "input", [{"type", "submit"},
142     + {"name", "enter"},
143     + {"value", "OK"}], []}]}]},
144     + ejabberd_web:make_xhtml([Form]);
145     + _ ->
146     + ejabberd_web:error(not_found)
147     + end;
148     +
149     +process(_Handlers, #request{method='GET', path=[_, Id, "image"]}) ->
150     + case mnesia:dirty_read(captcha, Id) of
151     + [#captcha{key=Key}] ->
152     + case create_image(Key) of
153     + {ok, Type, _, Img} ->
154     + {200,
155     + [{"Content-Type", Type},
156     + {"Cache-Control", "no-cache"},
157     + {"Last-Modified", httpd_util:rfc1123_date()}],
158     + Img};
159     + _ ->
160     + ejabberd_web:error(not_found)
161     + end;
162     + _ ->
163     + ejabberd_web:error(not_found)
164     + end;
165     +
166     +process(_Handlers, #request{method='POST', q=Q, path=[_, Id]}) ->
167     + ?T(case mnesia:read(captcha, Id, write) of
168     + [#captcha{pid=Pid, args=Args, key=Key, tref=Tref}] ->
169     + mnesia:delete({captcha, Id}),
170     + erlang:cancel_timer(Tref),
171     + Input = proplists:get_value("key", Q, none),
172     + if Input == Key ->
173     + Pid ! {captcha_succeed, Args},
174     + ejabberd_web:make_xhtml([]);
175     + true ->
176     + Pid ! {captcha_failed, Args},
177     + ejabberd_web:error(not_allowed)
178     + end;
179     + _ ->
180     + ejabberd_web:error(not_found)
181     + end).
182     +
183     +%%====================================================================
184     +%% gen_server callbacks
185     +%%====================================================================
186     +init([]) ->
187     + mnesia:create_table(captcha,
188     + [{ram_copies, [node()]},
189     + {attributes, record_info(fields, captcha)}]),
190     + mnesia:add_table_copy(captcha, node(), ram_copies),
191     + {ok, #state{}}.
192     +
193     +handle_call(_Request, _From, State) ->
194     + {reply, bad_request, State}.
195     +
196     +handle_cast(_Msg, State) ->
197     + {noreply, State}.
198     +
199     +handle_info({remove_id, Id}, State) ->
200     + ?DEBUG("captcha ~p timed out", [Id]),
201     + ?T(case mnesia:read(captcha, Id, write) of
202     + [#captcha{args=Args, pid=Pid}] ->
203     + Pid ! {captcha_failed, Args},
204     + mnesia:delete({captcha, Id});
205     + _ ->
206     + ok
207     + end),
208     + {noreply, State};
209     +
210     +handle_info(_Info, State) ->
211     + {noreply, State}.
212     +
213     +terminate(_Reason, _State) ->
214     + ok.
215     +
216     +code_change(_OldVsn, State, _Extra) ->
217     + {ok, State}.
218     +
219     +%%--------------------------------------------------------------------
220     +%%% Internal functions
221     +%%--------------------------------------------------------------------
222     +%%--------------------------------------------------------------------
223     +%% Function: create_image() -> {ok, Type, Key, Image} | {error, Reason}
224     +%% Type = "image/png" | "image/jpeg" | "image/gif"
225     +%% Key = string()
226     +%% Image = binary()
227     +%% Reason = atom()
228     +%%--------------------------------------------------------------------
229     +create_image() ->
230     + %% Six numbers from 1 to 9.
231     + Key = string:substr(randoms:get_string(), 1, 6),
232     + create_image(Key).
233     +
234     +create_image(Key) ->
235     + FileName = get_prog_name(),
236     + Cmd = lists:flatten(io_lib:format("~s ~s", [FileName, Key])),
237     + case cmd(Cmd) of
238     + {ok, <<16#89, $P, $N, $G, $\r, $\n, 16#1a, $\n, _/binary>> = Img} ->
239     + {ok, "image/png", Key, Img};
240     + {ok, <<16#ff, 16#d8, _/binary>> = Img} ->
241     + {ok, "image/jpeg", Key, Img};
242     + {ok, <<$G, $I, $F, $8, X, $a, _/binary>> = Img} when X==$7; X==$9 ->
243     + {ok, "image/gif", Key, Img};
244     + {error, Reason} ->
245     + ?ERROR_MSG("Failed to process an output from \"~s\": ~p",
246     + [Cmd, Reason]),
247     + {error, Reason};
248     + _ ->
249     + Reason = malformed_image,
250     + ?ERROR_MSG("Failed to process an output from \"~s\": ~p",
251     + [Cmd, Reason]),
252     + {error, Reason}
253     + end.
254     +
255     +get_prog_name() ->
256     + case ejabberd_config:get_local_option(captcha_cmd) of
257     + FileName when is_list(FileName) ->
258     + FileName;
259     + _ ->
260     + ""
261     + end.
262     +
263     +get_url(Str) ->
264     + case ejabberd_config:get_local_option(captcha_host) of
265     + Host when is_list(Host) ->
266     + "http://" ++ Host ++ "/captcha/" ++ Str;
267     + _ ->
268     + "http://" ++ ?MYNAME ++ "/captcha/" ++ Str
269     + end.
270     +
271     +%%--------------------------------------------------------------------
272     +%% Function: cmd(Cmd) -> Data | {error, Reason}
273     +%% Cmd = string()
274     +%% Data = binary()
275     +%% Description: os:cmd/1 replacement
276     +%%--------------------------------------------------------------------
277     +-define(CMD_TIMEOUT, 5000).
278     +-define(MAX_FILE_SIZE, 64*1024).
279     +
280     +cmd(Cmd) ->
281     + Port = open_port({spawn, Cmd}, [stream, eof, binary]),
282     + TRef = erlang:start_timer(?CMD_TIMEOUT, self(), timeout),
283     + recv_data(Port, TRef, <<>>).
284     +
285     +recv_data(Port, TRef, Buf) ->
286     + receive
287     + {Port, {data, Bytes}} ->
288     + NewBuf = <<Buf/binary, Bytes/binary>>,
289     + if size(NewBuf) > ?MAX_FILE_SIZE ->
290     + return(Port, TRef, {error, efbig});
291     + true ->
292     + recv_data(Port, TRef, NewBuf)
293     + end;
294     + {Port, {data, _}} ->
295     + return(Port, TRef, {error, efbig});
296     + {Port, eof} when Buf /= <<>> ->
297     + return(Port, TRef, {ok, Buf});
298     + {Port, eof} ->
299     + return(Port, TRef, {error, enodata});
300     + {timeout, TRef, _} ->
301     + return(Port, TRef, {error, timeout})
302     + end.
303     +
304     +return(Port, TRef, Result) ->
305     + case erlang:cancel_timer(TRef) of
306     + false ->
307     + receive
308     + {timeout, TRef, _} ->
309     + ok
310     + after 0 ->
311     + ok
312     + end;
313     + _ ->
314     + ok
315     + end,
316     + catch port_close(Port),
317     + Result.
318     diff -urN ejabberd-2.0.4/src/ejabberd_config.erl ejabberd-2.0.4-new/src/ejabberd_config.erl
319     --- ejabberd-2.0.4/src/ejabberd_config.erl 2009-03-12 09:41:02.000000000 +0100
320     +++ ejabberd-2.0.4-new/src/ejabberd_config.erl 2009-03-14 11:43:35.000000000 +0100
321     @@ -164,6 +164,10 @@
322     add_option(watchdog_admins, Admins, State);
323     {registration_timeout, Timeout} ->
324     add_option(registration_timeout, Timeout, State);
325     + {captcha_cmd, Cmd} ->
326     + add_option(captcha_cmd, Cmd, State);
327     + {captcha_host, Host} ->
328     + add_option(captcha_host, Host, State);
329     {loglevel, Loglevel} ->
330     ejabberd_loglevel:set(Loglevel),
331     State;
332     diff -urN ejabberd-2.0.4/src/ejabberd_sup.erl ejabberd-2.0.4-new/src/ejabberd_sup.erl
333     --- ejabberd-2.0.4/src/ejabberd_sup.erl 2009-03-12 09:41:02.000000000 +0100
334     +++ ejabberd-2.0.4-new/src/ejabberd_sup.erl 2009-03-14 12:36:43.000000000 +0100
335     @@ -84,6 +84,13 @@
336     brutal_kill,
337     worker,
338     [ejabberd_local]},
339     + Captcha =
340     + {ejabberd_captcha,
341     + {ejabberd_captcha, start_link, []},
342     + permanent,
343     + brutal_kill,
344     + worker,
345     + [ejabberd_captcha]},
346     Listener =
347     {ejabberd_listener,
348     {ejabberd_listener, start_link, []},
349     @@ -170,6 +177,7 @@
350     SM,
351     S2S,
352     Local,
353     + Captcha,
354     ReceiverSupervisor,
355     C2SSupervisor,
356     S2SInSupervisor,
357     diff -urN ejabberd-2.0.4/src/jlib.hrl ejabberd-2.0.4-new/src/jlib.hrl
358     --- ejabberd-2.0.4/src/jlib.hrl 2009-03-12 09:41:02.000000000 +0100
359     +++ ejabberd-2.0.4-new/src/jlib.hrl 2009-03-14 11:41:46.000000000 +0100
360     @@ -74,6 +74,12 @@
361    
362     -define(NS_CAPS, "http://jabber.org/protocol/caps").
363    
364     +%% CAPTCHA related NSes.
365     +-define(NS_OOB, "jabber:x:oob").
366     +-define(NS_CAPTCHA, "urn:xmpp:captcha").
367     +-define(NS_MEDIA, "urn:xmpp:media-element").
368     +-define(NS_BOB, "urn:xmpp:bob").
369     +
370     % TODO: remove "code" attribute (currently it used for backward-compatibility)
371     -define(STANZA_ERROR(Code, Type, Condition),
372     {xmlelement, "error",
373     diff -urN ejabberd-2.0.4/src/mod_muc/mod_muc_room.erl ejabberd-2.0.4-new/src/mod_muc/mod_muc_room.erl
374     --- ejabberd-2.0.4/src/mod_muc/mod_muc_room.erl 2009-03-12 09:41:02.000000000 +0100
375     +++ ejabberd-2.0.4-new/src/mod_muc/mod_muc_room.erl 2009-03-14 11:40:40.000000000 +0100
376     @@ -69,6 +69,7 @@
377     public_list = true,
378     persistent = false,
379     moderated = true,
380     + captcha_protected = false,
381     members_by_default = true,
382     members_only = false,
383     allow_user_invites = false,
384     @@ -98,6 +99,7 @@
385     jid,
386     config = #config{},
387     users = ?DICT:new(),
388     + robots = ?DICT:new(),
389     affiliations = ?DICT:new(),
390     history = lqueue_new(20),
391     subject = "",
392     @@ -382,7 +384,8 @@
393     (XMLNS == ?NS_MUC_ADMIN) or
394     (XMLNS == ?NS_MUC_OWNER) or
395     (XMLNS == ?NS_DISCO_INFO) or
396     - (XMLNS == ?NS_DISCO_ITEMS) ->
397     + (XMLNS == ?NS_DISCO_ITEMS) or
398     + (XMLNS == ?NS_CAPTCHA) ->
399     Res1 = case XMLNS of
400     ?NS_MUC_ADMIN ->
401     process_iq_admin(From, Type, Lang, SubEl, StateData);
402     @@ -391,7 +394,9 @@
403     ?NS_DISCO_INFO ->
404     process_iq_disco_info(From, Type, Lang, StateData);
405     ?NS_DISCO_ITEMS ->
406     - process_iq_disco_items(From, Type, Lang, StateData)
407     + process_iq_disco_items(From, Type, Lang, StateData);
408     + ?NS_CAPTCHA ->
409     + process_iq_captcha(From, Type, Lang, SubEl, StateData)
410     end,
411     {IQRes, NewStateData} =
412     case Res1 of
413     @@ -761,6 +766,30 @@
414     {empty, _} ->
415     {next_state, StateName, StateData}
416     end;
417     +handle_info({captcha_succeed, From}, normal_state, StateData) ->
418     + NewState = case ?DICT:find(From, StateData#state.robots) of
419     + {ok, {Nick, Packet}} ->
420     + Robots = ?DICT:store(From, passed, StateData#state.robots),
421     + add_new_user(From, Nick, Packet, StateData#state{robots=Robots});
422     + _ ->
423     + StateData
424     + end,
425     + {next_state, normal_state, NewState};
426     +handle_info({captcha_failed, From}, normal_state, StateData) ->
427     + NewState = case ?DICT:find(From, StateData#state.robots) of
428     + {ok, {Nick, Packet}} ->
429     + Robots = ?DICT:erase(From, StateData#state.robots),
430     + Err = jlib:make_error_reply(
431     + Packet, ?ERR_NOT_AUTHORIZED),
432     + ejabberd_router:route( % TODO: s/Nick/""/
433     + jlib:jid_replace_resource(
434     + StateData#state.jid, Nick),
435     + From, Err),
436     + StateData#state{robots=Robots};
437     + _ ->
438     + StateData
439     + end,
440     + {next_state, normal_state, NewState};
441     handle_info(_Info, StateName, StateData) ->
442     {next_state, StateName, StateData}.
443    
444     @@ -1461,7 +1490,8 @@
445     From, Err),
446     StateData;
447     {_, _, _, Role} ->
448     - case check_password(ServiceAffiliation, Els, StateData) of
449     + case check_password(ServiceAffiliation, Affiliation,
450     + Els, From, StateData) of
451     true ->
452     NewState =
453     add_user_presence(
454     @@ -1494,7 +1524,8 @@
455     true ->
456     NewState#state{just_created = false};
457     false ->
458     - NewState
459     + Robots = ?DICT:erase(From, StateData#state.robots),
460     + NewState#state{robots = Robots}
461     end;
462     nopass ->
463     ErrText = "Password required to enter this room",
464     @@ -1505,6 +1536,29 @@
465     StateData#state.jid, Nick),
466     From, Err),
467     StateData;
468     + captcha_required ->
469     + ID = randoms:get_string(),
470     + SID = xml:get_attr_s("id", Attrs),
471     + RoomJID = StateData#state.jid,
472     + To = jlib:jid_replace_resource(RoomJID, Nick),
473     + case ejabberd_captcha:create_captcha(
474     + ID, SID, RoomJID, To, Lang, From) of
475     + {ok, CaptchaEls} ->
476     + MsgPkt = {xmlelement, "message", [{"id", ID}], CaptchaEls},
477     + Robots = ?DICT:store(From,
478     + {Nick, Packet}, StateData#state.robots),
479     + ejabberd_router:route(RoomJID, From, MsgPkt),
480     + StateData#state{robots = Robots};
481     + error ->
482     + ErrText = "Unable to generate a captcha",
483     + Err = jlib:make_error_reply(
484     + Packet, ?ERRT_INTERNAL_SERVER_ERROR(Lang, ErrText)),
485     + ejabberd_router:route( % TODO: s/Nick/""/
486     + jlib:jid_replace_resource(
487     + StateData#state.jid, Nick),
488     + From, Err),
489     + StateData
490     + end;
491     _ ->
492     ErrText = "Incorrect password",
493     Err = jlib:make_error_reply(
494     @@ -1517,13 +1571,13 @@
495     end
496     end.
497    
498     -check_password(owner, _Els, _StateData) ->
499     +check_password(owner, _Affiliation, _Els, _From, _StateData) ->
500     %% Don't check pass if user is owner in MUC service (access_admin option)
501     true;
502     -check_password(_ServiceAffiliation, Els, StateData) ->
503     +check_password(_ServiceAffiliation, Affiliation, Els, From, StateData) ->
504     case (StateData#state.config)#config.password_protected of
505     false ->
506     - true;
507     + check_captcha(Affiliation, From, StateData);
508     true ->
509     Pass = extract_password(Els),
510     case Pass of
511     @@ -1539,6 +1593,19 @@
512     end
513     end.
514    
515     +check_captcha(Affiliation, From, StateData) ->
516     + case (StateData#state.config)#config.captcha_protected of
517     + true when Affiliation == none ->
518     + case ?DICT:find(From, StateData#state.robots) of
519     + {ok, passed} ->
520     + true;
521     + _ ->
522     + captcha_required
523     + end;
524     + _ ->
525     + true
526     + end.
527     +
528     extract_password([]) ->
529     false;
530     extract_password([{xmlelement, _Name, Attrs, _SubEls} = El | Els]) ->
531     @@ -2713,6 +2780,9 @@
532     ?BOOLXFIELD("Make room members-only",
533     "muc#roomconfig_membersonly",
534     Config#config.members_only),
535     + ?BOOLXFIELD("Make room captcha protected",
536     + "captcha_protected",
537     + Config#config.captcha_protected),
538     ?BOOLXFIELD("Make room moderated",
539     "muc#roomconfig_moderatedroom",
540     Config#config.moderated),
541     @@ -2823,6 +2893,8 @@
542     ?SET_BOOL_XOPT(members_by_default, Val);
543     set_xoption([{"muc#roomconfig_membersonly", [Val]} | Opts], Config) ->
544     ?SET_BOOL_XOPT(members_only, Val);
545     +set_xoption([{"captcha_protected", [Val]} | Opts], Config) ->
546     + ?SET_BOOL_XOPT(captcha_protected, Val);
547     set_xoption([{"muc#roomconfig_allowinvites", [Val]} | Opts], Config) ->
548     ?SET_BOOL_XOPT(allow_user_invites, Val);
549     set_xoption([{"muc#roomconfig_passwordprotectedroom", [Val]} | Opts], Config) ->
550     @@ -2913,6 +2985,7 @@
551     ?CASE_CONFIG_OPT(members_only);
552     ?CASE_CONFIG_OPT(allow_user_invites);
553     ?CASE_CONFIG_OPT(password_protected);
554     + ?CASE_CONFIG_OPT(captcha_protected);
555     ?CASE_CONFIG_OPT(password);
556     ?CASE_CONFIG_OPT(anonymous);
557     ?CASE_CONFIG_OPT(logging);
558     @@ -2954,6 +3027,7 @@
559     ?MAKE_CONFIG_OPT(members_only),
560     ?MAKE_CONFIG_OPT(allow_user_invites),
561     ?MAKE_CONFIG_OPT(password_protected),
562     + ?MAKE_CONFIG_OPT(captcha_protected),
563     ?MAKE_CONFIG_OPT(password),
564     ?MAKE_CONFIG_OPT(anonymous),
565     ?MAKE_CONFIG_OPT(logging),
566     @@ -3074,6 +3148,17 @@
567     {error, ?ERR_FORBIDDEN}
568     end.
569    
570     +process_iq_captcha(_From, get, _Lang, _SubEl, _StateData) ->
571     + {error, ?ERR_NOT_ALLOWED};
572     +
573     +process_iq_captcha(_From, set, _Lang, SubEl, StateData) ->
574     + case ejabberd_captcha:process_reply(SubEl) of
575     + ok ->
576     + {result, [], StateData};
577     + _ ->
578     + {error, ?ERR_NOT_ACCEPTABLE}
579     + end.
580     +
581     get_title(StateData) ->
582     case (StateData#state.config)#config.title of
583     "" ->
584     diff -urN ejabberd-2.0.4/src/web/ejabberd_http.erl ejabberd-2.0.4-new/src/web/ejabberd_http.erl
585     --- ejabberd-2.0.4/src/web/ejabberd_http.erl 2009-03-12 09:41:02.000000000 +0100
586     +++ ejabberd-2.0.4-new/src/web/ejabberd_http.erl 2009-03-14 10:57:34.000000000 +0100
587     @@ -106,6 +106,10 @@
588     {value, {request_handlers, H}} -> H;
589     false -> []
590     end ++
591     + case lists:member(captcha, Opts) of
592     + true -> [{["captcha"], ejabberd_captcha}];
593     + false -> []
594     + end ++
595     case lists:member(web_admin, Opts) of
596     true -> [{["admin"], ejabberd_web_admin}];
597     false -> []
598     Binary files ejabberd-2.0.4/tools/.DS_Store and ejabberd-2.0.4-new/tools/.DS_Store differ
599     diff -urN ejabberd-2.0.4/tools/captcha.sh ejabberd-2.0.4-new/tools/captcha.sh
600     --- ejabberd-2.0.4/tools/captcha.sh 1970-01-01 01:00:00.000000000 +0100
601     +++ ejabberd-2.0.4-new/tools/captcha.sh 2009-03-14 11:46:42.000000000 +0100
602     @@ -0,0 +1,21 @@
603     +#!/bin/sh
604     +
605     +SIGN=$(($RANDOM % 2))
606     +
607     +R1=$(($RANDOM % 20))
608     +R2=$(($RANDOM % 10 + 40))
609     +
610     +if [ $SIGN -eq "0" ]; then
611     + S1=$(( -1*($RANDOM % 20 + 50) ))
612     + S2=$(( $RANDOM % 20 + 50 ))
613     +else
614     + S2=$(( -1*($RANDOM % 20 + 50) ))
615     + S1=$(( $RANDOM % 20 + 50 ))
616     +fi
617     +
618     +convert -size 140x60 xc:white \
619     + -pointsize 30 -draw "text 20,30 '$1'" \
620     + -roll -$R2+$R1 -swirl $S1 \
621     + -roll +$R2-$R1 -swirl $S2 \
622     + +repage -resize 120x60 \
623     + -quality 90 -depth 8 png:-
624     --- ejabberd-2.0.5/ChangeLog~ 2009-04-01 19:23:52.000000000 +0400
625     +++ ejabberd-2.0.5/ChangeLog 2009-04-03 23:45:03.174979944 +0400
626     @@ -15,6 +15,15 @@
627     stanza (EJAB-300).
628     * src/ejabberd_c2s.erl: Likewise
629    
630     +2009-03-13 Evgeniy Khramtsov <ekhramtsov@process-one.net>
631     +
632     + * src/ejabberd_captcha.erl: XEP-158 (CAPTCHA Forms).
633     + * src/ejabberd_config.erl: likewise.
634     + * src/ejabberd_sup.erl: likewise.
635     + * src/jlib.hrl: likewise.
636     + * src/web/ejabberd_http.erl: likewise.
637     + * src/mod_muc/mod_muc_room.erl: CAPTCHA support.
638     +
639     2009-03-10 Badlop <badlop@process-one.net>
640    
641     * doc/release_notes_2.0.4.txt: Added file for new release

admin@koozali.org
ViewVC Help
Powered by ViewVC 1.2.1 RSS 2.0 feed