comparison mod_archive/mod_archive.lua @ 198:a3b5810de3e4

mod_archive: XEP-0059 Result Set Management for Retrieving a Collection is DONE
author shinysky<shinysky1986(AT)gmail.com>
date Wed, 07 Jul 2010 22:07:36 +0800
parents a1c2677257da
children 27b8a7482149
comparison
equal deleted inserted replaced
197:2686221255cf 198:a3b5810de3e4
10 local jid = require "util.jid"; 10 local jid = require "util.jid";
11 local datetime = require "util.datetime"; 11 local datetime = require "util.datetime";
12 12
13 local PREFS_DIR = "archive_prefs"; 13 local PREFS_DIR = "archive_prefs";
14 local ARCHIVE_DIR = "archive"; 14 local ARCHIVE_DIR = "archive";
15 local xmlns_rsm = "http://jabber.org/protocol/rsm";
15 16
16 module:add_feature("urn:xmpp:archive"); 17 module:add_feature("urn:xmpp:archive");
17 module:add_feature("urn:xmpp:archive:auto"); 18 module:add_feature("urn:xmpp:archive:auto");
18 module:add_feature("urn:xmpp:archive:manage"); 19 module:add_feature("urn:xmpp:archive:manage");
19 module:add_feature("urn:xmpp:archive:manual"); 20 module:add_feature("urn:xmpp:archive:manual");
366 local reply = st.reply(stanza):tag('list', {xmlns='urn:xmpp:archive'}); 367 local reply = st.reply(stanza):tag('list', {xmlns='urn:xmpp:archive'});
367 local count = table.getn(resset); 368 local count = table.getn(resset);
368 if count > 0 then 369 if count > 0 then
369 local max = elem.tags[1]:child_with_name("max"); 370 local max = elem.tags[1]:child_with_name("max");
370 if max then 371 if max then
371 max = tonumber(max:get_text()); 372 max = tonumber(max:get_text()) or 100;
372 else max = 100; end 373 else max = 100; end
373 local after = elem.tags[1]:child_with_name("after"); 374 local after = elem.tags[1]:child_with_name("after");
374 local before = elem.tags[1]:child_with_name("before"); 375 local before = elem.tags[1]:child_with_name("before");
375 local index = elem.tags[1]:child_with_name("index"); 376 local index = elem.tags[1]:child_with_name("index");
376 local s, e = 1, 1+max; 377 local s, e = 1, 1+max;
404 if e > count + 1 then e = count + 1; end 405 if e > count + 1 then e = count + 1; end
405 -- Assuming result set is sorted. 406 -- Assuming result set is sorted.
406 for i = s, e-1 do 407 for i = s, e-1 do
407 reply:add_child(st.stanza('chat', resset[i].attr)); 408 reply:add_child(st.stanza('chat', resset[i].attr));
408 end 409 end
409 local set = st.stanza('set', {xmlns='http://jabber.org/protocol/rsm'}); 410 local set = st.stanza('set', {xmlns = xmlns_rsm});
410 if s <= e-1 then 411 if s <= e-1 then
411 set:tag('first', {index=s-1}):text(gen_uid(resset[s])):up() 412 set:tag('first', {index=s-1}):text(gen_uid(resset[s])):up()
412 :tag('last'):text(gen_uid(resset[e-1])):up(); 413 :tag('last'):text(gen_uid(resset[e-1])):up();
413 end 414 end
414 set:tag('count'):text(tostring(count)):up(); 415 set:tag('count'):text(tostring(count)):up();
417 origin.send(reply); 418 origin.send(reply);
418 return true; 419 return true;
419 end 420 end
420 421
421 local function retrieve_handler(event) 422 local function retrieve_handler(event)
422 module:log("debug", "-- stanza:\n%s", tostring(event.stanza)); 423 local origin, stanza = event.origin, event.stanza;
424 local node, host = origin.username, origin.host;
425 local data = dm.list_load(node, host, ARCHIVE_DIR);
426 local elem = stanza.tags[1];
427 local collection = nil;
428 if data then
429 for k, v in ipairs(data) do
430 local c = st.deserialize(v);
431 if c.attr["with"] == elem.attr["with"]
432 and c.attr["start"] == elem.attr["start"] then
433 collection = c;
434 break;
435 end
436 end
437 end
438 if not collection then
439 -- TODO code=404
440 origin.send(st.error_reply(stanza, "cancel", "item-not-found"));
441 return true;
442 end
443 local resset = {}
444 for i, e in ipairs(collection) do
445 if e.name == "from" or e.name == "to" then
446 table.insert(resset, e);
447 end
448 end
449 collection.attr['xmlns'] = 'urn:xmpp:archive';
450 local reply = st.reply(stanza):tag('chat', collection.attr);
451 local count = table.getn(resset);
452 if count > 0 then
453 local max = elem.tags[1]:child_with_name("max");
454 if max then
455 max = tonumber(max:get_text()) or 100;
456 else max = 100; end
457 local after = elem.tags[1]:child_with_name("after");
458 local before = elem.tags[1]:child_with_name("before");
459 local index = elem.tags[1]:child_with_name("index");
460 local s, e = 1, 1+max;
461 if after then
462 after = tonumber(after:get_text());
463 if not after or after < 1 or after > count then -- not found
464 origin.send(st.error_reply(stanza, "cancel", "item-not-found"));
465 return true;
466 end
467 s = after + 1;
468 e = s + max;
469 elseif before then
470 before = tonumber(before:get_text());
471 if not before then -- the last page
472 e = count + 1;
473 s = e - max;
474 elseif before < 1 or before > count then
475 origin.send(st.error_reply(stanza, "cancel", "item-not-found"));
476 return true;
477 else
478 e = before;
479 s = e - max;
480 end
481 elseif index then
482 s = tonumber(index:get_text()) + 1; -- 0-based
483 e = s + max;
484 end
485 if s < 1 then s = 1; end
486 if e > count + 1 then e = count + 1; end
487 -- Assuming result set is sorted.
488 for i = s, e-1 do
489 reply:add_child(resset[i]);
490 end
491 local set = st.stanza('set', {xmlns = xmlns_rsm});
492 if s <= e-1 then
493 set:tag('first', {index=s-1}):text(tostring(s)):up()
494 :tag('last'):text(tostring(e-1)):up();
495 end
496 set:tag('count'):text(tostring(count)):up();
497 reply:add_child(set);
498 end
499 origin.send(reply);
423 return true; 500 return true;
424 end 501 end
425 502
426 local function remove_handler(event) 503 local function remove_handler(event)
427 module:log("debug", "-- stanza:\n%s", tostring(event.stanza)); 504 module:log("debug", "-- stanza:\n%s", tostring(event.stanza));
482 559
483 module:hook("message/full", msg_handler, 10); 560 module:hook("message/full", msg_handler, 10);
484 module:hook("message/bare", msg_handler, 10); 561 module:hook("message/bare", msg_handler, 10);
485 562
486 -- FIXME sort collections 563 -- FIXME sort collections
487 564 -- TODO exactmatch