Trucs de geek

[Updated 2] Atom-PubSub module for ejabberd

Posted on juin 19, 2008

As requested, the Atom PubSub bridge

This module offersr an AtomPub interface to ejabberd PubSub data. Currently in two unfinished flavors, one for use with yaws embedded. One for use with ejabberd_http server

Howto

You need to have Yaws available. It will start in embedded mode, with the mod_yaws module (included). To build, edit the Makefile to match your erlang install and make Put the resulting beams in some place where ejabberd will find them.

Also you’ll need to set the BASEURL macro in atom_pubsub.erl to your webserver hostname.

You’ll also need to add the module to your ejabberd.cfg in the mmodules section:


{mod_yaws,[{logdir, "/tmp/"},
    {servers, [
    {"localhost", 5224, "/opt/var/yaws/www", [
     {dir_listing, true},
     {appmods, {"/atom",     atom_pubsub}}
     ]}
   ]}
  ]}

What you get

The AtomPub interface passes the Atom Protocol Exerciser (though some warnings remain).

It means that any AtomPub clients will be able to post to a specific node in your PubSub tree.

It also means that your PubSub tree will also be available as an AtomFeed.

Of course, each time an item is posted through AtomPub or PubSub on a node you are subscribed to, you’ll get the notification.

Can I have it with OpenFire and Epeios ?

That’s not possible. At some point, there’s no way around hitting directly the PubSub mnesia tables. So you can’t extract the code as a component.

Moreover, it only works with PubSub nodes derived from the default node type. (because of the mnesia tables stuff)

What’s next ?

I’ll update the code soon. A few of things I’d like to implement :

  • remove all calls to mnesia and work through mod_pubsub API.
  • add HEAD, etag and slug support (that’s a patch for ejabberd though)
  • remove that baseurl horrible macro
  • add node subscription through REST
  • as soon as ejabberd 2.1 is published remove dependency from yaws
  • add binary collections support

Mickaël Rémond from Process-One kindly offered to host atom-pubsub on the ejabberd_modules svn.


svn co https://svn.process-one.net/ejabberd-modules/atom_pubsub/trunk/

There’s a quick port to the ejabberd_http server at this location : You need to be running ejabberd 2.1 or current trunk to have it work.


svn co https://svn.process-one.net/ejabberd-modules/atom_pubsub/branches/ejabberd_http_branch/

Check out the README for installation.

Shoot your questions in the comment or via email (anything on this weblog domain goes to my inbox)

CookieStore on Yaws

Posted on avril 10, 2008

I implemented a session cookie store, just like the one in Ruby on Rails 2.0.

Available with the same caveats : Session data is encoded in base64 and sent in the cookie with a SHA MAC of this data. This means that the user can see what’s inside, but will not be able to tamper with it.

Moreover session data should stay in small amount as the encoded and signed data may not exceed 4096 bytes.

This being said, that should give us Yaws clustering for free :) And no more sessions to expire, just set the cookie expiration date.

One small thing, make sure crypto is started.

session1.yaws has been rewritten to make use of this code.

Download here.

mini Auth CAS on Yaws

Posted on avril 03, 2008

Yaws, c’est le serveur web écrit en erlang, célèbre pour ce graphe qui montre comment Yaws met sa pâté à Apache.

Voici le client minimal permettant de s’authentifier sur un serveur CAS.

A sauver dans un fichier cas.yaws à mettre dans le /var/yaws (document root par défaut).

N’oubliez pas d’adapter CASHOST et SERVICE à votre configuration.

<erl>
-define(CASHOST, "http://localhost:8080/cas/").
-define(SERVICE, "service=http%3A%2F%2Flocalhost%3A5224%2Fcas.yaws").
-include_lib("xmerl/include/xmerl.hrl").

out(A)->
    H = A#arg.headers,
    C = H#headers.cookie,
    inets:start(),
    case yaws_api:find_cookie_val("casuser", C) of
        []->
            check_auth(A);  
        Cookie ->
            {ok, Username} = yaws_api:cookieval_to_opaque(Cookie),
            {html, "Authentified as "++Username}
    end.

check_auth(A)->  
    case queryvar(A,"ticket") of
        {ok, Ticket}->
            case verify_ticket(Ticket) of
                {ok, Username} ->
                    Cookie = yaws_api:new_cookie_session(Username),
                    CO = yaws_api:setcookie("casuser",Cookie,"/"),
                    [{html, "Authentified as "++Username}, CO];
                {error, Reason} ->
                    [{status, 403},{html, "Unauthorized : "++Reason}]
            end;
        undefined ->
            {redirect, ?CASHOST ++ "login?" ++ ?SERVICE }
        end.

verify_ticket(Ticket) ->
    inets:start(),
    Url =?CASHOST++"proxyValidate?"++?SERVICE++"&ticket="++Ticket,
    {ok, {_Status, _Headers, Body}} =
          http:request(Url),
    { Xml, _Rest } = xmerl_scan:string(Body),
    inets:stop(),
    case xmerl_xpath:string("//cas:user/text()",Xml) of
        [ #xmlText{value=Username} ] ->
            {ok, Username};
        [] ->
            {error, "invalid ticket " ++ Url}
        end.
</erl>

Tant qu’on est sur le sujet, il y a un article très intéressant sur le REST dans Yaws chez InfoQ.