From 20921d9f5508d74b0e3cbc314c667393251ef909 Mon Sep 17 00:00:00 2001
From: Edward Rudd
Date: Mon, 15 Feb 2010 12:34:02 -0500
Subject: import release 0.02
---
lib/DJabberd/RosterStorage/SQLite/Fixed.pm | 274 +++++++++++++++++++++++++++++
1 file changed, 274 insertions(+)
create mode 100644 lib/DJabberd/RosterStorage/SQLite/Fixed.pm
(limited to 'lib/DJabberd')
diff --git a/lib/DJabberd/RosterStorage/SQLite/Fixed.pm b/lib/DJabberd/RosterStorage/SQLite/Fixed.pm
new file mode 100644
index 0000000..fe41363
--- /dev/null
+++ b/lib/DJabberd/RosterStorage/SQLite/Fixed.pm
@@ -0,0 +1,274 @@
+package DJabberd::RosterStorage::SQLite::Fixed;
+use strict;
+use warnings;
+use base 'DJabberd::RosterStorage::SQLite';
+use DJabberd::Log;
+use DJabberd::Util;
+our $logger = DJabberd::Log->get_logger();
+
+=head1 NAME
+
+DJabberd::RosterStorage::SQLite::Fixed - a shared roster implementation for the SQLite roster storage
+
+=head1 VERSION
+
+Version 0.02
+=cut
+
+our $VERSION = '0.02';
+
+=head1 SYNOPSIS
+
+
+
+ [...]
+
+
+ Database jabberroster.sqlite
+ FixedGuestOK yes
+
+
+
+Valid command are all command valid in DJabberd::RosterStorage::SQLite Plus the following
+
+FixedGuestOK - Populate accounts with the shared roster if they are not in the roster itself?
+ Setting this to yes will populate a user who is not in the shared roster with everyone in the shared roster
+ The default is to only populate rosters for users that are part of the shared roster
+
+=head1 AUTHOR
+
+Edward Rudd, C<< >>
+
+=cut
+
+=head2 set_config_fixedguestok($self, $guest)
+
+Called to specify if guests should have the shared roster added to their roster
+
+=cut
+
+sub set_config_fixedguestok {
+ my ($self, $guest) = @_;
+ $self->{fixed_guestok} = as_bool $guest;
+}
+
+=head2 finalize($self)
+
+Set defaults for the configuration
+
+=cut
+
+sub finalize {
+ my $self = shift;
+ $self->{fixed_guestok} = 0 unless $self->{fixed_guestok};
+ $self->SUPER::finalize;
+}
+
+=head2 get_roster($self, $cb, $jid)
+
+Gets the Roster for the user
+
+=cut
+
+sub get_roster {
+ my ($self, $cb, $jid) = @_;
+ # cb can '->set_roster(Roster)' or decline
+
+ my $myself = lc $jid->as_bare_string;
+ $logger->info("Fixed loading roster for $myself ...");
+
+ my $on_load_roster = sub {
+ my (undef, $roster) = @_;
+
+ my $pre_ct = $roster->items;
+ $logger->info(" $pre_ct roster items prior to population...");
+
+ # see which shared contacts already in roster
+ my %has;
+ foreach my $it ($roster->items) {
+ my $jid = $it->jid;
+ $has{lc $jid->as_bare_string} = $it;
+ }
+
+ # add missing shared contacts to the roster
+ my $req_roster = $self->_roster();
+ if ($self->{fixed_guestok}==0) {
+ my $guestok = 0;
+ foreach my $user ( @$req_roster) {
+ if ($user->{jid} eq $myself) {
+ $guestok = 1;
+ last;
+ }
+ }
+ # Bail if guestOK == 0 && user it not in the roster
+ return if $guestok == 0;
+ }
+
+ foreach my $user ( @$req_roster) {
+ next if $user->{jid} eq $myself;
+
+ my $name = $user->{name};
+ my $ri = $has{$user->{jid}} || DJabberd::RosterItem->new(jid => $user->{jid},
+ name => ($user->{name} || $user->{jid}),
+ groups => [$user->{group}]);
+
+
+ $ri->subscription->set_from;
+ $ri->subscription->set_to;
+ $roster->add($ri);
+ }
+
+ my $post_ct = $roster->items;
+ $logger->info(" $post_ct roster items post population...");
+
+ $cb->set_roster($roster);
+ };
+
+ my $cb2 = DJabberd::Callback->new({set_roster => $on_load_roster,
+ decline => sub { $cb->decline }});
+ $self->SUPER::get_roster($cb2, $jid);
+}
+
+=head2 check_install_schema($self)
+
+Checks the SQL ite Schema
+
+=cut
+
+sub check_install_schema {
+ my $self = shift;
+
+ $self->SUPER::check_install_schema();
+
+ my $dbh = $self->{dbh};
+
+ eval {
+ $dbh->do(qq{
+ CREATE TABLE requiredusers (
+ jid VARCHAR(255) NOT NULL,
+ fullname VARCHAR(255) NOT NULL,
+ groupname VARCHAR(255) NOT NULL,
+ UNIQUE (jid)
+ )});
+ };
+ if ($@ && $@ !~ /table \w+ already exists/) {
+ $logger->logdie("SQL error $@");
+ die "SQL error: $@\n";
+ }
+ eval {
+ $dbh->do(qq{
+ CREATE VIEW RosterPreview AS
+ SELECT ju.jid AS UserID, g.name AS [Group],
+ jr.jid AS ContactID, r.name AS Contact, r.subscription AS Subscription
+ FROM roster r
+ JOIN jidmap ju ON r.userid=ju.jidid
+ JOIN jidmap jr ON r.contactid = jr.jidid
+ JOIN groupitem gi ON gi.contactid=r.contactid
+ JOIN rostergroup g ON g.userid=r.userid AND g.groupid=gi.groupid
+ UNION SELECT r1.jid, r2.groupname, r2.jid, r2.fullname, 3
+ FROM requiredusers r1, requiredusers r2
+ WHERE r1.jid != r2.jid});
+ };
+ if ($@ && $@ !~ /table \w+ already exists/) {
+ $logger->logdie("SQL error $@");
+ die "SQL error: $@\n";
+ }
+ eval {
+ $dbh->do(qq{
+ CREATE VIEW RosterList AS
+ SELECT J.jidid as LID, J2.jidid as RID,
+ G.groupid as GID,
+ J.jid AS Local, J2.jid AS Remote,
+ G.name AS [Group]
+ FROM jidmap J
+ JOIN rostergroup G ON G.userid=J.jidid
+ JOIN groupitem M ON G.groupid = M.groupid
+ JOIN jidmap J2 ON J2.jidid = M.contactid
+ ORDER BY J.jid, J2.jid});
+ };
+ if ($@ && $@ !~ /table \w+ already exists/) {
+ $logger->logdie("SQL error $@");
+ die "SQL error: $@\n";
+ }
+ $logger->info("Created all roster tables");
+}
+
+my $last_roster;
+my $last_roster_time = 0; # unixtime of last SQL suck
+sub _roster {
+ my $self = shift;
+ my $now = time();
+
+ # Cache list for 1 minute(s)
+ if ($last_roster && $last_roster_time > $now - 60) {
+ return $last_roster;
+ }
+
+ my $dbh = $self->{dbh};
+
+ my $sql = qq{
+ SELECT jid, fullname, groupname FROM requiredusers
+ };
+
+ my $roster = eval {
+ $dbh->selectall_arrayref($sql);
+ };
+ $logger->logdie("Failed to load roster: $@") if $@;
+
+ $logger->info("Found ".($#{ @$roster}+1)." Roster users");
+
+ my @info = ();
+ foreach my $item ( @$roster ) {
+ my $rec = {};
+ $rec->{'jid'} = $item->[0];
+ $rec->{'name'} = $item->[1];
+ $rec->{'group'} = $item->[2];
+ push @info, $rec;
+ }
+ $logger->info("Loaded ".($#info+1)." Roster users");
+ $last_roster_time = $now;
+ return $last_roster = \@info;
+}
+
+=head2 load_roster_item($self, $jid, $contact_jid, $cb)
+
+Called when a roster item is added
+
+=cut
+
+sub load_roster_item {
+ my ($self, $jid, $contact_jid, $cb) = @_;
+
+ my $is_shared = sub {
+ my $jid = shift;
+ my $roster = $self->_roster();
+ foreach my $user (@$roster) {
+ if (lc $user->{jid} eq lc $jid->as_bare_string) { return 1; }
+ }
+ return 0;
+ };
+
+ if ($is_shared->($jid) && $is_shared->($contact_jid)) {
+ my $both = DJabberd::Subscription->new;
+ $both->set_from;
+ $both->set_to;
+ my $rit = DJabberd::RosterItem->new(jid => $contact_jid,
+ subscription => $both);
+ $cb->set($rit);
+ return;
+ }
+
+ $self->SUPER::load_roster_item($jid, $contact_jid, $cb);
+}
+
+=head1 COPYRIGHT & LICENSE
+
+Original work Copyright 2006 Alexander Karelas, Martin Atkins, Brad Fitzpatrick and Aleksandar Milanov. All rights reserved.
+Copyright 2007 Edward Rudd. All rights reserved.
+
+This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.
+
+=cut
+
+1;
--
cgit