lunedì, 07 aprile 2008
As promised I'm releasing the cookie patch for ejabberd 2.0. The patch is quite simple and takes few minutes to check it out.
To apply the patch cumulatively, simply do the following

ejabberd/src/web/ $ patch < $HOME/ejabberd-2.0-cookie.patch
Otherwise you could apply the patch to single files:

ejabberd/src/web/ $ patch ejabberd_http.hrl $HOME/ejabberd_http_hrl.patch
ejabberd/src/web/ $ patch ejabberd_http.erl $HOME/ejabberd_http_erl.patch

Let me know if you got errors applying this patch.

Links:
ejabberd 2.0 Cumulative Cookie Patch
ejabberd_http Source Cookie Patch
ejabberd_http Header Cookie Patch
posted() loretoparisi times() 11:37 | Permalink | commenti | commenti (popup)
cookie, patch, ejabberd
venerdì, 04 aprile 2008
To add cookies to HTTP POST/GET requests in ejabberd (1.1.x and 2.x) we have to add some fields in the request headers, setting up the request and state records in ejabberd_http.erl module and its header file ejabberd_http.hrl.

First of all, we will add the field cookie to the record request in ejabberd_http.hrl header file as follows:

-record(request, {method,
                  path,
                  q = [],
                  us,
                  auth,
                  lang = "",
                  data = "",
                  cookie = "", %% lp: cookie request field
                  ip
                 }).


As you can see we are referring to ejabberd 2.0 (in the request record we have the new field ip for new user info).

Now we will edit the ejabberd_http.erl module, adding the field request_cookie to the record state:

-record(state, {sockmod,
                socket,
                request_method,
                request_version,
                request_path,
                request_auth,
                request_cookie, %% lp: cookie request field
                request_keepalive,
                (...)

 
At this point, we have to pass cookies to handlers, modifying the process_headers and process_request functions:

In the process_header, we will add to the case construct

process_header(State, Data) ->
    SockMod = State#state.sockmod,
    Socket = State#state.socket,
    case Data of
        {ok, {http_request, Method, Uri, Version}} ->
   
    (...)
        {ok, {http_header, _, 'Authorization', _, Auth}} ->
            State#state{request_auth = parse_auth(Auth)};
        {ok, {http_header, _, 'Cookie', _, Cookie}} ->
            %% lp: setting up request header cookie
            State#state{request_cookie = Cookie};
        {ok, {http_header, _, 'Content-Length', _, SLen}} ->
    (...)


In the process_request we have to modify the function header as follows:

process_request(#state{request_method = 'GET',
                       request_path = {abs_path, Path},
                       request_auth = Auth,
                       request_lang = Lang,
                       request_cookie = Cookie, %% lp: cookie request field
                       request_handlers = RequestHandlers,
                       sockmod = SockMod,
                       socket = Socket} = State) ->
                       
                        (...)
                        Request = #request{method = 'GET',
                               path = LPath,
                               q = LQuery,
                               auth = Auth,
                               lang = Lang,
                               cookie = Cookie, %% lp: here again :)
                               ip=IP},
                        (...)


and in the next header too:

process_request(#state{request_method = 'POST',
                       request_path = {abs_path, Path},
                       request_auth = Auth,
                       request_content_length = Len,
                       request_lang = Lang,
                       request_cookie = Cookie, %% lp: cookie
                       sockmod = SockMod,
                       socket = Socket,
                       request_handlers = RequestHandlers} = State)
  when is_integer(Len) ->

              (...)
              Request = #request{method = 'POST',
                               path = LPath,
                               q = LQuery,
                               auth = Auth,
                               cookie = Cookie, %% lp: cookie the last one ;)
                               data = Data,
                               lang = Lang},
              case process(RequestHandlers, Request) of
                 (...)


Now, we are ready to add the cookie request's field to our modules processing http requests:

process(#request{us = _US,
                     path = "login",
                     q = _Query,
                     lang = _Lang,
                     cookie = _Cookie} = Request) ->
          
              %% _Cookie will contain the request cookie now
              %% Manage request by cookies
              %% Send response :)



I will eventually post a addon patch for this :)

Enjoy your Jabber,
LP


PS. We used ejabberd 2.0, but you can do this in ejabberd 1.1.x in the same way


Links:
http://www.process-one.net/en/wiki/ejabberd_module_development/
posted() loretoparisi times() 18:05 | Permalink | commenti | commenti (popup)
cookie, request headers