Андрей (andy) wrote in changelog,
Андрей
andy
changelog

[livejournal] r22003: LJSUP-12255 (drop typepad antispam suppo...

Committer: ailyin
LJSUP-12255 (drop typepad antispam support)
U   trunk/bin/upgrading/update-db-general.pl
D   trunk/bin/worker/antispam
D   trunk/cgi-bin/LJ/AntiSpam.pm
U   trunk/cvs/multicvs.conf
D   trunk/htdocs/admin/antispam.bml
Modified: trunk/bin/upgrading/update-db-general.pl
===================================================================
--- trunk/bin/upgrading/update-db-general.pl	2012-05-18 14:50:05 UTC (rev 22002)
+++ trunk/bin/upgrading/update-db-general.pl	2012-05-21 07:32:59 UTC (rev 22003)
@@ -72,28 +72,6 @@
 )
 EOC
 
-register_tablecreate('antispam', <<'EOC');
-CREATE TABLE `antispam` (
-  `journalid` int(10) unsigned NOT NULL,
-  `itemid` int(10) unsigned NOT NULL DEFAULT '0',
-  `type` char(1) NOT NULL,
-  `posterid` int(10) unsigned NOT NULL DEFAULT '0',
-  `eventtime` date DEFAULT NULL,
-  `poster_ip` char(15) DEFAULT NULL,
-  `email` char(50) DEFAULT NULL,
-  `user_agent` varchar(128) DEFAULT NULL,
-  `uniq` char(15) DEFAULT NULL,
-  `spam` tinyint(3) unsigned DEFAULT NULL,
-  `confidence` float(4,3) unsigned DEFAULT NULL,
-  `review` char(1) DEFAULT NULL,
-  PRIMARY KEY (`journalid`,`itemid`,`type`),
-  KEY `posterid` (`posterid`,`eventtime`),
-  KEY `spam` (`spam`),
-  KEY `review` (`review`),
-  KEY `eventtime` (`eventtime`)
-)
-EOC
-
 register_tablecreate('authactions', <<'EOC');
 CREATE TABLE `authactions` (
   `aaid` int(10) unsigned NOT NULL AUTO_INCREMENT,
@@ -3513,6 +3491,7 @@
 register_tabledrop("userpic_comment");
 register_tabledrop("events");
 register_tabledrop("randomuserset");
+register_tabledrop("antispam");
 
 ### changes
 
@@ -4388,14 +4367,6 @@
                  "ADD revid int unsigned default null");
     }
 
-    unless (column_type("antispam", "eventtime") eq 'date') {
-        do_alter("antispam",
-                 "ALTER TABLE antispam " .
-                 "MODIFY eventtime DATE DEFAULT NULL");
-        do_alter("antispam",
-                 "ALTER TABLE antispam ADD INDEX(eventtime)");
-    }
-
     unless (column_type("site_messages", "countries")) {
         do_alter("site_messages",
                  "ALTER TABLE site_messages " .

Deleted: trunk/bin/worker/antispam
===================================================================
--- trunk/bin/worker/antispam	2012-05-18 14:50:05 UTC (rev 22002)
+++ trunk/bin/worker/antispam	2012-05-21 07:32:59 UTC (rev 22003)
@@ -1,100 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use lib "$ENV{LJHOME}/cgi-bin";
-require 'ljlib.pl';
-use LJ::AntiSpam;
-
-#
-# TPAS_KEY and TPAS_SERVER must be specified in config.
-#
-
-package LJ::NewWorker::TheSchwartz::AntiSpam;
-use base 'LJ::NewWorker::TheSchwartz';
-sub capabilities { 'LJ::Worker::AntiSpam' }
-__PACKAGE__->start();
-
-package LJ::Worker::AntiSpam;
-use base 'TheSchwartz::Worker';
-use Net::Akismet::TPAS;
-
-sub work {
-    my ($class, $job) = @_;
-    my $a  = $job->arg;
-
-    my $jid     = $a->{journalid};
-    my $itemid = $a->{itemid};
-    my $server  = $a->{server};
-    my $posterid = $a->{posterid};
-    my $uniq = $a->{remote_uniq};
-    my $email; # $a->{email} Not for use with an external spam service
-    my $ju      = LJ::load_userid($jid)
-        or die "No user able to be loaded\n";
-    my $content;
-
-    # Journal Entry
-    if ($a->{type} eq 'E') {
-        my $entry  = LJ::Entry->new($ju, jitemid => $itemid);
-
-        unless ($entry->valid && $entry->security eq "public") {
-            $job->completed;
-            return;
-        }
-        $content = $entry->event_html;
-    # Comment
-    } elsif ($a->{type} eq 'C') {
-        my $comment = LJ::Comment->new($ju, jtalkid => $itemid);
-
-        unless ($comment->valid && $comment->visible_to(undef)) {
-            $job->completed;
-            return;
-        }
-        $content = $comment->body_html;
-    }
-
-    my $url      = LJ::journal_base($ju) . "/";
-    my $name     = $ju->prop("journaltitle") || $ju->{name} || $ju->{user};
-
-    my $poster = LJ::load_userid($posterid);
-
-    unless ($content) {
-        $job->completed;
-        return;
-    }
-
-    # Setup key for TypePad
-    my $tpas = Net::Akismet::TPAS->new(
-                KEY => $LJ::TPAS_KEY->($posterid),
-                URL => $url,
-                SERVER => $LJ::TPAS_SERVER,
-                STRICT => 0,
-                VERIFY_KEY => 0,
-               ) or die "Key verification failure!";
-
-    my $verdict= $tpas->check(
-                    USER_IP                 => $a->{remote_ip},
-                    COMMENT_USER_AGENT      => $a->{remote_ua},
-                    COMMENT_CONTENT         => $content,
-                    COMMENT_AUTHOR          => $poster->user,
-                    COMMENT_AUTHOR_EMAIL    => $email,
-                ) or die "Failed to get response from antispam server.\n";
-
-    # How certain is the verdict
-    my $score = $tpas->get_confidence;
-    my $is_spam = $verdict eq 'true' ? 1 :0;
-
-    LJ::AntiSpam->create( journalid => $jid, itemid => $itemid,
-                          type => $a->{type}, posterid => $posterid,
-                          eventtime => $a->{timepost},
-                          poster_ip => $a->{remote_ip}, email => $email,
-                          user_agent => $a->{remote_ua}, uniq => $uniq,
-                          spam => $is_spam, confidence => $score );
-
-    $job->completed;
-    return;
-}
-
-sub keep_exit_status_for { 0 }
-sub grab_for { 60 }
-sub max_retries { 3 }
-sub retry_delay { 100 }
-

Deleted: trunk/cgi-bin/LJ/AntiSpam.pm
===================================================================
--- trunk/cgi-bin/LJ/AntiSpam.pm	2012-05-18 14:50:05 UTC (rev 22002)
+++ trunk/cgi-bin/LJ/AntiSpam.pm	2012-05-21 07:32:59 UTC (rev 22003)
@@ -1,346 +0,0 @@
-#
-# LiveJournal AntiSpam Object
-#
-# Is a given entry or comment spam? Store the verdict and related data.
-#
-
-package LJ::AntiSpam;
-use strict;
-use Net::Akismet::TPAS;
-use Carp qw/ croak cluck /;
-use LJ::TimeUtil;
-
-my @cols = qw( itemid type posterid journalid eventtime poster_ip email user_agent uniq spam confidence );
-my @extra_cols = qw( review );
-
-# Constructor
-sub new {
-    my $class = shift;
-
-    my $n_arg   = scalar @_;
-    croak("wrong number of arguments")
-        unless $n_arg && ($n_arg % 2 == 0);
-
-    my %opts = @_;
-
-    my $self = bless {
-        # arguments
-        journalid  => delete $opts{journalid},
-        itemid     => delete $opts{itemid},
-        type       => delete $opts{type},
-    };
-
-    croak("need to supply journalid") unless defined $self->{journalid};
-    croak("need to supply itemid") unless defined $self->{itemid};
-    croak("need to supply type") unless defined $self->{type};
-
-    croak("unknown parameters: " . join(", ", keys %opts))
-        if %opts;
-
-    return $self;
-}
-
-# Create a new AntiSpam object
-sub create {
-    my $class = shift;
-    my $self  = bless {};
-
-    my %opts = @_;
-    foreach my $f (@cols) {
-        croak("need to supply $f") unless exists $opts{$f};
-        $self->{$f} = delete $opts{$f};
-    }
-
-    croak("unknown parameters: " . join(", ", keys %opts))
-        if %opts;
-
-    my $dbh = LJ::get_db_writer()
-        or die "unable to contact global db master to create antispam entry";
-
-    $dbh->do("REPLACE INTO antispam VALUES (?,?,?,?,?,?,?,?,?,?,?,NULL)",
-             undef, $self->{journalid}, $self->{itemid}, $self->{type},
-             $self->{posterid}, LJ::TimeUtil->mysql_time($self->{eventtime}, 1),
-             $self->{poster_ip}, $self->{email}, $self->{user_agent},
-             $self->{uniq}, $self->{spam}, $self->{confidence} );
-    die $dbh->errstr if $dbh->err;
-
-    $self = $class->new( journalid => $self->{journalid},
-                         itemid => $self->{itemid}, type => $self->{type} );
-    return $self;
-}
-
-sub load_recent {
-    my $class = shift;
-    my %opts = @_;
-    my $type = (exists $opts{type}) ? $opts{type} : 'E'; # default to entries
-    my $reviewed = $opts{reviewed} || 0;
-    my $limit = $opts{limit} || 50;
-
-    my $hours = 3600 * 24; # 24 hours
-
-    my $dbh = LJ::get_db_reader()
-        or die "unable to contact global db slave to load antispam";
-
-    my $sth;
-    my $ago = LJ::TimeUtil->mysql_time(time() - $hours, 1);
-    my $xsql = "AND type='$type' ";
-    $xsql .= "ORDER BY eventtime DESC";
-    $xsql .= " LIMIT $limit";
-
-    # Retrieve all antispam
-    if ($reviewed) {
-        $sth = $dbh->prepare("SELECT * FROM antispam WHERE eventtime > ? $xsql");
-
-    # Retrieve all anitspam not yet reviewed
-    } else {
-        $sth = $dbh->prepare("SELECT * FROM antispam WHERE eventtime > ? " .
-                             "AND review IS NULL $xsql");
-    }
-    $sth->execute($ago);
-    die $dbh->errstr if $dbh->err;
-
-    my @antispams;
-    while (my $row = $sth->fetchrow_hashref) {
-        my $as = $class->new( journalid => $row->{journalid},
-                              itemid => $row->{itemid},
-                              type => $row->{type} );
-        $as->absorb_row($row);
-
-        push @antispams, $as;
-    }
-
-    return @antispams;
-}
-
-sub load_row {
-    my $self = shift;
-    return 1 if $self->{_loaded_row};
-
-    my $dbh = LJ::get_db_reader()
-        or die "unable to contact global db slave to load antispam";
-
-    my $sth = $dbh->prepare("SELECT * FROM antispam WHERE journalid=? AND " .
-                            "itemid=? AND type=?");
-    $sth->execute($self->{journalid}, $self->{itemid}, $self->{type});
-    die $dbh->errstr if $dbh->err;
-
-    $self->absorb_row($sth->fetchrow_hashref);
-}
-
-sub absorb_row {
-    my ($self, $row) = @_;
-
-    $self->{$_} = $row->{$_} foreach @cols;
-    $self->{$_} = $row->{$_} foreach @extra_cols;
-
-    $self->{_loaded_row} = 1;
-
-    return 1;
-}
-
-sub _get_set {
-    my $self = shift;
-    my $key  = shift;
-
-    if (@_) { # setter case
-        my $val = shift;
-
-        my $dbh = LJ::get_db_writer()
-            or die "unable to contact global db master to load category";
-
-        $dbh->do("UPDATE antispam SET $key=? WHERE journalid=? AND itemid=? " .
-                 "AND type=?", undef, $val, $self->{journalid},
-                 $self->{itemid}, $self->{type});
-        die $dbh->errstr if $dbh->err;
-
-        return $self->{$key} = $val;
-    }
-
-    # getter case
-    $self->load_row unless $self->{_loaded_row};
-
-    return $self->{$key};
-}
-
-sub journalid   { shift->_get_set('journalid')  }
-sub itemid      { shift->_get_set('itemid')     }
-sub type        { shift->_get_set('type')       }
-sub posterid    { shift->_get_set('posterid')   }
-sub eventtime   { shift->_get_set('eventtime')  }
-sub poster_ip   { shift->_get_set('poster_ip')  }
-sub email       { shift->_get_set('email')      }
-sub user_agent  { shift->_get_set('user_agent') }
-sub uniq        { shift->_get_set('uniq')       }
-sub spam        { shift->_get_set('spam')       }
-sub confidence  { shift->_get_set('confidence') }
-sub review      { shift->_get_set('review')     }
-sub set_review  { shift->_get_set('review' => $_[0]) }
-
-
-sub column_list { return @cols }
-
-#############################
-# Comment/Entry related subs
-#
-
-sub is_entry {
-    my $self = shift;
-
-    return $self->type eq 'E' ? 1 : 0;
-}
-
-sub is_comment {
-    my $self = shift;
-
-    return $self->type eq 'C' ? 1 : 0;
-}
-
-# This can be an Entry or Comment object
-sub _post {
-    my $self = shift;
-
-    return $self->{_post} if $self->{_post};
-
-    if ($self->is_entry) {
-        $self->{_post} = LJ::Entry->new($self->journalid, jitemid => $self->itemid);
-    } elsif ($self->is_comment) {
-        $self->{_post} = LJ::Comment->new($self->journalid, jtalkid => $self->itemid);
-    }
-
-    return $self->{_post};
-}
-
-sub valid_post {
-    my $self = shift;
-
-    # valid is a method common to Entry and Comment objects
-    return $self->_post->valid;
-}
-
-sub url {
-    my $self = shift;
-
-    # url is a method common to Entry and Comment objects
-    return $self->_post->url;
-}
-
-sub subject {
-    my $self = shift;
-
-    # subject_html is a method common to Entry and Comment objects
-    return $self->_post->subject_html;
-}
-
-sub body {
-    my $self = shift;
-
-    if ($self->is_entry) {
-        return $self->_post->event_html;
-    } elsif ($self->is_comment) {
-        return $self->_post->body_html;
-    }
-}
-
-sub post_time {
-    my $self = shift;
-
-    if ($self->is_entry) {
-        return $self->_post->eventtime_mysql;
-    } elsif ($self->is_comment) {
-        return LJ::TimeUtil->mysql_time($self->_post->unixtime);
-    }
-}
-
-#
-#######################################
-
-################################
-# Review subs
-
-# Set review as 'T' for True.
-sub mark_reviewed {
-    my $class = shift;
-    my @recs = @_;
-
-    foreach my $rec (@recs) {
-        my $as = LJ::AntiSpam->new(journalid => $rec->{journalid},
-                                   itemid => $rec->{itemid},
-                                   type => $rec->{type} );
-        $as->set_review('T');
-    }
-}
-
-sub mark_false_neg {
-    my $class = shift;
-    return $class->_mark_false_do("false_neg", @_);
-}
-
-sub mark_false_pos {
-    my $class = shift;
-    return $class->_mark_false_do("false_pos", @_);
-}
-
-sub _mark_false_do {
-    my $class = shift;
-    my $sign = shift;
-    my @recs = @_;
-
-    foreach my $rec (@recs) {
-        my $as = LJ::AntiSpam->new(journalid => $rec->{journalid},
-                                   itemid => $rec->{itemid},
-                                   type => $rec->{type} );
-        my $ju = LJ::load_userid($as->journalid);
-        my $poster = LJ::load_userid($as->posterid);
-        my $content;
-
-        if ($as->type eq 'E') {
-            my $entry = LJ::Entry->new($ju, jitemid => $as->itemid);
-            $content = $entry->event_html;
-        } elsif ($as->type eq 'C') {
-            my $comment = LJ::Comment->new($ju->userid, jtalkid => $as->itemid);
-            $content = $comment->body_html;
-        }
-
-        my $tpas = LJ::AntiSpam->tpas($as->posterid, LJ::journal_base($ju) . "/");
-
-        if ($sign eq 'false_neg' && !$as->spam) {
-            my $feedback = $tpas->spam(
-                            USER_IP                 => $as->poster_ip,
-                            COMMENT_USER_AGENT      => $as->user_agent,
-                            COMMENT_CONTENT         => $content,
-                            COMMENT_AUTHOR          => $poster->user,
-                            COMMENT_AUTHOR_EMAIL    => $as->email,
-                           ) or die "Failed to get response from antispam server.\n";
-        } elsif ($sign eq 'false_pos' && $as->spam) {
-            my $feedback = $tpas->ham(
-                            USER_IP                 => $as->poster_ip,
-                            COMMENT_USER_AGENT      => $as->user_agent,
-                            COMMENT_CONTENT         => $content,
-                            COMMENT_AUTHOR          => $poster->user,
-                            COMMENT_AUTHOR_EMAIL    => $as->email,
-                           ) or die "Failed to get response from antispam server.\n";
-        }
-        $as->set_review('F');
-    }
-}
-
-#
-###############################
-
-sub tpas {
-    my $class = shift;
-    my $uid = shift;
-    my $url = shift;
-
-    my $tpas = Net::Akismet::TPAS->new(
-                KEY => $LJ::TPAS_KEY->($uid),
-                URL => $url,
-                SERVER => $LJ::TPAS_SERVER,
-                STRICT => 0,
-                VERIFY_KEY => 0,
-               ) or die "Key verification failure!";
-
-    return $tpas;
-}
-
-1;

Modified: trunk/cvs/multicvs.conf
===================================================================
--- trunk/cvs/multicvs.conf	2012-05-18 14:50:05 UTC (rev 22002)
+++ trunk/cvs/multicvs.conf	2012-05-21 07:32:59 UTC (rev 22003)
@@ -33,7 +33,6 @@
 SVN(Test-FakeApache)      = http://code.livejournal.org/svn/Test-FakeApache/trunk/
 SVN(LJ-UserSearch)        = http://code.livejournal.org/svn/LJ-UserSearch/trunk/
 SVN(TheSchwartz-Worker-SendEmail) = http://code.livejournal.org/svn/TheSchwartz-Worker-SendEmail/trunk/
-SVN(antispam)             = http://code.sixapart.com/svn/antispam/trunk/lib/Net/
 
 livejournal                                   .
 
@@ -73,8 +72,6 @@
 
 dmtp/server/dmtpd                             bin/dmtpd
 
-antispam/Akismet                              cgi-bin/Net/Akismet
-
 mogilefs/api/perl/MogileFS-Client/lib         cgi-bin
 mogilefs/utils/mogadm                         bin/mogadm
 mogilefs/utils/mogtool                        bin/mogtool

Deleted: trunk/htdocs/admin/antispam.bml
===================================================================
--- trunk/htdocs/admin/antispam.bml	2012-05-18 14:50:05 UTC (rev 22002)
+++ trunk/htdocs/admin/antispam.bml	2012-05-21 07:32:59 UTC (rev 22003)
@@ -1,157 +0,0 @@
-<?page
-title=>Latest AntiSpam Posts
-head<=
-<style>
- table td { vertical-align: top; }
- .verdict { font-weight: bold; text-align: center; }
- .spam0 { background-color: #33ff33; color: #fff; }
- .spam1 { background-color: #dd0000; color: #000; }
- </style>
- <=head
-body<=
-<?_code
-{
-    use strict;
-    use vars qw(%GET %POST $title $headextra @errors @warnings);
-    use Class::Autouse qw(LJ::AntiSpam);
-
-    my $remote = LJ::get_remote();
-
-    return "<?needlogin?>"
-        unless $remote;
-
-    return "You are not allowed to view this page"
-        unless LJ::check_priv($remote, 'supporthelp', 'antispam');
-
-    my $ret;
-    my $type = $GET{type} || $POST{type} || undef;
-    $type = 'E' unless ($type =~ /[EC]/);
-
-    if (LJ::did_post() && $POST{mode} eq 'review') {
-        push @errors, "Invalid form submission" unless LJ::check_form_auth();
-
-        my @correct; # list of correct verdicts
-        my @false_neg; # list of false negatives for spam
-        my @false_pos; # list of false positives for ham
-        my $changes;
-
-        foreach (grep { /^review_/} keys %POST) {
-            $changes = 1;
-            my $as = $_;
-            $as =~ s/^review_//;
-            my ($spam, $jid, $type, $itemid) = split('-', $as);
-            if ($POST{$_} eq '1') {
-                push @correct,
-                     {journalid => $jid, type => $type, itemid => $itemid};
-            } elsif ($POST{$_} eq '0') {
-                if ($spam) {
-                    push @false_pos, {journalid => $jid, type => $type,
-                                      itemid => $itemid};
-                } else {
-                    push @false_neg, {journalid => $jid, type => $type,
-                                      itemid => $itemid};
-                }
-            }
-        }
-
-        LJ::AntiSpam->mark_reviewed(@correct) if (@correct);
-        LJ::AntiSpam->mark_false_neg(@false_neg) if (@false_neg);
-        LJ::AntiSpam->mark_false_pos(@false_pos) if (@false_pos);
-
-        unless (@errors) {
-            if ($changes) {
-                $ret .= "<span class='super notice'>Reviews saved.</span>";
-            } else {
-                $ret .= "<span class='super notice'>No changes.</span>";
-            }
-            $ret .= "<p><a href=''>Review more AntiSpam</a></p>";
-        }
-
-        return $ret;
-    }
-
-    my @posts = LJ::AntiSpam->load_recent(type => $type);
-    my @cols = LJ::AntiSpam->column_list;
-
-    $ret .= "<form method='POST'>\n";
-    $ret .= LJ::form_auth();
-    $ret .= "<p>Display ";
-    $ret .= LJ::html_select({ name => 'type',
-                              selected => $type || undef,
-                }, ('E', 'Entries', 'C', 'Comments') );
-    $ret .= "<br />" . LJ::html_submit('mode', 'Refresh');
-    $ret .= "</p></form>";
-
-    unless (@posts) {
-        $ret .= "No recent posts to review";
-        return $ret;
-    }
-
-    $ret .= "<form method='POST'>\n";
-    $ret .= LJ::form_auth();
-    $ret .= LJ::html_hidden(mode => 'review');
-    $ret .= "<p style='text-align: center'>" . LJ::html_submit('submit', 'Submit') . "</p>";
-    $ret .= "<table border=1>";
-    foreach my $p (@posts) {
-        next unless $p->valid_post;
-        $ret .= "<tr><td width='350'>";
-
-        # Left Column
-        # Top of cell indicating result
-        $ret .= "<div class='verdict spam".$p->{spam}."'>";
-        $ret .= $p->{spam} ? "SPAM" : "Yummy Ham";
-        $ret .= "</div>\n";
-
-        foreach my $c (@cols) {
-            $ret .= "<b>$c:</b> " . $p->$c . "<br />";
-        }
-        my $uj = LJ::want_user($p->journalid);
-        my $up = LJ::want_user($p->posterid);
-        my $url = $p->url;
-        my $subject = $p->subject;
-        my $body = $p->body;
-
-        # Middle Column
-        $ret .= "</td><td width=80>";
-        my $asid = $p->spam . "-" . $p->journalid . "-" . $p->type . "-" . $p->itemid;
-        $ret .= "<div><label for='true_$asid'>";
-        $ret .= LJ::html_check({ name => "review_$asid", id => "true_$asid",
-                                 type => 'radio', value => 1, });
-        $ret .= " TRUE";
-        $ret .= "</label></div><br />\n";
-
-        $ret .= "<div><label for='false_$asid'>";
-        $ret .= LJ::html_check({ name => "review_$asid", id => "false_$asid",
-                                 type => 'radio', value => 0, });
-        $ret .= " FALSE";
-        $ret .= "</label></div>\n";
-
-        # Right Column
-        $ret .= "</td><td>";
-
-        $ret .= "<a href=\"$url\">" .
-                $p->post_time .
-                "</a><br />\n";
-        $ret .= LJ::ljuser($up->{user});
-        if ($up->{userid} != $uj->{userid}) {
-            $ret .= " (in " . LJ::ljuser($uj->{user}, {type => $uj->{journaltype}}) . ")";
-        }
-        $ret .= ":<br />\n";
-
-        $ret .= "<div class='entry'>";
-        $ret .= "<h3>$subject</h3>\n" if $subject;
-        $ret .= $body . "</div>";
-        $ret .= "</td></tr>\n";
-    }
-    $ret .= "</table>";
-
-    $ret .= "<p style='text-align: center'>" . LJ::html_submit('submit', 'Submit') . "</p>";
-
-    $ret .= "</form>";
-
-    return $ret;
-}
-_code?>
-
-<=body
-page?>

Tags: ailyin, andy, bml, conf, livejournal, pl, pm
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments