This commit is contained in:
2019-02-06 00:49:12 +03:00
commit 8dbb1bb605
4796 changed files with 506072 additions and 0 deletions

206
local/bin/checkconfig.pl Executable file
View File

@@ -0,0 +1,206 @@
#!/usr/bin/perl
#
my @errors;
my $err = sub {
return unless @_;
die "Problem:\n" . join('', map { " * $_\n" } @_);
};
my %dochecks; # these are the ones we'll actually do
my @checks = ( # put these in the order they should be checked in
"modules",
"modules_print",
"env",
"database"
);
foreach my $check (@checks) { $dochecks{$check} = 1; }
my $only = 0;
arg: foreach my $arg (@ARGV) {
($w, $c) = ($arg =~ /^-(no|only)(.*)/) or die "unknown option $arg";
die "only one '-onlyfoo' option may be specified" if $w eq "only" and $only++;
foreach my $check (@checks) {
if ($check eq $c) {
if ($w eq "only") { %dochecks = ( $check => 1 ); }
else { $dochecks{$check} = 0 }
next arg;
}
}
die "unknown check '$c' (known checks: " . join(", ", @checks) . ")\n";
}
my %modules = (
"DBI" => { 'deb' => 'libdbi-perl', },
"DBD::mysql" => { 'deb' => 'libdbd-mysql-perl', },
"Digest::MD5" => { 'deb' => 'libdigest-md5-perl', },
"Digest::SHA1" => { 'deb' => 'libdigest-sha1-perl', },
"Image::Size" => { 'deb' => 'libimage-size-perl', },
"MIME::Lite" => { 'deb' => 'libmime-lite-perl', },
"MIME::Words" => { 'deb' => 'libmime-perl', },
"Compress::Zlib" => { 'deb' => 'libcompress-zlib-perl', },
"Net::SMTP" => {
'deb' => 'libnet-perl',
'opt' => "Alternative to piping into sendmail to send mail.",
},
"Net::DNS" => {
'deb' => 'libnet-dns-perl',
},
"MIME::Base64" => { 'deb' => 'libmime-base64-perl' },
"URI::URL" => { 'deb' => 'liburi-perl' },
"HTML::Tagset" => { 'deb' => 'libhtml-tagset-perl' },
"HTML::Parser" => { 'deb' => 'libhtml-parser-perl', },
"LWP::Simple" => { 'deb' => 'libwww-perl', },
"LWP::UserAgent" => { 'deb' => 'libwww-perl', },
"GD" => { 'deb' => 'libgd-perl' },
"GD::Graph" => {
'deb' => 'libgd-graph-perl',
'opt' => 'Required to make graphs for the statistics page.',
},
"Mail::Address" => { 'deb' => 'libmailtools-perl', },
"Proc::ProcessTable" => {
'deb' => 'libproc-process-perl',
'opt' => "Better reliability for starting daemons necessary for high-traffic installations.",
},
"RPC::XML" => {
'deb' => 'librpc-xml-perl',
'opt' => 'Required for outgoing XMLRPC support',
},
"SOAP::Lite" => {
'deb' => 'libsoap-lite-perl',
'opt' => 'Required for XML-RPC support.',
},
"Unicode::MapUTF8" => { 'deb' => 'libunicode-maputf8-perl', },
"Storable" => {
'deb' => 'libstorable-perl',
},
"XML::RSS" => {
'deb' => 'libxml-rss-perl',
'opt' => 'Required for retrieving RSS off of other sites (syndication).',
},
"XML::Simple" => {
'deb' => 'libxml-simple-perl',
'ver' => 2.12,
},
"String::CRC32" => {
'deb' => 'libstring-crc32-perl',
'opt' => 'Required for palette-altering of PNG files. Only necessary if you plan to make your own S2 styles that use PNGs, not GIFs.',
},
"Time::HiRes" => { 'deb' => 'libtime-hires-perl' },
"IO::WrapTie" => { 'deb' => 'libio-stringy-perl' },
"XML::Atom" => {
'deb' => 'libxml-atom-perl',
'opt' => 'Required for AtomAPI support.',
},
"Math::BigInt::GMP" => {
'opt' => 'Aides Crypt::DH so it isn\'t crazy slow.',
},
"URI::Fetch" => {
'opt' => 'Required for OpenID support.',
},
"Crypt::DH" => {
'opt' => 'Required for OpenID support.',
},
);
sub check_modules_print {
print "[Printing required Perl Modules...]\n";
foreach my $mod (sort keys %modules) {
print $mod .
($modules{$mod}->{'ver'} ? " >= " . $modules{$mod}->{'ver'} : "") .
($modules{$mod}->{'opt'} ? " -- " . $modules{$mod}->{'opt'} : "") .
"\n";
}
}
sub check_modules {
print "[Checking for Perl Modules....]\n";
my @debs;
foreach my $mod (sort keys %modules) {
my $rv = eval "use $mod;";
if ($@) {
my $dt = $modules{$mod};
if ($dt->{'opt'}) {
print STDERR "Missing optional module $mod: $dt->{'opt'}\n";
} else {
push @errors, "Missing perl module: $mod";
}
push @debs, $dt->{'deb'} if $dt->{'deb'};
next;
}
my $ver_want = $modules{$mod}{ver};
my $ver_got = $mod->VERSION;
if ($ver_want && $ver_got && $ver_got < $ver_want) {
push @errors, "Out of date module: $mod (need $ver_want, $ver_got installed)";
}
}
if (@debs && -e '/etc/debian_version') {
print STDERR "\n# apt-get install ", join(' ', @debs), "\n\n";
}
$err->(@errors);
}
sub check_env {
print "[Checking LJ Environment...]\n";
$err->("\$LJHOME environment variable not set.")
unless $ENV{'LJHOME'};
$err->("\$LJHOME directory doesn't exist ($ENV{'LJHOME'})")
unless -d $ENV{'LJHOME'};
# before ljconfig.pl is called, we want to call the site-local checkconfig,
# otherwise ljconfig.pl might load ljconfig-local.pl, which maybe load
# new modules to implement site-specific hooks.
my $local_config = "$ENV{'LJHOME'}/bin/checkconfig-local.pl";
if (-e $local_config) {
my $good = eval { require $local_config; };
exit 1 unless $good;
}
$err->("No ljconfig.pl file found at $ENV{'LJHOME'}/cgi-bin/ljconfig.pl")
unless -e "$ENV{'LJHOME'}/cgi-bin/ljconfig.pl";
eval { require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl"; };
$err->("Failed to load ljlib.pl: $@") if $@;
# if SMTP_SERVER is set, then Net::SMTP is required, not optional.
if ($LJ::SMTP_SERVER && ! defined $Net::SMTP::VERSION) {
$err->("Net::SMTP isn't available, and you have \$LJ::SMTP_SERVER set.");
}
}
sub check_database {
print "[Checking Database...]\n";
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
my $dbh = LJ::get_dbh("master");
unless ($dbh) {
$err->("Couldn't get master database handle.");
}
foreach my $c (@LJ::CLUSTERS) {
my $dbc = LJ::get_cluster_master($c);
next if $dbc;
$err->("Couldn't get db handle for cluster \#$c");
}
if (%LJ::MOGILEFS_CONFIG && $LJ::MOGILEFS_CONFIG{hosts}) {
print "[Checking MogileFS client.]\n";
my $mog = LJ::mogclient();
die "Couldn't create mogilefs client." unless $mog;
}
}
foreach my $check (@checks) {
next unless $dochecks{$check};
my $cn = "check_".$check;
&$cn;
}
print "All good.\n";
print "NOTE: checkconfig.pl doesn't check everything yet\n";

View File

@@ -0,0 +1,84 @@
#!/usr/bin/perl
# remote user id of user to clean
my $ru_id = 491;
# database connection
my $queue_db = "livejournal";
my $queue_host = "localhost";
my $queue_login = "lj";
my $queue_pass = "lj-upyri";
use strict; # preventing my program from doing bad things
use DBI; # http://dbi.perl.org
$| = 1; # unbuffered (almost) output
my $dbh = DBI->connect(
"DBI:mysql:$queue_db:$queue_host",
$queue_login, $queue_pass,
{RaiseError => 0, AutoCommit => 1}
) || die "Can't open database connection: $DBI::errstr";
my $sth = $dbh->prepare("select * from ljr_remote_users where ru_id = $ru_id");
$sth->execute;
while (my $row = $sth->fetchrow_hashref) {
if ($row->{created_comments_maxid} > 0) {
die "User has created comments. Cannot clean cached comments (IMPLEMENT THIS!)\n";
}
my $sth1 = $dbh->prepare("select * from ljr_cached_users where ru_id = $ru_id");
$sth1->execute();
my $row1 = $sth1->fetchrow_hashref;
print
"You're about to delete cached comments for user [" .
$row1->{remote_username} . "].\n" .
"Please confirm by typing their username: "
;
while (<>) {
my $iu = $_;
if ($iu =~ /\s*(.*)\s*/) {
$iu = $1;
}
if ($iu ne $row1->{remote_username}) {
die "You have to learn to type letters to use this tool.\n";
}
last;
}
$sth1->finish;
print "deleting cached comprops...\n";
$sth1 = $dbh->prepare("select * from ljr_cached_comments where ru_id = $ru_id");
$sth1->execute();
while ($row1 = $sth1->fetchrow_hashref) {
my $sth2 = $dbh->prepare(
"delete from ljr_cached_comprops where cc_id = " . $row1->{cc_id}
);
$sth2->execute();
$sth2->finish;
print ".";
}
$sth1->finish;
print "deleting cached comments...\n";
$sth1 = $dbh->prepare(
"delete from ljr_cached_comments where ru_id = " . $ru_id
);
$sth1->execute();
$sth1->finish;
print "resetting cached counters...\n";
$sth1 = $dbh->prepare(
"update ljr_cached_users
set remote_meta_maxid = 0, cached_comments_maxid = 0
where ru_id = " . $ru_id);
$sth1->execute();
$sth1->finish;
}
$sth->finish;
$dbh->disconnect;

View File

@@ -0,0 +1,94 @@
#!/usr/bin/perl
# database connection
my $queue_db = "livejournal";
my $queue_host = "localhost";
my $queue_login = "lj";
my $queue_pass = "lj-upyri";
use strict; # preventing my program from doing bad things
use DBI; # http://dbi.perl.org
$| = 1; # unbuffered (almost) output
my $dbh = DBI->connect(
"DBI:mysql:$queue_db:$queue_host",
$queue_login, $queue_pass,
{RaiseError => 0, AutoCommit => 1}
) || die "Can't open database connection: $DBI::errstr";
my $username;
my $new_identity;
my $sth = $dbh->prepare(
"select * from identitymap where idtype='O' and identity like 'http://www.livejournal.com/%'");
$sth->execute;
while (my $row = $sth->fetchrow_hashref) {
$username = "";
if ($row->{"identity"} =~ /\/users\/(.+[^\/])\/??/ || $row->{"identity"} =~ /\/\~(.+[^\/])\/??/) {
my $new_id;
my $old_email;
my $new_email;
my $sth2;
$username = $1;
$new_identity = "";
if ($username =~ /^_/ || $username =~ /_$/) {
$new_identity = "http://users.livejournal.com/" . $username . "/";
}
else {
$new_identity = "http://" . $username . ".livejournal.com/";
}
$sth2 = $dbh->prepare("select email from user where userid = " . $row->{"userid"});
$sth2->execute;
if (my $row1 = $sth2->fetchrow_hashref) {
$old_email = $row1->{"email"};
}
$sth2->finish;
$sth2 = $dbh->prepare(
"select * from identitymap where idtype='O' and identity ='" . $new_identity . "'");
$sth2->execute();
if (my $row1 = $sth2->fetchrow_hashref) {
$new_id = $row1->{"userid"};
my $sth3 = $dbh->prepare("select email from user where userid = " . $new_id);
$sth3->execute;
if (my $row2 = $sth3->fetchrow_hashref) {
$new_email = $row2->{"email"};
}
$sth3->finish;
print
$username . "(" .
$row->{"userid"} . ", " . $old_email . "):(" .
$new_id . "," . $new_email . ")\n";
}
$sth2->finish;
if (!$new_id) {
$sth2 = $dbh->prepare(
"update identitymap set identity = '" . $new_identity . "' " .
"where idtype='O' and userid = " . $row->{"userid"}
);
$sth2->execute();
$sth2->finish;
}
else {
if (!$new_email) {
$sth2 = $dbh->prepare("update user set email = '" . $old_email . "' " .
"where userid = " . $new_id);
$sth2->execute();
$sth2->finish;
}
}
}
}
$sth->finish;
$dbh->disconnect;

View File

@@ -0,0 +1,113 @@
#!/usr/bin/perl
use strict;
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
require "$ENV{'LJHOME'}/cgi-bin/talklib.pl";
# remote user id of user to clean
my $ru_id = 27850;
# database connection
my $queue_db = "livejournal";
my $queue_host = "localhost";
my $queue_login = "lj";
my $queue_pass = "lj-upyri";
use strict; # preventing my program from doing bad things
use DBI; # http://dbi.perl.org
$| = 1; # unbuffered (almost) output
my $dbh = DBI->connect(
"DBI:mysql:$queue_db:$queue_host",
$queue_login, $queue_pass,
{RaiseError => 0, AutoCommit => 1}
) || die "Can't open database connection: $DBI::errstr";
my $sth = $dbh->prepare("select * from ljr_remote_users where ru_id = $ru_id");
$sth->execute;
while (my $row = $sth->fetchrow_hashref) {
if (! $row->{ru_id}) {
die "User not found.\n";
}
my $sth1 = $dbh->prepare("select * from ljr_cached_users where ru_id = $ru_id");
$sth1->execute();
my $row1 = $sth1->fetchrow_hashref;
print
"You're about to delete user [" .
$row1->{remote_username} . "].\n" .
"Please confirm by typing their username: "
;
while (<>) {
my $iu = $_;
if ($iu =~ /\s*(.*)\s*/) { $iu = $1; }
if ($iu ne $row1->{remote_username}) {
die "You have to learn to type letters to use this tool.\n";
}
last;
}
$sth1->finish;
print "deleting cached comprops and remote comments...\n";
$sth1 = $dbh->prepare("select * from ljr_cached_comments where ru_id = $ru_id");
$sth1->execute();
while ($row1 = $sth1->fetchrow_hashref) {
my $sth2 = $dbh->prepare("delete from ljr_cached_comprops where cc_id = " . $row1->{cc_id});
$sth2->execute();
$sth2->finish;
$sth2 = $dbh->prepare("delete from ljr_remote_comments where cc_id = " . $row1->{cc_id});
$sth2->execute();
$sth2->finish;
print ".";
}
$sth1->finish;
print "deleting cached comments...\n";
$sth1 = $dbh->prepare("delete from ljr_cached_comments where ru_id = $ru_id");
$sth1->execute();
$sth1->finish;
print "deleting ljr_cached_userpics...\n";
$sth1 = $dbh->prepare("delete from ljr_cached_userpics where ru_id = $ru_id");
$sth1->execute();
$sth1->finish;
print "deleting ljr_cached_users...\n";
$sth1 = $dbh->prepare("delete from ljr_cached_users where ru_id = $ru_id");
$sth1->execute();
$sth1->finish;
print "deleting local entries...\n";
my $lu;
$sth1 = $dbh->prepare("select * from ljr_remote_entries where ru_id = $ru_id");
$sth1->execute();
while ($row1 = $sth1->fetchrow_hashref) {
$lu = LJ::load_userid($row1->{"local_journalid"}) unless $lu;
LJ::delete_entry($lu, $row1->{"local_jitemid"});
}
$sth1->finish;
print "deleting ljr_remote_entries...\n";
$sth1 = $dbh->prepare("delete from ljr_remote_entries where ru_id = $ru_id");
$sth1->execute();
$sth1->finish;
print "deleting ljr_remote_userpics...\n";
$sth1 = $dbh->prepare("delete from ljr_remote_userpics where ru_id = $ru_id");
$sth1->execute();
$sth1->finish;
}
$sth->finish;
$sth = $dbh->prepare("delete from ljr_remote_users where ru_id = $ru_id");
$sth->execute;
$sth->finish;
$dbh->disconnect;

View File

@@ -0,0 +1,26 @@
#!/usr/bin/perl -w
use strict;
use Simple; # corrected LJ::Simple
use XML::Parser;
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
require "$ENV{'LJHOME'}/cgi-bin/talklib.pl";
require "ljr-defaults.pl";
require "ljr-links.pl";
require LJR::Distributed;
require "ipics.pl";
#require "ijournal.pl";
#require "icomments.pl";
my $e = import_pics(
"http://www.livejournal.com",
"sharlei",
"",
"imp_5204",
"", 1);
print $e->{errtext} ."\n" if $e->{err};

View File

@@ -0,0 +1,50 @@
#!/usr/bin/perl -w
#
# replaces text in all journal entries. use with caution.
#
BEGIN {
$ENV{'LJHOME'} = "/home/lj-admin/lj";
};
use strict;
use lib $ENV{'LJHOME'}."/cgi-bin";
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
my $dbh = LJ::get_dbh("master");
my ($journal, $from_text, $to_text, $do) = @ARGV;
die("usage: $0 journal_name from_text to_text")
unless $journal && $from_text && $to_text;
$do = 'no' unless $do;
my $u = LJ::load_user($journal);
die("Invalid journal [$journal]") unless $u;
print "Loaded: $u->{'name'} [$u->{'userid'}] \n";
my $sth = $dbh->prepare("select * from logtext2 where journalid = ?");
$sth->execute($u->{'userid'});
while (my $r = $sth->fetchrow_hashref()) {
if ($r->{'event'} =~ /$from_text/) {
print "journal entry [$r->{'jitemid'}] matches\n";
# print "journal entry [$r->{'jitemid'}] matches:\n$r->{'event'}\n";
$r->{'event'} =~ s/$from_text/$to_text/g;
# print "replaced:\n$r->{'event'}\n\n";
if ($do eq 'process') {
$dbh->do("UPDATE logtext2 set event = ? where journalid=? and jitemid=?",
undef, $r->{'event'}, $r->{'journalid'}, $r->{'jitemid'});
if ($dbh->err) {
die("Error while updating entry [$r->{'jitemid'}]: " . $dbh->errstr);
}
}
}
}
print "do not forget to restart memcache" if $do eq 'process';
print "finished\n";

View File

@@ -0,0 +1,53 @@
#!/usr/bin/perl -w
#
# converts s1usercache and s1stylecache blob fields
# which store Storable::freeze data from ::freeze to ::nfreeze
#
# 14oct07 petya@nigilist.ru
# initial revision
#
sub convert {
my ($dbh, $table, $unique, $field) = @_;
print "convert $table.$field ($unique)\n";
my $sql = "select * from $table;";
my $sth = $dbh->prepare($sql) or die "preparing: ", $dbh->errstr;
$sth->execute or die "executing: ", $dbh->errstr;
while (my $row = $sth->fetchrow_hashref) {
if ($row->{"$field"}) {
my $obj = Storable::thaw($row->{"$field"});
if ($obj) {
print $row->{"$unique"} . "\n";
$dbh->do("UPDATE $table SET $field=? WHERE $unique=?", undef,
Storable::nfreeze($obj), $row->{"$unique"}) ||
die "Error updating $table. Unique id: " . $row->{"$unique"} . "\n";
}
}
}
print "\n";
}
use strict;
use DBI;
use Storable;
$ENV{'LJHOME'} = "/home/lj-admin";
do $ENV{'LJHOME'} . "/lj/cgi-bin/ljconfig.pl";
my $host = $LJ::DBINFO{'master'}->{'host'};
my $user = $LJ::DBINFO{'master'}->{'user'};
my $pwd = $LJ::DBINFO{'master'}->{'pass'};
my $db = "prod_livejournal";
$| = 1; # turn off buffered output
# connect to the database.
my $dbh = DBI->connect( "DBI:mysql:mysql_socket=/tmp/mysql.sock;hostname=$host;port=3306;database=$db", $user, $pwd)
or die "Connecting : $DBI::errstr\n ";
#convert ($dbh, "s1stylecache", "styleid", "vars_stor");
#convert ($dbh, "s1usercache", "userid", "color_stor");
#convert ($dbh, "s1usercache", "userid", "override_stor");

View File

@@ -0,0 +1,128 @@
#!/usr/bin/perl
use strict;
use XMLRPC::Lite;
use Digest::MD5 qw(md5_hex);
use DBI;
use Time::Local;
use lib "$ENV{'LJHOME'}/cgi-bin";
do $ENV{'LJHOME'} . "/cgi-bin/ljconfig.pl";
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
use LJR::Viewuserstandalone;
use LJR::Gate;
use LJR::Distributed;
#
#îÁÓÔÒÏÊËÉ
#
#ó×ÏÊÓÔ×Á ÓÏÅÄÉÎÅÎÉÑ Ó ÂÁÚÏÊ
my $qhost = $LJ::DBINFO{'master'}->{'host'};
my $quser = $LJ::DBINFO{'master'}->{'user'};
my $qpass = $LJ::DBINFO{'master'}->{'pass'};
my $qsock = $LJ::DBINFO{'master'}->{'sock'};
my $qport = $LJ::DBINFO{'master'}->{'port'};
my $dbh = DBI->connect(
"DBI:mysql:mysql_socket=$qsock;hostname=$qhost;port=$qport;database=prod_ljgate",
$quser, $qpass, ) || die localtime(time) . ": Can't connect to database\n";
my $dbhljr = DBI->connect(
"DBI:mysql:mysql_socket=$qsock;hostname=$qhost;port=$qport;database=prod_livejournal",
$quser, $qpass, ) || die localtime(time) . ": Can't connect to database\n";
my $get_our = sub {
my ($userid) = @_;
my $sqh = $dbh->prepare("SELECT * FROM our_user where userid=?");
$sqh->execute($userid);
my $res = $sqh->fetchrow_hashref;
$sqh->finish;
return $res;
};
my $get_alien = sub {
my ($userid) = @_;
my $sqh = $dbh->prepare("SELECT * FROM alien where alienid=?");
$sqh->execute($userid);
my $res = $sqh->fetchrow_hashref;
$sqh->finish;
return $res;
};
my $get_lj_user = sub {
my ($user) = @_;
$user =~ s/\-/\_/g;
my $sqh = $dbhljr->prepare("SELECT * FROM user where user=?");
$sqh->execute($user);
my $res = $sqh->fetchrow_hashref;
$sqh->finish;
return $res;
};
my $count_gated_records = sub {
my ($userid) = @_;
my $sqh = $dbh->prepare("SELECT count(*) FROM rlj_lj_id where userid=?");
$sqh->execute($userid);
my ($res) = $sqh->fetchrow_array;
$sqh->finish;
return $res;
};
my $sqh = $dbh->prepare("SELECT userid,alienid FROM rlj2lj");
$sqh->execute;
my $result;
while ($result = $sqh->fetchrow_hashref) {
my $our = $get_our->($result->{'userid'});
my $alien = $get_alien->($result->{'alienid'});
if ($our && $alien && $alien->{'alienpass'}) {
my $ljuser = $get_lj_user->($our->{'our_user'});
my $ru = LJR::Distributed::get_remote_server("www.livejournal.com");
die $ru->{"errtext"} if $ru->{"err"};
$ru->{'username'} = $alien->{'alien'};
$ru = LJR::Distributed::get_cached_user($ru);
die $ru->{"errtext"} if $ru->{"err"};
print
$our->{'our_user'} .
" -> " .
$alien->{'alien'} . " ($ru->{'ru_id'}) " . "pass: " . $alien->{'alienpass'} .
"\n"
;
my $r = LJR::Distributed::update_export_settings($our->{'our_user'}, $ru->{'ru_id'}, $alien->{'alienpass'});
die $r->{'errtext'} if $r->{'err'};
if ($ljuser) {
print "ljr id: " . $ljuser->{'userid'};
}
else {
print "ljr id: error";
}
print "; ";
my $gated_records = $count_gated_records->($our->{'userid'});
print $gated_records;
print "\n";
# my $xmlrpc = LJR::Gate::Authenticate ("www.livejournal.com",
# $alien->{'alien'}, $alien->{'alienpass'});
# if ($xmlrpc->{'err_text'}) {
# print "err\n";
# }
# else {
# print "ok\n";
# }
}
else {
print
$result->{'userid'} . "($our->{'our_user'})" . " -> " .
$result->{'alienid'} . "($alien->{'alien'})" . "\n"
;
}
}
$sqh->finish;
$dbh->disconnect;
$dbhljr->disconnect;

4596
local/bin/ljrimport/Simple.pm Executable file

File diff suppressed because it is too large Load Diff

647
local/bin/ljrimport/icomments.pl Executable file
View File

@@ -0,0 +1,647 @@
#!/usr/bin/perl -w
use strict;
use Simple; # corrected LJ::Simple
use XML::Parser;
use POSIX;
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
require "ljr-defaults.pl";
require "ljr-links.pl";
require LJR::Distributed;
require LJR::unicode;
require "$ENV{'LJHOME'}/cgi-bin/talklib.pl";
require "ipics.pl";
my $err = sub {
my %res = ();
$res{"err"} = 1;
$res{"errtext"} = join ("\n", @_);
return \%res;
};
my $xmlerrt;
my $xmlerr = sub {
my $expat = shift;
my $cstack = "\ncallstack:";
my $i = 0;
while ( 1 ) {
my $tfunc = (caller($i))[3];
if ($tfunc && $tfunc ne "") {
if ($tfunc !~ /\_\_ANON\_\_/) {
$cstack .= " " . $tfunc;
}
$i = $i + 1;
}
else {
last;
}
}
$xmlerrt = join("\n", @_);
$xmlerrt .= $cstack;
$expat->finish();
};
my $dumpxml = sub {
my ($xdata, $username) = @_;
my $t = `date +"%T"`;
$t = substr($t, 0, length($t) - 1);
open(my $outfile, ">$ENV{'LJHOME'}/logs/err_" . $username . "_" . $t . ".xml");
print $outfile "$xdata";
close($outfile);
};
# kind of global variables
my $DEBUG=1;
my $got_max_commentid;
my $empty_num = 0;
my $ru; # current remote user (the one being cached and imported)
my $cmode;
my $xml_maxid = 0;
my $soft_cached_default_pics;
my $soft_cached_keyworded_pics;
my $posters_without_names; # lj bug workaround: http://rt.livejournal.org/Ticket/Display.html?id=762
sub cstatus_print {
my $statustr = join("", @_);
eval { LJR::Import::import_log($statustr); };
if ($@) {
print $@ . "\n";
}
if ($DEBUG) {
eval { LJR::Import::log_print($statustr); };
if ($@) {
print $statustr . "\n";
}
}
}
# comment processing
my $skip_tags = qr/^(livejournal|comments|usermaps|nextid)$/;
my $maxid = qr/^(maxid)$/;
my $comment_tag = qr/^(comment)$/;
my $usermap_tag = qr/^(usermap)$/;
my $data_tags = qr/^(subject|body|date)$/;
my $prop_tag = qr/^(property)$/;
LJ::load_props("talk");
return $err->("Can't load talkprops.") unless $LJ::CACHE_PROP{talk};
my @tprops;
foreach my $k (keys %{$LJ::CACHE_PROP{talk}}) {
push(@tprops, $k);
}
my $tprops = join("|", @tprops);
my $known_props = qr/^($tprops)$/;
my %comment = (); # current comment structure
my $cid = ""; # current tag (inside comment tag)
my $ctext = ""; # current value of $cid
# export_comments.bml xml handling routines
sub xmlh_comment_start() {
my $expat = shift;
my @params = @_;
if ($params[0] =~ /$skip_tags/) {
# skip valid but meaningless tags
}
elsif ($cmode eq "comment_meta" && $params[0] =~ /$usermap_tag/) {
shift @params; # skip "usermap"
my %usermap = ();
%usermap = @params;
if ($usermap{id} && $usermap{user}) {
my $r = {
serverid => $ru->{serverid},
userid => $usermap{id},
username => $usermap{user},
};
$r = LJR::Distributed::get_cached_user($r);
return $xmlerr->($expat, $r->{errtext}) if $r->{err};
$r = LJR::Distributed::get_imported_user($r);
return $xmlerr->($expat, $r->{errtext}) if $r->{err};
$r = LJR::Distributed::set_cu_field($r, "local_commenterid", $r->{commenterid});
return $xmlerr->($expat, $r->{errtext}) if $r->{err};
if (!$soft_cached_default_pics->{$usermap{id}}) {
my $iu = LJ::load_userid ($r->{local_commenterid});
# cstatus_print(
# "caching default userpic for " . $r->{username} .
# " (" . $r->{local_commenterid} . ":" . $iu->{user} . ")"
# );
my $e = import_pics(
$ru->{servername},
$usermap{user},
"",
$iu->{user},
"", 1);
return $xmlerr->($expat, "importing default userpic for [" . $usermap{user} . "]:", $e->{errtext})
if $e->{err};
$soft_cached_default_pics->{$usermap{id}} = 1;
}
}
elsif ($usermap{id} && !$usermap{user}) {
$posters_without_names->{$usermap{id}} = 1;
}
else {
return $xmlerr->($expat,
"Unknown XML-structure: " . join (" ", @params),
"at line " . $expat->current_line);
}
}
elsif ($params[0] =~ /$comment_tag/) {
# we're starting to process new comment
shift @params;
%comment = ();
%comment = @params; # grab all comment attributes
}
elsif ($cmode eq "comment_body" && $params[0] =~ /$data_tags/) {
$cid = $params[0];
$ctext = "";
}
elsif ($cmode eq "comment_body" && $params[0] =~ /$prop_tag/) {
shift @params; # skip "property"
# skip "name" attribute name
if (shift @params && $params[0] =~ /$known_props/) {
$cid = $params[0];
$ctext = "";
}
}
elsif ($params[0] =~ /$maxid/) {
$ctext = "";
}
else {
return $xmlerr->($expat,
"Unknown XML-structure: " . join (" ", @params),
"at line " . $expat->current_line);
}
}
sub xmlh_comment_end() {
my $expat = shift;
my @params = @_;
if ($params[0] =~ /$skip_tags/) {
# almost finished
}
elsif ($cmode eq "comment_meta" && $params[0] =~ /$usermap_tag/) {
# nop
}
elsif ($params[0] =~ /$comment_tag/) {
if ($cmode eq "comment_body") {
# print $comment{"id"} . "\n";
# print "COMMENT\n";
# while ((my $k, my $v) = each(%comment)) {
# print $k . ":" . $v . "\n";
# }
# print "/COMMENT\n";
$comment{ru_id} = $ru->{ru_id};
if (
$comment{props} &&
$comment{props}->{"picture_keyword"} &&
$comment{posterid} &&
!$soft_cached_keyworded_pics->{$comment{posterid}}->{$comment{props}->{"picture_keyword"}}
) {
my $r = {
serverid => $ru->{serverid},
userid => $comment{posterid},
};
$r = LJR::Distributed::get_cached_user($r);
return $xmlerr->($expat, $r->{errtext}) if $r->{err};
$r = LJR::Distributed::get_imported_user($r);
return $xmlerr->($expat, $r->{errtext} . "(userid: " . $comment{'posterid'} . ")") if $r->{err};
$r = LJR::Distributed::get_cu_field($r, "local_commenterid");
return $xmlerr->($expat, $r->{errtext}) if $r->{err};
my $iu = LJ::load_userid ($r->{local_commenterid});
#cstatus_print ("caching userpic " . $comment{props}->{"picture_keyword"} . " for " . $r->{username} . ":" . $iu->{user});
my $e = import_pics (
$ru->{servername},
$r->{username},
"",
$iu->{user},
$comment{props}->{"picture_keyword"},
0);
return $xmlerr->($expat, $e->{errtext}) if $e->{err};
$soft_cached_keyworded_pics->{$comment{posterid}}->{$comment{props}->{"picture_keyword"}} = 1;
}
LJR::Links::make_ljr_hrefs(
LJR::Links::get_server_url($ru->{"servername"}, "base"),
$ru->{"servername"}, \$comment{body}
);
if ($comment{'posterid'} && $posters_without_names->{$comment{'posterid'}}) {
$comment{'posterid'} = undef;
}
if (!$comment{'body'} && $comment{'state'} ne "D") {
$comment{'body'} = "LJR::Import warning: no comment body during import.";
}
my $c = LJR::Distributed::cache_comment (\%comment);
return $xmlerr->($expat, $c->{'errtext'}) if $c->{'err'};
if (!$ru->{cached_comments_maxid} ||
$comment{id} > $ru->{cached_comments_maxid}) {
$ru->{cached_comments_maxid} = $comment{id};
}
}
$got_max_commentid++;
$empty_num = 0;
}
elsif ($params[0] =~ /$data_tags/) {
$comment{$cid} = $ctext;
}
elsif ($params[0] =~ /$prop_tag/) {
$comment{props}->{$cid} = $ctext;
}
elsif ($params[0] =~ /$maxid/) {
$xml_maxid = $ctext;
if ($cmode eq "comment_body" && $xml_maxid > $ru->{remote_meta_maxid}) {
my $tmid = $got_max_commentid;
my $txid = $xml_maxid;
my $tempty = $empty_num;
$got_max_commentid = $ru->{remote_meta_maxid};
my $e = get_usermaps_cycled(
$ru->{servername},
$ru->{username},
$ru->{pass},
$got_max_commentid + 1);
return $xmlerr->($expat, $e->{errtext}) if $e->{err};
# restore comment_body xml-parsing mode
$xml_maxid = $txid;
$got_max_commentid = $tmid;
$empty_num = $tempty;
$cmode = "comment_body";
}
}
else {
return $xmlerr->($expat,
"Unknown tag: " . join (" ", @params),
"at line " . $expat->current_line
);
}
}
sub xmlh_comment_char() {
my $expat = shift;
my $tt = join("", @_);
$ctext = $ctext . $tt;
}
sub get_usermaps_cycled {
my ($server, $username, $pass, $startid) = @_;
my $comments_map = {};
my $do_login = 1;
$LJ::Simple::network_retries = $LJR::NETWORK_RETRIES;
$LJ::Simple::network_sleep = $LJR::NETWORK_SLEEP;
$LJ::Simple::LJ_Client = $LJR::LJ_CLIENT;
$LJ::Simple::UserAgent = $LJR::USER_AGENT;
my $i = 0;
my $remote_lj;
while (1) {
if ($do_login) {
$remote_lj = new LJ::Simple ({
site => $server,
user => $username,
pass => $pass,
pics => 0,
moods => 0,
});
return $err->("Can't login to remote site.", $LJ::Simple::error) unless defined $remote_lj;
if (!$remote_lj->GenerateCookie()) {
if (!$remote_lj->GenerateCookie()) {
return $err->("Can't generate login cookie.", $LJ::Simple::error);
}
}
$do_login = 0;
}
# do not process those which were processed once
if ($comments_map->{$startid}) {
$startid++;
next;
}
my $res = $remote_lj->GetRawData(
{"url" => "/export_comments.bml?get=comment_meta&startid=" . $startid}
);
if ($res && $res->{content}) {
$cmode = "comment_meta";
my $xdata = $res->{content};
LJR::unicode::force_utf8(\$xdata);
eval { LJ::text_out(\$xdata); };
my $p1 = new XML::Parser (
Handlers => {
Start => \&xmlh_comment_start,
End => \&xmlh_comment_end,
Char => \&xmlh_comment_char
});
$xml_maxid = 0;
$xmlerrt = "";
eval { $p1->parse($xdata); };
if ($@) {
if ($i < $LJR::NETWORK_RETRIES) {
if ($xdata =~ /Login Required/) {
$do_login = 1;
}
$i++;
LJR::NETWORK_SLEEP;
next;
}
else {
$dumpxml->($xdata, $username);
return $err->("Runtime error parsing XML (meta, $startid): ", $@);
}
}
if ($xmlerrt) {
$dumpxml->($xdata, $username);
return $err->("Error parsing XML (meta, $startid): ", $xmlerrt);
}
# xml was processed successfully
$comments_map->{$startid} = 1;
cstatus_print ("prefetched $got_max_commentid (skipped $empty_num) of $xml_maxid comments");
if ($got_max_commentid + $empty_num < $xml_maxid) {
$empty_num++;
$startid = $got_max_commentid + $empty_num;
next;
}
else {
$got_max_commentid = 0 unless $got_max_commentid;
$ru = LJR::Distributed::set_cu_field($ru, "remote_meta_maxid", $got_max_commentid);
return $err->($ru->{errtext}) if $ru->{err};
return undef;
}
}
else {
if ($i < $LJR::NETWORK_RETRIES) {
LJR::NETWORK_SLEEP; $i++; next;
}
else {
return $err->("can't get comments metadata: " . $LJ::Simple::error);
}
}
}
}
sub get_usermaps {
my ($server, $username, $pass, $startid) = @_;
$ru = LJR::Distributed::get_remote_server($server);
return $err->($ru->{"errtext"}) if $ru->{"err"};
$ru->{username} = $username;
$ru->{pass} = $pass;
$ru = LJR::Distributed::get_cached_user($ru);
return $err->($ru->{"errtext"}) if $ru->{"err"};
$got_max_commentid = $startid - 1;
cstatus_print ("caching commented users.");
my $e = get_usermaps_cycled($server, $username, $pass, $startid);
return $err->($e->{errtext}) if $e->{err};
}
sub get_comments_cycled {
my ($server, $username, $pass, $startid) = @_;
my $comments_map = {};
my $do_login = 1;
$ru = LJR::Distributed::get_remote_server($server) unless $ru->{serverid};
return $err->($ru->{"errtext"}) if $ru->{"err"};
$ru->{username} = $username;
$ru = LJR::Distributed::get_cached_user($ru);
return $err->($ru->{"errtext"}) if $ru->{"err"};
$LJ::Simple::network_retries = $LJR::NETWORK_RETRIES;
$LJ::Simple::network_sleep = $LJR::NETWORK_SLEEP;
$LJ::Simple::LJ_Client = $LJR::LJ_CLIENT;
$LJ::Simple::UserAgent = $LJR::USER_AGENT;
my $i = 0;
my $h_counter;
my $remote_lj;
while (1) {
if ($do_login) {
$remote_lj = new LJ::Simple ({
site => $server,
user => $username,
pass => $pass,
pics => 0,
moods => 0,
});
return $err->("Can't login to remote site.", $LJ::Simple::error) unless defined $remote_lj;
if (!$remote_lj->GenerateCookie()) {
if (!$remote_lj->GenerateCookie()) {
return $err->("Can't generate login cookie.", $LJ::Simple::error);
}
}
$do_login = 0;
}
# do not process those which were processed once
if ($comments_map->{$startid}) {
$startid++;
next;
}
my $res = $remote_lj->GetRawData(
{"url" => "/export_comments.bml?get=comment_body&props=1&startid=" . $startid}
);
if ($res && $res->{content}) {
my $xdata = $res->{content};
LJR::unicode::force_utf8(\$xdata);
eval { LJ::text_out(\$xdata); };
$cmode = "comment_body";
my $p1 = new XML::Parser (
Handlers => {
Start => \&xmlh_comment_start,
End => \&xmlh_comment_end,
Char => \&xmlh_comment_char
});
$xmlerrt = "";
eval { $p1->parse($xdata); };
if ($@) {
if ($i < $LJR::NETWORK_RETRIES) {
if ($xdata =~ /Login Required/) {
$do_login = 1;
}
$i++;
LJR::NETWORK_SLEEP;
next;
}
else {
$dumpxml->($xdata, $username);
return $err->("Runtime error parsing XML (body, $startid): ", $@);
}
}
if ($xmlerrt) {
$dumpxml->($xdata, $username);
return $err->("Error parsing XML (body, $startid): ", $xmlerrt);
}
# remember last cached comment number (which is equal to its id)
$ru = LJR::Distributed::set_cu_field(
$ru, "cached_comments_maxid",
$ru->{cached_comments_maxid});
return $err->($ru->{errtext}) if $ru->{err};
# xml was processed successfully
$comments_map->{$startid} = 1;
cstatus_print ("getting comments. last id: $ru->{cached_comments_maxid}, skipping: $empty_num, just walked: $startid, max: $ru->{remote_meta_maxid}");
if ($ru->{cached_comments_maxid} + $empty_num < $ru->{remote_meta_maxid}) {
if ($empty_num > 0) {
$empty_num =
(POSIX::floor($ru->{cached_comments_maxid} / 100) + 1) * 100 -
$ru->{cached_comments_maxid} +
$h_counter * 100;
$h_counter++;
}
else {
$empty_num++;
$h_counter = 0;
}
$startid = $ru->{cached_comments_maxid} + $empty_num;
next;
}
else {
return undef;
}
}
else {
if ($i < $LJR::NETWORK_RETRIES) {
LJR::NETWORK_SLEEP; $i++; next;
}
else {
return $err->("can't get comments: " . $LJ::Simple::error);
}
}
}
}
sub get_comments {
my ($server, $username, $pass, $startid) = @_;
cstatus_print ("caching comments");
LJ::disconnect_dbs();
$soft_cached_keyworded_pics = {};
$soft_cached_default_pics = {};
$posters_without_names = {};
$ru = LJR::Distributed::get_remote_server($server);
return $err->($ru->{"errtext"}) if $ru->{"err"};
$ru->{username} = $username;
$ru->{pass} = $pass;
$ru = LJR::Distributed::get_cached_user($ru);
return $err->($ru->{"errtext"}) if $ru->{"err"};
my $e; # for possible errors
$ru = LJR::Distributed::get_cu_field($ru, "cached_comments_maxid");
$ru->{cached_comments_maxid} = 0 if not defined $ru->{cached_comments_maxid};
# don't want to download cached comments again
$startid = $ru->{cached_comments_maxid} + 1
if $ru->{cached_comments_maxid} > $startid;
$ru = LJR::Distributed::get_cu_field($ru, "remote_meta_maxid");
$ru->{remote_meta_maxid} = 0 if not defined $ru->{remote_meta_maxid};
# try to minimize possible further delays
$got_max_commentid = $ru->{remote_meta_maxid};
$e = get_usermaps_cycled($server, $username, $pass, $got_max_commentid + 1);
return $err->($e->{errtext}) if $e->{err};
# get remote comments and cache them
$got_max_commentid = $startid - 1;
$e = get_comments_cycled($server, $username, $pass, $startid);
return $err->($e->{errtext}) if $e->{err};
$soft_cached_keyworded_pics = {};
$soft_cached_default_pics = {};
$posters_without_names = {};
return undef;
}
sub create_imported_comments {
my ($remote_site, $remote_user, $local_user) = @_;
LJ::disconnect_dbs();
my $ru = LJR::Distributed::get_remote_server($remote_site);
return $err->($ru->{"errtext"}) if $ru->{"err"};
$ru->{username} = $remote_user;
$ru = LJR::Distributed::get_cached_user($ru);
return $err->($ru->{"errtext"}) if $ru->{"err"};
cstatus_print("creating comments.");
$ru = LJR::Distributed::create_imported_comments($ru, $local_user);
return $err->($ru->{"errtext"}) if $ru->{"err"};
return undef;
}
return 1;

839
local/bin/ljrimport/ijournal.pl Executable file
View File

@@ -0,0 +1,839 @@
#!/usr/bin/perl -w
use strict;
use Simple; # corrected LJ::Simple
use POSIX;
use XML::Parser;
use Unicode::String;
use Unicode::MapUTF8 qw(to_utf8 from_utf8 utf8_supported_charset);
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
require "ljr-defaults.pl";
require "ljr-links.pl";
require LJR::Distributed;
require LJR::unicode;
require LWPx::ParanoidAgent;
require "ipics.pl";
require "$ENV{'LJHOME'}/cgi-bin/ljprotocol.pl";
my $DEBUG=1;
# shared variables (between flat and xml mode)
my $ru; # remote user
my %rfg=(); # remote friend groups
my ($ritem_id, $ranum, $rhtml_id); # remote entry ids
my $local_u; # local user being imported into
my $flags; # ljprotocol.pl flags
my $do_overwrite; # overwrite entries
my $warns;
# flat mode parameters
my $REMOTE_MAX_GET = 50; # livejournal.com lets us download no more than 50 events for a given day
# XML mode functions and variables
my $xmlerrt;
my $xmlerr = sub {
my $expat = shift;
my $cstack = "\ncallstack:";
my $i = 0;
while ( 1 ) {
my $tfunc = (caller($i))[3];
if ($tfunc && $tfunc ne "") {
if ($tfunc !~ /\_\_ANON\_\_/) {
$cstack .= " " . $tfunc;
}
$i = $i + 1;
}
else {
last;
}
}
$xmlerrt = join("\n", @_);
$xmlerrt .= $cstack;
$expat->finish();
};
my $dumptofile = sub {
my ($fdata, $filename, $ext) = @_;
my $t = `date +"%T"`;
$t = substr($t, 0, length($t) - 1);
open(my $outfile, ">$ENV{'LJHOME'}/logs/" . $filename . "_" . $t . $ext);
print $outfile "$fdata";
close($outfile);
};
my %xentry = (); # current entry
my $ctext = ""; # current field value
my $root_tags = qr/^(livejournal)$/;
my $entry_tag = qr/^(entry)$/;
my $entry_data_tag = qr/^(itemid|eventtime|logtime|subject|event|security|allowmask|current_music|current_mood)$/;
# error handling
my $err = sub {
my %res = ();
$res{"err"} = 1;
$res{"errtext"} = join ("\n", @_);
if ($warns) {
$res{"warns"} = $warns;
}
return \%res;
};
my $warn = sub {
print "WARNING: " . join ("\n", @_);
print "\n";
if (!$warns || length($warns) < 255) {
$warns .= $warns . join(" ", @_);
if (substr($warns, 0, 244) ne $warns) {
$warns = substr($warns, 0, 244) + "; and more";
}
}
};
sub jstatus_print {
my $statustr = join("", @_);
if ($DEBUG) {
eval { LJR::Import::import_log($statustr); };
if ($@) {
print $@ . "\n";
print $statustr . "\n";
}
}
}
# overwrite entry
sub check_overwrite {
my ($local_u, $ru_id, $ritem_id, $overwrite) = @_;
my $r = LJR::Distributed::get_local_itemid ($local_u, $ru_id, $ritem_id. "I");
return $err->($r->{"errtext"}) if $r->{"err"};
if ($r->{"itemid"} && $overwrite eq "1") {
my %req = (
'username' => $local_u->{'user'},
'ownerid' => $local_u->{'user'},
'clientversion' => $LJR::LJ_CLIENT,
'ver' => $LJ::PROTOCOL_VER,
'selecttype' => 'one',
'itemid' => $r->{"itemid"},
'getmenus' => 0,
'lineendings' => "unix",
'truncate' => 0,
);
my $err1;
my $items = LJ::Protocol::do_request("getevents", \%req, \$err1, $flags);
if ($err1) {
my $errstr = LJ::Protocol::error_message($err1);
return $err->($errstr);
}
my $h = @{$items->{events}}[0];
LJ::delete_entry($local_u, $h->{itemid});
$r = LJR::Distributed::get_local_itemid ($local_u, $ru_id, $ritem_id, "I");
return $err->($r->{"errtext"}) if $r->{"err"};
}
elsif ($r->{"itemid"} && $overwrite eq "0") {
return {"continue" => 0};
}
return {"continue" => 1};
}
# XML handlers
sub xmlh_entry_start() {
my $expat = shift;
my @params = @_;
if ($params[0] =~ /$root_tags/) {
# skip valid but meaningless tags
}
elsif ($params[0] =~ /$entry_tag/) {
# we're starting to process new entry
shift @params;
%xentry = ();
}
elsif ($params[0] =~ /$entry_data_tag/) {
$ctext = "";
}
else {
return $xmlerr->($expat,
"Unknown XML-structure: " . join (" ", @params),
"at line " . $expat->current_line);
}
}
sub xmlh_entry_end() {
my $expat = shift;
my @params = @_;
if ($params[0] =~ /$root_tags/) {
# almost finished
}
elsif ($params[0] =~ /$entry_tag/) {
my $xe = xml_create_entry(\%xentry);
return $xmlerr->($expat, "xml_create_entry: " . $xe->{errtext}) if $xe && $xe->{err};
}
elsif ($params[0] =~ /$entry_data_tag/) {
$xentry{$params[0]} = $ctext;
# print $params[0] . " => " . $ctext . "\n";
}
else {
return $xmlerr->($expat,
"Unknown tag: " . join (" ", @params),
"at line " . $expat->current_line
);
}
}
sub xmlh_entry_char() {
my $expat = shift;
my $tt = join("", @_);
$ctext = $ctext . $tt;
}
# should be called after populating shared variables (see section above)
sub xml_create_entry {
my ($xentry) = @_;
return $err->("XML import: can't extract remote itemid.") unless $xentry->{"itemid"};
$ritem_id = int($xentry->{"itemid"} / 256); # export.bml returns html_id instead of item_id
my $is_gated = LJR::Distributed::get_local_itemid($local_u, $ru->{'ru_id'}, $ritem_id, "E");
return $err->($is_gated->{"errtext"}) if $is_gated->{"err"};
return {"err" => 0} if $is_gated->{'itemid'};
my $r = check_overwrite($local_u, $ru->{'ru_id'}, $ritem_id, $do_overwrite);
return $err->($r->{"errtext"}) if $r->{"err"};
return unless $r->{"continue"};
my ($min,$hour,$mday,$mon,$year);
if ($xentry->{"eventtime"} =~ /(\d\d\d\d)\-(\d\d)\-(\d\d)\ (\d\d)\:(\d\d)/o) {
$year = $1;
$mon = $2;
$mday = $3;
$hour = $4;
$min = $5;
}
else {
return $err->("XML import: can't extract eventtime. remote itemid = " . $ritem_id);
}
my $moodid;
if ($xentry->{"current_mood"}) {
$moodid = LJ::mood_id($xentry->{"current_mood"});
}
LJR::Links::make_ljr_hrefs(
LJR::Links::get_server_url($ru->{"servername"}, "base"),
$ru->{"servername"}, \$xentry->{"event"}
);
# LJR::unicode::utf8ize(\$xentry->{"event"});
# LJR::unicode::utf8ize(\$xentry->{"subject"});
# LJR::unicode::utf8ize(\$xentry->{"current_mood"});
# LJR::unicode::utf8ize(\$xentry->{"current_music"});
# LJ now exports lj-polls (previously
# they exported only links to polls)
$xentry->{'event'} =~ s/<lj-poll>.+<\/lj-poll>//sog;
my %req = (
'mode' => 'postevent',
'ljr-import' => 1,
'ver' => $LJ::PROTOCOL_VER,
'clientversion' => $LJR::LJ_CLIENT,
'user' => $local_u->{'user'},
'username' => $local_u->{'user'},
'usejournal' => $local_u->{'user'},
'getmenus' => 0,
'lineendings' => "unix",
'event' => $xentry->{"event"},
'subject' => $xentry->{"subject"},
'year' => $year,
'mon' => $mon,
'day' => $mday,
'hour' => $hour,
'min' => $min,
'props' => {
'current_moodid' => $moodid,
'current_mood' => $xentry->{"current_mood"},
'current_music' => $xentry->{"current_music"},
'opt_preformatted' => 0,
'opt_nocomments' => 0,
'taglist' => "",
'picture_keyword' => "",
'opt_noemail' => 0,
'unknown8bit' => 0,
'opt_backdated' => 1,
},
);
if ($xentry->{"security"} eq "public" || $xentry->{"security"} eq "private") {
$req{'security'} = $xentry->{"security"};
$req{'allowmask'} = 0;
}
elsif ($xentry->{"security"} eq "usemask" && $xentry->{"allowmask"} == 1) {
$req{'security'} = 'usemask';
$req{'allowmask'} = 1;
}
else {
$req{'security'} = 'usemask';
my @groups = ();
foreach my $grp_id (keys %rfg) {
if ($xentry->{"allowmask"}+0 & 1 << $grp_id) {
push @groups, $rfg{$grp_id}->{name};
}
}
my $mask = 0;
while (my $grpname = shift @groups) {
my $group = LJ::get_friend_group($local_u, {'name' => $grpname});
if ($group) {
$mask = $mask | (1 << $group->{groupnum});
}
}
$req{'allowmask'} = $mask;
}
my %res = ();
LJ::do_request(\%req, \%res, $flags);
if ($res{"success"} ne "OK" && $res{"errmsg"} =~ "Missing required argument") {
$warn->($res{"errmsg"} . " while processing " . $xentry->{"eventtime"});
return;
}
if ($res{"success"} ne "OK" && $res{"errmsg"} =~ "Post too large") {
$dumptofile->($req{'event'}, "large_" . $local_u->{'user'}, ".raw");
}
return $err->($xentry->{"eventtime"} . ": " . $res{"errmsg"}) unless $res{"success"} eq "OK";
$r = LJR::Distributed::store_remote_itemid(
$local_u,
$res{"itemid"},
$ru->{ru_id},
$ritem_id,
$xentry->{"itemid"});
return $err->($xentry->{"eventtime"} . ": " . $r->{"errtext"}) if $r->{"err"};
return {"err" => 0};
}
# do the actual import
sub import_journal {
my (
$throttle_speed,
$remote_site, $remote_protocol, $remote_user, $remote_pass, $remote_shared_journal,
$local_user, $local_shared_journal, $overwrite
) = @_;
$do_overwrite = $overwrite;
LJ::disconnect_dbs(); # force reconnection to the database
if ($remote_shared_journal eq "") {
$remote_shared_journal = undef;
}
if ($local_shared_journal eq "") {
$local_shared_journal = undef;
}
my %gdc_hr = ();
my %req = ();
my %lfg = ();
my %res = ();
if ($remote_protocol ne "flat" && $remote_protocol ne "xml") {
return $err->("Unsupported remote protocol $remote_protocol.");
}
$LJ::Simple::network_retries = $LJR::NETWORK_RETRIES;
$LJ::Simple::network_sleep = $LJR::NETWORK_SLEEP;
$LJ::Simple::LJ_Client = $LJR::LJ_CLIENT;
$LJ::Simple::UserAgent = $LJR::USER_AGENT;
# login to the remote site
my $remote_lj = new LJ::Simple ({
site => $remote_site,
user => $remote_user,
pass => $remote_pass,
pics => 0,
moods => 0,
});
if (! defined $remote_lj) {
return $err->("Can't login to remote site.", $LJ::Simple::error);
}
if (!$remote_lj->GenerateCookie()) {
if (!$remote_lj->GenerateCookie()) {
return $err->("Can't generate login cookie.", $LJ::Simple::error);
}
}
# since we're able to login with supplied credentials --
# get and/or cache remote server and remote user ident
$ru = LJR::Distributed::get_remote_server($remote_site);
return $err->($ru->{"errtext"}) if $ru->{"err"};
# try to get userid
my $idres;
my $i1 = 0;
while(1) {
my $ua = LWPx::ParanoidAgent->new(timeout => 60);
$ua->agent($LJR::USER_AGENT);
# TODO: parameterize allpics.bml
my $url = $ru->{"servername"} . "/users/" . $remote_user . "/info/" ;
$idres = $ua->get($url);
if (!($idres && ($idres->is_success || $idres->code == 403)) && $i1 < $LJR::NETWORK_RETRIES) {
my $txt;
#foreach my $k (keys %$idres) {
# $txt .= $k . "->(" . $idres->{$k} ."), ";
#}
###_content->(500 DNS lookup timeout), _rc->(500), _headers->(HTTP::Headers=HASH(0x2d2ec70)), _msg->(DNS lookup timeout), _request->(HTTP::Request=HASH(0x2c61ac0)),
$txt .= "_msg->" . $idres->{'_msg'} . ", ";
foreach my $k (keys %{$idres->{'_headers'}}) {
$txt .= "\n" . $k . ": " . $idres->{'_headers'}->{$k} ;
}
print STDERR "*** $url $txt\n";
LJR::NETWORK_SLEEP(); $i1++; next;
}
else { last; }
}
if (!($idres && ($idres->is_success || $idres->code == 403))) {
return $err->("LWPx: Can't get remote user id: $remote_user\n");
}
if ($idres->content && $idres->content =~ /\<b\>$remote_user\<\/b\>\<\/a\>\ \((\d+)\)/s) {
$ru->{"userid"} = $1;
}
$ru->{"username"} = $remote_user;
$ru = LJR::Distributed::get_cached_user($ru); # populates $ru->{ru_id}
return $err->($ru->{"errtext"}) if $ru->{"err"};
# get local user object for user being imported into
$local_u = LJ::load_user($local_user, 1);
return $err->("Can't load local user $local_user.") unless $local_u;
$ru = LJR::Distributed::remote_local_assoc($ru, $local_u);
return $err->("error while getting remote-local association: " . $ru->{errtext})
if $ru->{err};
jstatus_print ("getting userpics");
my $e = import_pics(
$ru->{servername},
$ru->{username},
$remote_pass,
$local_user,
"", 0);
return $err->("Can't import " . $ru->{username} . ": " . $e->{errtext})
if $e->{err};
# clear duplicate protection
LJ::set_userprop($local_u, "dupsig_post", undef);
# needed everywhere
$flags = {
'u' => $local_u,
'noauth' => 1,
'BMAX_EVENT' => 150000,
'CMAX_EVENT' => 150000,
'no-cache' => 1,
'omit_underscore_check' => 1,
};
%req = ( 'mode' => 'login',
'ver' => $LJ::PROTOCOL_VER,
'clientversion' => $LJR::LJ_CLIENT,
'user' => $local_u->{'user'},
'getmenus' => 0,
);
%res = ();
LJ::do_request(\%req, \%res, $flags);
return $err->($res{'errmsg'}) unless $res{'success'} eq 'OK';
jstatus_print ("getting friend groups");
# get remote and local friend groups, mix them up, update on local server
if (! defined $remote_lj->GetFriendGroups(\%rfg)) {
return $err->("Failed to get groups on the remote site.", $LJ::Simple::error);
}
LJ::Protocol::do_request(
{
'mode' => 'getfriendgroups',
'user' => $local_u->{'user'},
'ver' => $LJ::PROTOCOL_VER,
'clientversion' => $LJR::LJ_CLIENT,
'includegroups' => 1,
'getmenus' => 0,
},
\%res,
$flags
);
if (! $res{'success'} eq "OK") {
return $err->("Unable to get local user" . $local_u->{'user'} . "groups",
$res{'success'} . ":" . $res{'errmsg'});
}
# convert it to LJ::Simple hash
while((my $k, my $v) = each %res) {
$k=~/^frgrp_([0-9]+)_(.*)$/o || next;
my ($id, $name) = ($1, $2);
if (!exists $lfg{$id}) {
$lfg{$id}={
id => $id,
public => 0,
};
}
($name eq "sortorder") && ($name="sort");
$lfg{$id}->{$name}=$v;
}
# add nonexisting remote groups (identified by name) to local server
foreach my $grp_id (keys %rfg) {
my $e = 0;
foreach my $lg (values %lfg) {
if ($lg->{name} eq $rfg{$grp_id}->{name}) {
$e = 1;
}
if ($lg->{name} =~ /default view/i) {
$e = 1;
}
}
if (!$e) {
my $egroup = 1;
foreach my $cgroup (sort { $a <=> $b } keys %lfg) {
if ($egroup == $cgroup) {
$egroup++;
}
}
if ($egroup < 31) {
$lfg{$egroup} = $rfg{$grp_id};
}
}
}
# create local friend groups (existing + copied)
my $i = 0;
%req = (
'mode' => "editfriendgroups",
'user' => $local_u->{'user'},
'clientversion' => $LJR::LJ_CLIENT,
'ver' => $LJ::PROTOCOL_VER,
);
# convert LJ::Simple hash back to ljprotocol hash
foreach my $grpid (keys %lfg) {
if ($grpid > 0 && $grpid < 31) {
my $pname = "efg_set_" . $grpid . "_name";
$req{$pname} = $lfg{$grpid}->{name};
$i++;
}
}
# do the actual request
LJ::do_request(\%req, \%res, $flags);
if (! $res{'success'} eq "OK") {
return $err->(
"Unable to update local user" . $local_u->{'user'} . "groups",
$res{'success'} . ":" . $res{'errmsg'}
);
}
# get remote days with entries
if (! defined $remote_lj->GetDayCounts(\%gdc_hr, undef)) {
return $err->("can't get day counts: ", $LJ::Simple::error);
}
# import entries by means of export.bml (XML format)
if ($remote_protocol eq "xml") {
my $mydc = {};
foreach (sort {$a<=>$b} keys %gdc_hr) {
my $timestamp = $_;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime($timestamp);
$mon++;
$year = $year + 1900;
$mydc->{$year}->{$mon} = 0;
$mydc->{$year}->{$mon} = $mydc->{$year}->{$mon} + $gdc_hr{$timestamp};
}
foreach (sort {$a <=> $b} keys %{$mydc}) {
my $y = $_;
foreach (sort {$a <=> $b} keys %{$mydc->{$y}}) {
jstatus_print ("getting XML data and creating local entries for " . $_ . "/" . $y);
my $do_login = 0;
while (1) {
if ($do_login) {
$remote_lj = new LJ::Simple ({
site => $remote_site,
user => $remote_user,
pass => $remote_pass,
pics => 0,
moods => 0,
});
if (! defined $remote_lj) {
return $err->("Can't login to remote site.", $LJ::Simple::error);
}
if (!$remote_lj->GenerateCookie()) {
if (!$remote_lj->GenerateCookie()) {
return $err->("Can't generate login cookie.", $LJ::Simple::error);
}
}
}
my $res = $remote_lj->GetRawData({
"url" => "/export_do.bml",
"post-data" => {
"authas" => $remote_user, # "nit",
"format" => "xml",
"encid" => 2, # utf-8; for full listing see htdocs/export.bml
"header" => 1,
"year" => $y,
"month" => $_,
"field_itemid" => 1,
"field_eventtime" => 1,
"field_logtime" => 1,
"field_subject" => 1,
"field_event" => 1,
"field_security" => 1,
"field_allowmask" => 1,
"field_currents" => 1,
}});
if ($res && $res->{content}) {
my $xdata = $res->{content};
LJR::unicode::force_utf8(\$xdata);
my $p1 = new XML::Parser (
Handlers => {
Start => \&xmlh_entry_start,
End => \&xmlh_entry_end,
Char => \&xmlh_entry_char
});
eval { $p1->parse($xdata); };
if ($@) {
if ($i < $LJR::NETWORK_RETRIES) {
if ($@ =~ /not\ well\-formed\ \(invalid\ token\)/) {
# $xdata <?xml version="1.0" encoding='windows-1251'?>
}
if ($xdata =~ /Login Required/) {
$do_login = 1;
}
LJR::NETWORK_SLEEP(); $i++; next;
}
else {
$dumptofile->($xdata, "err_" . $remote_user, ".xml");
return $err->("Runtime error while parsing XML data: ", $@);
}
}
if ($xmlerrt) {
$dumptofile->($xdata, "err_" . $remote_user, ".xml");
return $err->("Error while parsing XML data: ", $xmlerrt);
}
last;
}
else {
return $err->("Can't get XML data..");
}
}
}
}
}
# import entries by means of flat protocol
if ($remote_protocol eq "flat") {
# process them, day by day, sleeping a little
foreach (sort {$a<=>$b} keys %gdc_hr) {
my $timestamp = $_;
# download all the entries for a day
if ($gdc_hr{$timestamp} < $REMOTE_MAX_GET) {
jstatus_print (
"getting remote and creating local entries for " .
strftime ("%a %b %e %Y", localtime($timestamp))
);
my %r_entries=(); # remote entries
if (! defined $remote_lj->GetEntries(\%r_entries,$remote_shared_journal,"day",($timestamp))) {
if ($LJ::Simple::error =~ "Cannot display this post") {
$warn->(strftime ("%a %b %e %Y", localtime($timestamp)) . ":" . $LJ::Simple::error);
next;
}
return $err->("can't get remote entries: " . strftime ("%a %b %e %Y", localtime($timestamp)) . ": ",
$LJ::Simple::error);
}
my $rkey=undef;
my $rentry=undef;
my $r;
ENTRIES: while (($rkey, $rentry) = each(%r_entries)) {
($ritem_id, $ranum, $rhtml_id) = $remote_lj->GetItemId($rentry);
my $tevent = $remote_lj->GetEntry($rentry);
my $is_gated = LJR::Distributed::get_local_itemid($local_u, $ru->{'ru_id'}, $ritem_id, "E");
return $err->($is_gated->{"errtext"}) if $is_gated->{"err"};
next ENTRIES if $is_gated->{'itemid'};
$r = check_overwrite($local_u, $ru->{'ru_id'}, $ritem_id, $do_overwrite);
return $err->($r->{"errtext"}) if $r->{"err"};
next ENTRIES unless $r->{"continue"};
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime($remote_lj->GetDate($rentry));
$mon++;
$year = $year + 1900;
LJR::Links::make_ljr_hrefs(
LJR::Links::get_server_url($ru->{"servername"}, "base"),
$ru->{"servername"},
\$tevent
);
my $tsubject = $remote_lj->GetSubject($rentry);
my $tcurrent_mood = $remote_lj->Getprop_current_mood($rentry);
my $tcurrent_music = $remote_lj->Getprop_current_music($rentry);
my $ttaglist = $remote_lj->Getprop_taglist($rentry);
$ttaglist = LJ::trim($ttaglist);
my $tpicture_keyword = $remote_lj->Getprop_picture_keyword($rentry);
# LJR::unicode::utf8ize(\$tevent);
# LJR::unicode::utf8ize(\$tsubject);
# LJR::unicode::utf8ize(\$tcurrent_mood);
# LJR::unicode::utf8ize(\$tcurrent_music);
# LJR::unicode::utf8ize(\$ttaglist);
# LJR::unicode::utf8ize(\$tpicture_keyword);
%req = ( 'mode' => 'postevent',
'ljr-import' => 1,
'ver' => $LJ::PROTOCOL_VER,
'clientversion' => $LJR::LJ_CLIENT,
'user' => $local_u->{'user'},
'username' => $local_u->{'user'},
'usejournal' => $local_u->{'user'},
'getmenus' => 0,
'lineendings' => "unix",
'event' => $tevent,
'subject' => $tsubject,
'year' => $year,
'mon' => $mon,
'day' => $mday,
'hour' => $hour,
'min' => $min,
'props' => {
'current_moodid' => $rentry->{prop_current_moodid},
'current_mood' => $tcurrent_mood,
'current_music' => $tcurrent_music,
'opt_preformatted' => $remote_lj->Getprop_preformatted($rentry),
'opt_nocomments' => $remote_lj->Getprop_nocomments($rentry),
'taglist' => $ttaglist,
'picture_keyword' => $tpicture_keyword,
'opt_noemail' => $remote_lj->Getprop_noemail($rentry),
'unknown8bit' => $remote_lj->Getprop_unknown8bit($rentry),
'opt_backdated' => 1,
},
);
my @r_protection = $remote_lj->GetProtect($rentry);
if ($r_protection[0] eq "public" || $r_protection[0] eq "private") {
$req{'security'} = $r_protection[0];
$req{'allowmask'} = 0;
}
elsif ($r_protection[0] eq "friends") {
$req{'security'} = 'usemask';
$req{'allowmask'} = 1;
}
elsif ($r_protection[0] eq "groups") {
$req{'security'} = 'usemask';
shift @r_protection;
my $mask=0;
while (my $grpname = shift @r_protection) {
my $group = LJ::get_friend_group($local_u, {'name' => $grpname});
$mask = $mask | (1 << $group->{groupnum});
}
$req{'allowmask'} = $mask;
}
%res = ();
LJ::do_request(\%req, \%res, $flags);
if ($res{"success"} ne "OK" && $res{"errmsg"} =~ "Post too large") {
$dumptofile->($req{'event'}, "large_" . $local_u->{'user'}, ".raw");
}
if ($res{"success"} ne "OK" && $res{"errmsg"} =~ "Invalid text encoding") {
$warn->($res{"errmsg"});
next;
}
if ($res{"success"} ne "OK" && $res{"errmsg"} =~ "Invalid or malformed tag list") {
return $err->($res{"errmsg"} . ": [$ttaglist]");
}
return $err->($res{'errmsg'}) unless $res{'success'} eq 'OK';
$r = LJR::Distributed::store_remote_itemid(
$local_u,
$res{"itemid"},
$ru->{ru_id},
$ritem_id,
$rhtml_id);
return $err->($r->{"errtext"}) if $r->{"err"};
}
sleep($throttle_speed);
}
else {
$warn->("Too much entries for a day. " . $local_u->{'user'} . " " .
strftime ("%a %b %e %Y", localtime($timestamp))
);
}
} # process them day by day
}
if ($warns) {
my %warns = ('warns' => $warns);
return \%warns;
}
else {
return undef;
}
}
return 1;

533
local/bin/ljrimport/ipics.pl Executable file
View File

@@ -0,0 +1,533 @@
#!/usr/bin/perl
use strict;
use Image::Size ();
use Simple; # corrected LJ::Simple
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
require "ljr-defaults.pl";
require "ljr-links.pl";
require LJR::Distributed;
require LWPx::ParanoidAgent;
# error handling
my $err = sub {
my %res = ();
my $cstack = "\ncallstack:";
my $i = 0;
while ( 1 ) {
my $tfunc = (caller($i))[3];
if ($tfunc && $tfunc ne "") {
if ($tfunc !~ /\_\_ANON\_\_/) {
$cstack .= " " . $tfunc;
}
$i = $i + 1;
}
else {
last;
}
}
$res{"err"} = 1;
$res{"errtext"} = join ("\n", @_);
$res{"errtext"} .= $cstack;
return \%res;
};
# example:
my $DEBUG = 0;
sub cache_remote_pics {
my ($remote_site, $remote_user, $remote_pass, $local_userid) = @_;
my $ua;
my $res;
my %remote_urls = ();
my %remote_keywords = ();
my %remote_comments = ();
my $default_pic = "";
my $i = 0;
my $content;
# get remote pictures list with keywords
if ($remote_pass ne "") {
$LJ::Simple::network_retries = $LJR::NETWORK_RETRIES;
$LJ::Simple::network_sleep = $LJR::NETWORK_SLEEP;
$LJ::Simple::LJ_Client = $LJR::LJ_CLIENT;
$LJ::Simple::UserAgent = $LJR::USER_AGENT;
my $ljs_site = $remote_site;
if ($ljs_site =~ /^http\:\/\/(.*)/) {
$ljs_site = $1;
}
my $remote_lj = new LJ::Simple ({
site => $ljs_site,
user => $remote_user,
pass => $remote_pass,
pics => 0,
moods => 0,
});
return $err->("Can't login to remote site.", $LJ::Simple::error)
unless defined($remote_lj);
if (!$remote_lj->GenerateCookie()) {
return $err->("Can't generate login cookie.", $LJ::Simple::error);
}
$res = $remote_lj->GetRawData({
"url" => "/allpics.bml",
});
if (!($res && $res->{content})) {
return $err->("LJ::Simple: Can't get remote user pictures: $remote_user\n");
}
$content = $res->{content};
}
else {
while(1) {
$ua = LWPx::ParanoidAgent->new(timeout => 60);
$ua->agent($LJR::USER_AGENT);
# TODO: parameterize allpics.bml
$res = $ua->get($remote_site . "/allpics.bml?user=" . $remote_user);
if (!($res && $res->is_success) && $i < $LJR::NETWORK_RETRIES) {
LJR::NETWORK_SLEEP(); $i++; next;
}
else {
last;
}
}
if (!($res && $res->is_success)) {
return $err->("LWPx: Can't get remote user pictures: $remote_user\n");
}
$content = $res->content;
}
my $ru = LJR::Distributed::get_remote_server($remote_site);
return $err->($ru->{"errtext"}) if $ru->{"err"};
$ru->{username} = $remote_user;
$ru = LJR::Distributed::get_cached_user($ru);
$i = 0;
my $dbh = LJ::get_db_writer();
return $err->("Can't get database writer!") unless $dbh;
$dbh->do("DELETE FROM ljr_cached_userpics WHERE ru_id=?", undef, $ru->{ru_id});
return $err->($dbh->errstr) if $dbh->err;
my $iru;
my $userpic_base = LJR::Links::get_server_url($remote_site, "userpic_base");
# extract pic urls and keywords
if ($content =~ m!<\s*?body.*?>(.+)</body>!si) {
$content = $1;
while ($content =~
/\G.*?($userpic_base\/(\d+)\/(\d+))(.*?)($userpic_base\/(\d+)\/(\d+)|$)(.*)/sg
) {
my $picurl = $1;
my $props = $4;
my $cuserid = $3;
my $cpicid = $2;
$content = $5 . $8;
my $is_default = 0;
# save userid
if (!$iru->{ru_id}) {
$iru = LJR::Distributed::get_remote_server($remote_site);
return $err->($ru->{"errtext"}) if $ru->{"err"};
$iru->{username} = $remote_user;
$iru->{userid} = $cuserid;
$iru = LJR::Distributed::get_cached_user($iru);
return $err->($ru->{"errtext"}) if $ru->{"err"};
}
if ($props =~ /(.*?)Keywords\:\<\/b\>\ (.*?)\<br\ \/\>(.*?)\<\/td\>/s) {
$remote_keywords{$picurl} = $2;
$remote_comments{$picurl} = $3;
$remote_comments{$picurl} =~ s/^\s+|\s+$//;
}
if ($props =~ /\<u\>Default\<\/u\>/s) {
$default_pic = $picurl;
$is_default = 1;
}
my @keywords = "";
if ($remote_keywords{$picurl}) {
@keywords = split(/\s*,\s*/, $remote_keywords{$picurl});
@keywords = grep { s/^\s+//; s/\s+$//; $_; } @keywords;
}
elsif ($is_default) {
@keywords = ("");
}
foreach my $kw (@keywords) {
if($remote_urls{$cpicid}) {
$dbh->do("UPDATE ljr_cached_userpics set keyword=?, is_default=?, comments=?
where ru_id=? and remote_picid=?",
undef, $kw, $is_default, $remote_comments{$picurl},
$ru->{ru_id}, $cpicid);
return $err->($dbh->errstr) if $dbh->err;
}
else {
$dbh->do("INSERT INTO ljr_cached_userpics VALUES (?,?,?,?,?)",
undef, $ru->{ru_id}, $cpicid, $kw,
$is_default, $remote_comments{$picurl});
return $err->($dbh->errstr) if $dbh->err;
}
}
$remote_urls{$cpicid} = $picurl;
}
}
return undef;
}
sub import_pics {
my (
$remote_site, $remote_user, $remote_pass,
$local_user, $o_keyword, $o_default
) = @_;
my $MAX_UPLOAD = 40960;
my %remote_ids = ();
my %remote_urls = ();
my %remote_keywords = ();
my %remote_comments = ();
my $default_pic = "";
my $ru = LJR::Distributed::get_remote_server($remote_site);
return $err->($ru->{"errtext"}) if $ru->{"err"};
$ru->{username} = $remote_user;
$ru = LJR::Distributed::get_cached_user($ru);
# load user object (force, otherwise get error outside of apache)
my $u = LJ::load_user($local_user, 1);
return $err->("Invalid local user: " . $local_user) unless $u;
# prepare database connections (for different versions of user objects)
my ($dbcm, $dbcr, $sth);
$dbcm = LJ::get_cluster_master($u);
return $err->("Can't get cluster master!") unless $dbcm;
$dbcr = LJ::get_cluster_def_reader($u);
return $err->("Can't get cluster reader!") unless $dbcr;
my $dbh = LJ::get_db_writer();
return $err->("Can't get database writer!") unless $dbh;
my $dbr = LJ::get_db_reader();
return $err->("Can't get database reader!") unless $dbr;
my $e;
if (!$o_keyword && !$o_default) {
$e = cache_remote_pics($remote_site, $remote_user, $remote_pass, $u->{userid});
return $e if $e->{err};
}
else {
$sth = $dbr->prepare(
"SELECT ru_id FROM ljr_cached_userpics WHERE ru_id=? GROUP BY ru_id");
$sth->execute($ru->{ru_id});
my $ruid = $sth->fetchrow_hashref;
$sth->finish;
if (!$ruid) {
$e = cache_remote_pics($remote_site, $remote_user, $remote_pass, $u->{userid});
return $e if $e->{err};
}
}
# get ru->{userid} which should come up after caching remote pic props
$ru = LJR::Distributed::get_cached_user($ru);
if ($o_keyword) {
$sth = $dbr->prepare(
"SELECT remote_picid, keyword, is_default, comments " .
"FROM ljr_cached_userpics WHERE ru_id=? and keyword=?");
$sth->execute($ru->{ru_id}, $o_keyword);
}
elsif ($o_default) {
$sth = $dbr->prepare(
"SELECT remote_picid, keyword, is_default, comments " .
"FROM ljr_cached_userpics WHERE ru_id=? and is_default=1");
$sth->execute($ru->{ru_id});
}
else {
$sth = $dbr->prepare(
"SELECT remote_picid, keyword, is_default, comments " .
"FROM ljr_cached_userpics WHERE ru_id=?");
$sth->execute($ru->{ru_id});
}
my $i = 0;
while (my $rpic = $sth->fetchrow_hashref) {
my $picurl = $remote_site . "/userpic/" . $rpic->{remote_picid} . "/" . $ru->{userid};
$remote_ids{$i} = $rpic->{remote_picid};
$remote_urls{$rpic->{remote_picid}} = $picurl;
$remote_comments{$picurl} = $rpic->{comments};
$remote_keywords{$picurl} =
(($remote_keywords{$picurl}) ? $remote_keywords{$picurl} . "," : "") .
$rpic->{keyword};
if ($rpic->{is_default}) {
$default_pic = $picurl;
}
print
$picurl . ":" .
$remote_ids{$i} . ":" .
$remote_comments{$picurl} . ":" .
$remote_keywords{$picurl} . "\n"
if $DEBUG;
$i++;
}
$sth->finish;
RPICID: foreach my $rpicid (sort {$a <=> $b} values %remote_ids) {
my $local_picid = $dbr->selectrow_array(
"SELECT local_picid FROM ljr_remote_userpics " .
"WHERE ru_id=? and remote_picid=? and local_userid = ?",
undef, $ru->{ru_id}, $rpicid, $u->{userid});
if ($local_picid) {
my $r_picid = $dbr->selectrow_array(
"SELECT picid FROM userpic2 WHERE picid=?",
undef, $local_picid);
if (!$r_picid) {
$u->do("DELETE FROM ljr_remote_userpics WHERE local_picid=?", undef, $local_picid);
$local_picid = undef;
}
else {
next RPICID;
}
}
my %POST = ();
$POST{urlpic} = $remote_urls{$rpicid};
$POST{keywords} = $remote_keywords{$remote_urls{$rpicid}};
$POST{comments} = $remote_comments{$remote_urls{$rpicid}};
$POST{url} = "";
if ($default_pic eq $remote_urls{$rpicid}) {
$POST{make_default} = 1;
}
# get remote picture and validate it
my $ua;
my $res;
my ($sx, $sy, $filetype);
$i = 0;
while(1) {
$ua = LWPx::ParanoidAgent->new(
timeout => 60,
max_size => $MAX_UPLOAD + 1024);
$ua->agent($LJR::USER_AGENT);
$res = $ua->get($POST{urlpic});
# if the picture doesn't exist on the remote server
# then we get 404 http error and remove it from our cache
if ($res &&
($res->{"_rc"} eq 404 || $res->{"_rc"} eq 503)
) {
$dbh->do("DELETE FROM ljr_cached_userpics WHERE ru_id=? and remote_picid=?",
undef, $ru->{ru_id}, $rpicid);
return $err->($dbh->errstr) if $dbh->err;
next RPICID;
}
$POST{userpic} = $res->content if $res && $res->is_success;
($sx, $sy, $filetype) = Image::Size::imgsize(\$POST{'userpic'});
if (!(
$res && $res->is_success && defined($sx) &&
length($POST{'userpic'}) <= $MAX_UPLOAD &&
($filetype eq "GIF" || $filetype eq "JPG" || $filetype eq "PNG") &&
$sx <= 100 && $sy <= 100
) &&
$i < $LJR::NETWORK_RETRIES) {
LJR::NETWORK_SLEEP(); $i++; next;
}
else {
last;
}
}
if (!($res && $res->is_success)) {
return $err->("Can't get remote user picture: ",
$remote_user, $local_user, $o_keyword, $o_default, $POST{urlpic},
$res->status_line);
}
if (!defined $sx) {
print ("Invalid image: " . $POST{urlpic} . "\n");
next RPICID;
}
if (length($POST{'userpic'}) > $MAX_UPLOAD) {
return $err->("Picture " . $POST{urlpic} . "is too large");
}
return $err->("Unsupported filetype: " . $POST{urlpic})
unless ($filetype eq "GIF" || $filetype eq "JPG" || $filetype eq "PNG");
return $err->("Image too large: " . $POST{urlpic}) if ($sx > 150 || $sy > 150);
my $base64 = Digest::MD5::md5_base64($POST{'userpic'});
# see if it's a duplicate
my $picid;
my $contenttype;
if ($filetype eq "GIF") { $contenttype = 'G'; }
elsif ($filetype eq "PNG") { $contenttype = 'P'; }
elsif ($filetype eq "JPG") { $contenttype = 'J'; }
$picid = $dbcr->selectrow_array(
"SELECT picid FROM userpic2 WHERE userid=? AND fmt=? AND md5base64=?",
undef, $u->{'userid'}, $contenttype, $base64);
$picid = 0 unless defined($picid);
print "trying to insert into db\n" if $DEBUG;
# if picture isn't a duplicate, insert it
if ($picid == 0) {
# Make a new global picid
$picid = LJ::alloc_global_counter('P') or
return $err->('Unable to allocate new picture id');
$u->do(
"INSERT INTO userpic2 (picid, userid, fmt, width, height, " .
"picdate, md5base64, location, state) " .
"VALUES (?, ?, ?, ?, ?, NOW(), ?, ?, 'N')",
undef, $picid, $u->{'userid'}, $contenttype, $sx, $sy, $base64, undef);
return $err->($u->errstr) if $u->err;
my $clean_err = sub {
if ($picid) {
$u->do(
"DELETE FROM userpic2 WHERE userid=? AND picid=?",
undef, $u->{'userid'}, $picid);
$u->do(
"DELETE FROM userpicblob2 WHERE userid=? AND picid=?",
undef, $u->{'userid'}, $picid);
}
return $err->(@_);
};
### insert the blob
$u->do(
"INSERT INTO userpicblob2 (userid, picid, imagedata) VALUES (?,?,?)",
undef, $u->{'userid'}, $picid, $POST{'userpic'});
return $clean_err->($u->errstr) if $u->err;
# make it their default pic?
if ($POST{'make_default'}) {
LJ::update_user($u, { defaultpicid => $picid });
$u->{'defaultpicid'} = $picid;
}
# set default keywords?
if ($POST{'keywords'} && $POST{'keywords'} ne '') {
print "storing keywords\n" if $DEBUG;
$sth = $dbcr->prepare("SELECT kwid, picid FROM userpicmap2 WHERE userid=?");
$sth->execute($u->{'userid'});
my @exist_kwids;
while (my ($kwid, $picid) = $sth->fetchrow_array) {
$exist_kwids[$kwid] = $picid;
}
my @keywords = split(/\s*,\s*/, $POST{'keywords'});
@keywords = grep { s/^\s+//; s/\s+$//; $_; } @keywords;
my (@bind, @data);
my $c = 0;
foreach my $kw (@keywords) {
my $kwid = LJ::get_keyword_id($u, $kw);
next unless $kwid; # Houston we have a problem! This should always return an id.
if ($c > $LJ::MAX_USERPIC_KEYWORDS) {
return $clean_err->("Too many userpic keywords: " . LJ::ehtml($kw));
}
if ($exist_kwids[$kwid]) { # Already used on another picture
# delete existing pic while there's newer one
$u->do("
delete ljr_remote_userpics, ljr_cached_userpics
from ljr_cached_userpics, ljr_remote_userpics
where
ljr_cached_userpics.ru_id = ljr_remote_userpics.ru_id and
ljr_cached_userpics.remote_picid = ljr_remote_userpics.remote_picid and
ljr_remote_userpics.local_userid = ? and local_picid = ?",
undef, $u->{'userid'}, $exist_kwids[$kwid]);
$u->do("DELETE FROM userpicmap2 WHERE userid=? AND picid=?",
undef, $u->{'userid'}, $exist_kwids[$kwid]);
$u->do("DELETE FROM userpicblob2 WHERE userid=? AND picid=?",
undef, $u->{'userid'}, $exist_kwids[$kwid]);
$u->do("DELETE FROM userpic2 WHERE userid=? AND picid=?",
undef, $u->{'userid'}, $exist_kwids[$kwid]);
}
push @bind, '(?, ?, ?)';
push @data, $u->{'userid'}, $kwid, $picid;
$c++;
}
if (@data && @bind) {
my $bind = join(',', @bind);
$u->do(
"INSERT INTO userpicmap2 (userid, kwid, picid) VALUES $bind",
undef, @data);
}
}
# set default comments and the url
my (@data, @set);
if ($POST{'comments'} && $POST{'comments'} ne '') {
push @set, 'comment=?';
push @data, LJ::text_trim($POST{'comments'}, $LJ::BMAX_UPIC_COMMENT, $LJ::CMAX_UPIC_COMMENT);
}
if ($POST{'url'} ne '') {
push @set, 'url=?';
push @data, $POST{'url'};
}
if (@set) {
my $set = join(',', @set);
$u->do("UPDATE userpic2 SET $set WHERE userid=? AND picid=?",
undef, @data, $u->{'userid'}, $picid);
return $err->($u->errstr) if $u->err;
}
$u->do("INSERT INTO ljr_remote_userpics VALUES (?,?,?,?)",
undef, $ru->{ru_id}, $rpicid, $u->{userid}, $picid);
return $err->($u->errstr) if $u->err;
}
}
return undef;
}
return 1;

View File

@@ -0,0 +1,35 @@
#!/usr/bin/perl
package LJR;
$LJ_CLIENT = "LJR::Import/0.01";
$USER_AGENT = "LJR::Import/0.01; http://lj.rossia.org/; lj-admin\@rossia.org";
# How much times to retry if any network related error occurs
$NETWORK_RETRIES = 10; #was: 20
# Hom much seconds to wait before each retry
$NETWORK_SLEEP = 30; #was: 5
$DEBUG = 1;
sub NETWORK_SLEEP {
my $msg = shift;
if ($msg) {
$msg = " (" . $msg . ")";
}
else {
$msg = "";
}
my $t = `date +"%D %T"`;
print
substr($t, 0, length($t) - 1) .
" sleeping $NETWORK_SLEEP seconds due to network related error" . $msg . ".\n"
if $DEBUG;
sleep $NETWORK_SLEEP;
};
return 1;

106
local/bin/ljrimport/ljr-import.pl Executable file
View File

@@ -0,0 +1,106 @@
#!/usr/bin/perl -w
package LJR::Import;
use strict; # preventing my program from doing bad things
use DBI; # http://dbi.perl.org
use POSIX ();
do $ENV{'LJHOME'} . "/cgi-bin/ljconfig.pl";
my $qhost = $LJ::DBINFO{'master'}->{'host'};
my $quser = $LJ::DBINFO{'master'}->{'user'};
my $qpass = $LJ::DBINFO{'master'}->{'pass'};
my $qdb = $LJ::DBINFO{'master'}->{'dbname'};
my $qsock = $LJ::DBINFO{'master'}->{'sock'};
my $qport = $LJ::DBINFO{'master'}->{'port'};
$| = 1; # unbuffered (almost) output
# global database handle
$LJR::Import::global_dbh = 0;
# global shutdown request received flag
$LJR::Import::cool_stop = 0;
my $history_id;
# POSIX unmasks the sigprocmask properly
my $sigset = POSIX::SigSet->new();
my $action = POSIX::SigAction->new(
'LJR::Import::sigTERM_handler', $sigset, &POSIX::SA_NODEFER);
POSIX::sigaction(&POSIX::SIGTERM, $action);
sub log_print {
my $msg = shift;
my $t = `date +"%D %T"`;
print substr($t, 0, length($t) - 1) . " $msg\n";
}
sub sigTERM_handler {
my $t = `date +"%D %T"`;
print substr($t, 0, length($t) - 1) . " ljr-import.pl: received shutdown request\n";
$LJR::Import::cool_stop = 1;
}
# configuration
my $speed_throttle = 10; # seconds
print "\n";
LJR::Import::log_print("started");
# main loop, throttled
while (!process_exit()) {
process_queue(); # process new requests for import if any
sleep ($speed_throttle); # sleep for a while
}
LJR::Import::log_print("ljr-import.pl: shutting down due to safe shutdown request");
sub import_log {
my ($istatus) = @_;
my $sth2 = $LJR::Import::global_dbh->prepare (
"update ljr_ihistory set
istatus = ?,
idate = now()
where importid = ?");
$sth2->execute($istatus, $history_id);
$sth2->finish;
}
sub process_exit {
return ($LJR::Import::cool_stop);
}
sub process_queue {
my $row;
my $row1;
my $sth2;
my $e;
$LJR::Import::global_dbh = DBI->connect(
"DBI:mysql:mysql_socket=$qsock;hostname=$qhost;port=$qport;database=$qdb",
$quser, $qpass,
{RaiseError => 0, AutoCommit => 1}
) || die "Can't open database connection: $DBI::errstr";
my $sth = $LJR::Import::global_dbh->prepare("SELECT * from ljr_iqueue order by priority, importid");
$sth->execute;
while (($row = $sth->fetchrow_hashref) && !process_exit()) {
my $r = system ("nice -n 19 ./ljr-importdo.pl");
if ($r != 0) {
$sth->finish;
$LJR::Import::global_dbh->disconnect;
return;
}
sleep($speed_throttle); # do not hurry
$sth->execute; # refresh the query
}
$sth->finish;
$LJR::Import::global_dbh->disconnect;
}

View File

@@ -0,0 +1,218 @@
#!/usr/bin/perl -w
package LJR::Import;
use strict; # preventing my program from doing bad things
use DBI; # http://dbi.perl.org
use POSIX ();
do $ENV{'LJHOME'} . "/cgi-bin/ljconfig.pl";
my $qhost = $LJ::DBINFO{'master'}->{'host'};
my $quser = $LJ::DBINFO{'master'}->{'user'};
my $qpass = $LJ::DBINFO{'master'}->{'pass'};
my $qdb = $LJ::DBINFO{'master'}->{'dbname'};
my $qsock = $LJ::DBINFO{'master'}->{'sock'};
my $qport = $LJ::DBINFO{'master'}->{'port'};
require "ijournal.pl";
require "icomments.pl";
$| = 1; # unbuffered (almost) output
# global database handle
$LJR::Import::global_dbh = 0;
# global shutdown request received flag
$LJR::Import::cool_stop = 0;
my $history_id;
# POSIX unmasks the sigprocmask properly
my $sigset = POSIX::SigSet->new();
my $action = POSIX::SigAction->new(
'LJR::Import::sigTERM_handler', $sigset, &POSIX::SA_NODEFER);
POSIX::sigaction(&POSIX::SIGTERM, $action);
sub log_print {
my $msg = shift;
my $t = `date +"%D %T"`;
print substr($t, 0, length($t) - 1) . " $msg\n";
}
sub sigTERM_handler {
my $t = `date +"%D %T"`;
print substr($t, 0, length($t) - 1) . " ljr-import-do.pl: received shutdown request\n";
$LJR::Import::cool_stop = 1;
}
# configuration
my $speed_throttle = 10; # seconds
process_queue_alone(); # there must be something there!
if (process_exit()) {
exit 1;
}
else {
exit 0;
}
sub import_log {
my ($istatus) = @_;
my $sth2 = $LJR::Import::global_dbh->prepare (
"update ljr_ihistory set
istatus = ?,
idate = now()
where importid = ?");
$sth2->execute($istatus, $history_id);
$sth2->finish;
}
sub process_exit {
return ($LJR::Import::cool_stop);
}
sub process_queue_alone {
my $row;
my $row1;
my $sth2;
my $e;
$LJR::Import::global_dbh = DBI->connect(
"DBI:mysql:mysql_socket=$qsock;hostname=$qhost;port=$qport;database=$qdb",
$quser, $qpass,
{RaiseError => 0, AutoCommit => 1}
) || die "Can't open database connection: $DBI::errstr";
my $sth = $LJR::Import::global_dbh->prepare("SELECT * from ljr_iqueue order by priority, importid");
$sth->execute;
while (($row = $sth->fetchrow_hashref) && !process_exit()) {
my $sth1 = $LJR::Import::global_dbh->prepare (
"SELECT * from ljr_iqueue where
local_user = '" . $row->{'local_user'} . "'
order by local_user desc, importid desc limit 1");
$sth1->execute; # find last user request for import
$row = $sth1->fetchrow_hashref;
# create history record
$sth2 = $LJR::Import::global_dbh->prepare (
"insert into ljr_ihistory values ('',?,?,'',?,?,?,?,now(),'STARTED',now())");
$sth2->execute (
$row->{'remote_site'}, $row->{'remote_user'}, $row->{'remote_protocol'},
$row->{'local_user'}, $row->{'opt_overwrite'}, $row->{'opt_comments'}
); # save import history (parameters, time when started)
$history_id = $LJR::Import::global_dbh->selectrow_array("SELECT LAST_INSERT_ID()");
$sth2->finish;
LJR::Import::log_print(
$row->{'local_user'} . " <- " .
$row->{'remote_site'} . "::" . $row->{'remote_user'} .
" (entries)"
);
$e = "";
$e = import_journal(
0, # throttle_speed (seconds)
$row->{'remote_site'}, # remote_site
$row->{'remote_protocol'},# remote_protocol
$row->{'remote_user'}, # remote_user
$row->{'remote_pass'}, # remote_pass
"", # remote shared journal (if any)
$row->{'local_user'}, # local_user
"", # local shared journal (if any)
$row->{'opt_overwrite'} # overwrite entries
);
if ($row->{'opt_comments'} && (!$e || !$e->{'err'})) {
LJR::Import::log_print(
$row->{'local_user'} . " <- " .
$row->{'remote_site'} . "::" . $row->{'remote_user'} .
" (caching comments)"
);
$e = get_comments(
$row->{'remote_site'},
$row->{'remote_user'},
$row->{'remote_pass'},
1);
if (!$e || !$e->{'err'}) {
LJR::Import::log_print(
$row->{'local_user'} . " <- " .
$row->{'remote_site'} . "::" . $row->{'remote_user'} .
" (creating comments)");
$e = create_imported_comments (
$row->{'remote_site'},
$row->{'remote_user'},
$row->{'local_user'});
}
}
if ($e->{'err'}) {
$sth2 = $LJR::Import::global_dbh->prepare (
"update ljr_ihistory " .
"set remote_pass = '" . $row->{'remote_pass'} . "' " .
"where importid = " . $history_id . " ;"
);
$sth2->execute; # save remote pass for debugging purposes
$sth2->finish;
my $boo = $e->{errtext};
$boo =~ s/\n//;
LJR::Import::log_print(
$row->{'local_user'} . " <- " .
$row->{'remote_site'} . "::" . $row->{'remote_user'} . " " . $boo
);
import_log($e->{errtext});
}
else {
$sth2 = $LJR::Import::global_dbh->prepare (
"update ljr_ihistory " .
"set remote_pass = '' " .
"where remote_site = '" . $row->{'remote_site'} . "' and " .
"remote_user = '" . $row->{'remote_user'} . "' ;"
);
$sth2->execute; # remove remote pass since the journal was imported successfully
$sth2->finish;
LJR::Import::log_print(
$row->{'local_user'} . " <- " .
$row->{'remote_site'} . "::" . $row->{'remote_user'} .
": successful"
);
if ($e->{'warns'}) {
import_log("SUCCESSFUL, but " . $e->{'warns'});
}
else {
import_log("SUCCESSFUL");
}
}
$sth1 = $LJR::Import::global_dbh->prepare (
"delete from ljr_iqueue " .
"where local_user = '" . $row->{'local_user'} . "'"
); # empty all the user's request after processing last one
$sth1->execute;
$sth1->finish;
$sth->finish;
# we're quitting!
# if (process_exit()) {
$LJR::Import::global_dbh->disconnect;
return;
# }
}
$sth->finish;
$LJR::Import::global_dbh->disconnect;
}

117
local/bin/ljrimport/ljr-links.pl Executable file
View File

@@ -0,0 +1,117 @@
#!/usr/bin/perl
use strict;
package LJR::Links;
sub get_server_url {
my ($canonical_url, $type) = @_;
if ($canonical_url eq "http://www.livejournal.com") {
if ($type eq "base") {
return "livejournal.com";
}
if ($type eq "userpic_base") {
return "http://userpic.livejournal.com";
}
}
}
sub make_ljr_hrefs {
my ($server_patt, $server_full, $text) = @_;
my $content = $$text;
$$text = "";
my $url;
my $orig_url;
my $orig_url_text;
return unless $content;
# replace valid html hyperlinks (<a href=http://www.livejournal.com/users/username/111.html>url_text</a>)
# with <ljr-href url="/users/username/111.html" site="http://www.livejournal.com">url_text</ljr-href>
#
while ($content =~
/\G(.*?)(\<a.*?href.*?=(\s?\"\s?)?(.*?)(\s?\"\s?)?\>(.*?)\<\/a\>)(.*)/sgi
) {
$$text .= $1;
$orig_url = $2;
$orig_url_text = $6;
$url = $4;
$content = $7;
# relative link (to the server from which we're importing)
if ($url =~ /^(\/users\/.*?\/\d*?\.html(.*?$))/) { # (\?thread=\d*\#t\d*)|$
$$text .= "<ljr-href url=\"$1\" site=\"$server_full\">$orig_url_text</ljr-href>";
}
# relative link to oldstyle talkread.bml
elsif ($url =~ /^\/talkread.bml?\?journal=(.*?)\&itemid=(\d+)/) {
$$text .= "<ljr-href url=\"/users/$1/$2.html\" site=\"$server_full\">$orig_url_text</ljr-href>";
}
# absolute link to oldstyle talkread.bml
elsif ($url =~ /^http:\/\/(www\.|)$server_patt\/talkread.bml\?journal=(.*?)\&itemid=(\d+)/) {
$$text .= "<ljr-href url=\"/users/$2/$3.html\" site=\"$server_full\">$orig_url_text</ljr-href>";
}
# free users own two types of urls (first is canonical)
# http://www.livejournal.com/users/free_user/123456.html
# http://www.livejournal.com/~free_user/123456.html
elsif ($url =~ /^http:\/\/(www\.|)$server_patt(((\/~(\w*?)\/)|(\/users\/.*?\/))(\d*?\.html(.*?$)))/) { # (\?thread=\d*\#t\d*)|$
if ($5) {
$$text .= "<ljr-href url=\"/users/$5/$7\" site=\"$server_full\">$orig_url_text</ljr-href>";
}
else {
$$text .= "<ljr-href url=\"$2\" site=\"$server_full\">$orig_url_text</ljr-href>";
}
}
# payed users might own http://payeduser.livejournal.com/123456.html urls
elsif ($url =~ /^http:\/\/(\w*?)\.$server_patt\/(\d*?\.html(.*?$))/) { # (\?thread=\d*\#t\d*)|$
$$text .= "<ljr-href url=\"/users/$1/$2\" site=\"$server_full\">$orig_url_text</ljr-href>";
}
else {
$$text .= $orig_url;
}
}
$$text .= $content;
$content = $$text;
$$text = "";
# replace strings like http://www.livejournal.com/users/lookslikeentry/123456.html with
# <ljr-href url="/users/lookslikeentry/123456.html" site="http://www.livejournal.com">http://www.livejournal.com/users/lookslikeentry/123456.html</ljr-href>
#
# now these can be only absolute links starting with http://
while ($content =~
/\G(.*?(^|[\ \t\r\n\f]))(http:\/\/.*?)(($|[\ \t\r\n\f]).*)/sg
) {
$$text .= $1;
$orig_url = $3;
$orig_url_text = $3;
$url = $3;
$content = $4;
# free users (copied from above)
if ($url =~ /^http:\/\/(www\.|)$server_patt(((\/~(\w*?)\/)|(\/users\/.*?\/))(\d*?\.html(.*?$)))/) { # (\?thread=\d*\#t\d*)|$
if ($5) {
$$text .= "<ljr-href url=\"/users/$5/$7\" site=\"$server_full\">$orig_url_text</ljr-href>";
}
else {
$$text .= "<ljr-href url=\"$2\" site=\"$server_full\">$orig_url_text</ljr-href>";
}
}
# oldstyle talkread.bml
elsif ($url =~ /^http:\/\/(www\.|)$server_patt\/talkread.bml\?journal=(.*?)\&itemid=(\d+)/) {
$$text .= "<ljr-href url=\"/users/$2/$3.html\" site=\"$server_full\">$orig_url_text</ljr-href>";
}
# payed users (copied from above)
elsif ($url =~ /^http:\/\/(\w*?)\.$server_patt\/(\d*?\.html(.*?$))/) { # (\?thread=\d*\#t\d*)|$
$$text .= "<ljr-href url=\"/users/$1/$2\" site=\"$server_full\">$orig_url_text</ljr-href>";
}
else {
$$text .= $orig_url;
}
}
$$text .= $content;
}
return 1;

View File

@@ -0,0 +1,17 @@
#!/bin/bash
export LJHOME=/home/lj-admin/lj
IMPORT_NAME=ljr-import
ipid=`ps -e --format=pid,cmd | grep $IMPORT_NAME | grep -v grep | cut --bytes=1-5`
if [ ! "$ipid" == "" ]; then
echo "LJR::Import found, PID: $ipid; shutdown with ljr-stop.sh first."
else
if [ "$LJHOME" != "" ]; then
cd $LJHOME/bin/ljrimport
./ljr-import.pl >> $LJHOME/logs/ljr-import.log 2>&1 &
else
echo \$LJHOME is not set.
fi
fi

12
local/bin/ljrimport/ljr-stop.sh Executable file
View File

@@ -0,0 +1,12 @@
#!/bin/bash
IMPORT_NAME=ljr-import
ipid=`ps -e --format=pid,cmd | grep $IMPORT_NAME | grep -v grep | cut --bytes=1-5`
if [ ! "$ipid" == "" ]; then
echo "LJR::Import found, PID: $ipid; sending shutdown signal."
kill $ipid
else
echo "LJR::Import is not running."
fi

View File

@@ -0,0 +1,21 @@
#!/usr/bin/perl
#
$maint{'clean_challenges'} = sub
{
my $dbh = LJ::get_db_writer();
my $sth;
my $ctime = time();
my $deltime = $ctime - 60*60*24*14; # two weeks
print "current time: $ctime\n";
print "deleting challenges older than: $deltime\n";
$sth = $dbh->prepare("delete from challenges where challenge < 'c0:$deltime'");
$sth->execute();
if ($dbh->err) { die $dbh->errstr; }
print "done.\n";
};
1;

548
local/bin/maint/stats.pl Executable file
View File

@@ -0,0 +1,548 @@
#!/usr/bin/perl
#
use strict;
use vars qw(%maint);
require "$ENV{'LJHOME'}/cgi-bin/statslib.pl";
# filled in by ljmaint.pl, 0=quiet, 1=normal, 2=verbose
$LJ::Stats::VERBOSE = $LJ::LJMAINT_VERBOSE >= 2 ? 1 : 0;
$maint{'genstats'} = sub
{
my @which = @_ || qw(users countries
states gender clients
pop_interests meme pop_faq);
# popular faq items
LJ::Stats::register_stat
({ 'type' => "global",
'jobname' => "popfaq",
'statname' => "pop_faq",
'handler' =>
sub {
my $db_getter = shift;
return undef unless ref $db_getter eq 'CODE';
my $db = $db_getter->();
return undef unless $db;
my $sth = $db->prepare("SELECT faqid, COUNT(*) FROM faquses WHERE " .
"faqid<>0 GROUP BY 1 ORDER BY 2 DESC LIMIT 50");
$sth->execute;
die $db->errstr if $db->err;
my %ret;
while (my ($id, $count) = $sth->fetchrow_array) {
$ret{$id} = $count;
}
return \%ret;
},
});
# popular interests
LJ::Stats::register_stat
({ 'type' => "global",
'jobname' => "pop_interests",
'statname' => "pop_interests",
'handler' =>
sub {
my $db_getter = shift;
return undef unless ref $db_getter eq 'CODE';
my $db = $db_getter->();
return undef unless $db;
return {} if $LJ::DISABLED{'interests-popular'};
# see what the previous min was, then subtract 20% of max from it
my ($prev_min, $prev_max) = $db->selectrow_array("SELECT MIN(statval), MAX(statval) " .
"FROM stats WHERE statcat='pop_interests'");
my $stat_min = int($prev_min - (0.2*$prev_max));
$stat_min = 1 if $stat_min < 1;
my $sth = $db->prepare("SELECT interest, intcount FROM interests WHERE intcount>? " .
"ORDER BY intcount DESC, interest ASC LIMIT 400");
$sth->execute($stat_min);
die $db->errstr if $db->err;
my %ret;
while (my ($int, $count) = $sth->fetchrow_array) {
$ret{$int} = $count;
}
return \%ret;
},
});
# popular memes
LJ::Stats::register_stat
({ 'type' => "global",
'jobname' => "meme",
'statname' => "popmeme",
'handler' =>
sub {
my $db_getter = shift;
return undef unless ref $db_getter eq 'CODE';
my $db = $db_getter->();
return undef unless $db;
return {} if $LJ::DISABLED{'meme'};
my $sth = $db->prepare("SELECT url, count(*) FROM meme " .
"GROUP BY 1 ORDER BY 2 DESC LIMIT 100");
$sth->execute;
die $db->errstr if $db->err;
my %ret;
while (my ($url, $count) = $sth->fetchrow_array) {
$ret{$url} = $count;
}
return \%ret;
},
});
# clients
LJ::Stats::register_stat
({ 'type' => "global",
'jobname' => "clients",
'statname' => "client",
'handler' =>
sub {
my $db_getter = shift;
return undef unless ref $db_getter eq 'CODE';
my $db = $db_getter->();
return undef unless $db;
return {} if $LJ::DISABLED{'clientversionlog'};
my $tsql = "SELECT MAX(userid) FROM user";
$tsql .= " where userid < " . $LJ::LJR_IMPORTED_USERIDS if $LJ::LJR_IMPORTED_USERIDS;
my $usertotal = $db->selectrow_array($tsql);
my $blocks = LJ::Stats::num_blocks($usertotal);
my %ret;
foreach my $block (1..$blocks) {
my ($low, $high) = LJ::Stats::get_block_bounds($block);
$db = $db_getter->(); # revalidate connection
my $sth = $db->prepare("SELECT c.client, COUNT(*) AS 'count' FROM clients c, clientusage cu " .
"WHERE c.clientid=cu.clientid AND cu.userid BETWEEN $low AND $high " .
"AND cu.lastlogin > DATE_SUB(NOW(), INTERVAL 30 DAY) GROUP BY 1 ORDER BY 2");
$sth->execute;
die $db->errstr if $db->err;
while ($_ = $sth->fetchrow_hashref) {
$ret{$_->{'client'}} += $_->{'count'};
}
print LJ::Stats::block_status_line($block, $blocks);
}
return \%ret;
},
});
# user table analysis
LJ::Stats::register_stat
({ 'type' => "global",
'jobname' => "users",
'statname' => ["account", "newbyday", "age", "userinfo"],
'handler' =>
sub {
my $db_getter = shift;
return undef unless ref $db_getter eq 'CODE';
my $db = $db_getter->();
return undef unless $db;
my $tsql = "SELECT MAX(userid) FROM user";
$tsql .= " where userid < " . $LJ::LJR_IMPORTED_USERIDS if $LJ::LJR_IMPORTED_USERIDS;
my $usertotal = $db->selectrow_array($tsql);
my $blocks = LJ::Stats::num_blocks($usertotal);
my %ret; # return hash, (statname => { arg => val } since 'statname' is arrayref above
# iterate over user table in batches
foreach my $block (1..$blocks) {
my ($low, $high) = LJ::Stats::get_block_bounds($block);
# user query: gets user,caps,age,status,allow_getljnews
$db = $db_getter->(); # revalidate connection
my $sth = $db->prepare
("SELECT user, caps, " .
"FLOOR((TO_DAYS(NOW())-TO_DAYS(bdate))/365.25) AS 'age', " .
"status, allow_getljnews " .
"FROM user WHERE userid BETWEEN $low AND $high");
$sth->execute;
die $db->errstr if $db->err;
while (my $rec = $sth->fetchrow_hashref) {
# account types
my $capnameshort = LJ::name_caps_short($rec->{'caps'});
$ret{'account'}->{$capnameshort}++;
# ages
$ret{'age'}->{$rec->{'age'}}++
if $rec->{'age'} > 4 && $rec->{'age'} < 110;
# users receiving news emails
$ret{'userinfo'}->{'allow_getljnews'}++
if $rec->{'status'} eq "A" && $rec->{'allow_getljnews'} eq "Y";
}
# userusage query: gets timeupdate,datereg,nowdate
my $sth = $db->prepare
("SELECT DATE_FORMAT(timecreate, '%Y-%m-%d') AS 'datereg', " .
"DATE_FORMAT(NOW(), '%Y-%m-%d') AS 'nowdate', " .
"UNIX_TIMESTAMP(timeupdate) AS 'timeupdate' " .
"FROM userusage WHERE userid BETWEEN $low AND $high");
$sth->execute;
die $db->errstr if $db->err;
while (my $rec = $sth->fetchrow_hashref) {
# date registered
$ret{'newbyday'}->{$rec->{'datereg'}}++
unless $rec->{'datereg'} eq $rec->{'nowdate'};
# total user/activity counts
$ret{'userinfo'}->{'total'}++;
if (my $time = $rec->{'timeupdate'}) {
my $now = time();
$ret{'userinfo'}->{'updated'}++;
$ret{'userinfo'}->{'updated_last30'}++ if $time > $now-60*60*24*30;
$ret{'userinfo'}->{'updated_last7'}++ if $time > $now-60*60*24*7;
$ret{'userinfo'}->{'updated_last1'}++ if $time > $now-60*60*24*1;
}
}
print LJ::Stats::block_status_line($block, $blocks);
}
return \%ret;
},
});
LJ::Stats::register_stat
({ 'type' => "clustered",
'jobname' => "countries",
'statname' => "country",
'handler' =>
sub {
my $db_getter = shift;
return undef unless ref $db_getter eq 'CODE';
my $db = $db_getter->();
my $cid = shift;
return undef unless $db && $cid;
my $upc = LJ::get_prop("user", "country");
die "Can't find country userprop. Database populated?\n" unless $upc;
my $tsql = "SELECT MAX(userid) FROM userproplite2";
$tsql .= " where userid < " . $LJ::LJR_IMPORTED_USERIDS if $LJ::LJR_IMPORTED_USERIDS;
my $usertotal = $db->selectrow_array($tsql);
my $blocks = LJ::Stats::num_blocks($usertotal);
my %ret;
foreach my $block (1..$blocks) {
my ($low, $high) = LJ::Stats::get_block_bounds($block);
$db = $db_getter->(); # revalidate connection
my $sth = $db->prepare("SELECT u.value, COUNT(*) AS 'count' FROM userproplite2 u " .
"LEFT JOIN clustertrack2 c ON u.userid=c.userid " .
"WHERE u.upropid=? AND u.value<>'' AND u.userid=c.userid " .
"AND u.userid BETWEEN $low AND $high " .
"AND (c.clusterid IS NULL OR c.clusterid=?)" .
"GROUP BY 1 ORDER BY 2");
$sth->execute($upc->{'id'}, $cid);
die "clusterid: $cid, " . $db->errstr if $db->err;
while ($_ = $sth->fetchrow_hashref) {
$ret{$_->{'value'}} += $_->{'count'};
}
print LJ::Stats::block_status_line($block, $blocks);
}
return \%ret;
},
});
LJ::Stats::register_stat
({ 'type' => "clustered",
'jobname' => "states",
'statname' => "stateus",
'handler' =>
sub {
my $db_getter = shift;
return undef unless ref $db_getter eq 'CODE';
my $db = $db_getter->();
my $cid = shift;
return undef unless $db && $cid;
my $upc = LJ::get_prop("user", "country");
die "Can't find country userprop. Database populated?\n" unless $upc;
my $ups = LJ::get_prop("user", "state");
die "Can't find state userprop. Database populated?\n" unless $ups;
my $tsql = "SELECT MAX(userid) FROM userproplite2";
$tsql .= " where userid < " . $LJ::LJR_IMPORTED_USERIDS if $LJ::LJR_IMPORTED_USERIDS;
my $usertotal = $db->selectrow_array($tsql);
my $blocks = LJ::Stats::num_blocks($usertotal);
my %ret;
foreach my $block (1..$blocks) {
my ($low, $high) = LJ::Stats::get_block_bounds($block);
$db = $db_getter->(); # revalidate connection
my $sth = $db->prepare("SELECT ua.value, COUNT(*) AS 'count' " .
"FROM userproplite2 ua, userproplite2 ub " .
"WHERE ua.userid=ub.userid AND ua.upropid=? AND " .
"ub.upropid=? and ub.value='US' AND ub.value<>'' " .
"AND ua.userid BETWEEN $low AND $high " .
"GROUP BY 1 ORDER BY 2");
$sth->execute($ups->{'id'}, $upc->{'id'});
die $db->errstr if $db->err;
while ($_ = $sth->fetchrow_hashref) {
$ret{$_->{'value'}} += $_->{'count'};
}
print LJ::Stats::block_status_line($block, $blocks);
}
return \%ret;
},
});
LJ::Stats::register_stat
({ 'type' => "clustered",
'jobname' => "gender",
'statname' => "gender",
'handler' =>
sub {
my $db_getter = shift;
return undef unless ref $db_getter eq 'CODE';
my $db = $db_getter->();
my $cid = shift;
return undef unless $db && $cid;
my $upg = LJ::get_prop("user", "gender");
die "Can't find gender userprop. Database populated?\n" unless $upg;
my $tsql = "SELECT MAX(userid) FROM userproplite2";
$tsql .= " where userid < " . $LJ::LJR_IMPORTED_USERIDS if $LJ::LJR_IMPORTED_USERIDS;
my $usertotal = $db->selectrow_array($tsql);
my $blocks = LJ::Stats::num_blocks($usertotal);
my %ret;
foreach my $block (1..$blocks) {
my ($low, $high) = LJ::Stats::get_block_bounds($block);
$db = $db_getter->(); # revalidate connection
my $sth = $db->prepare("SELECT value, COUNT(*) AS 'count' FROM userproplite2 up " .
"LEFT JOIN clustertrack2 c ON up.userid=c.userid " .
"WHERE up.upropid=? AND up.userid BETWEEN $low AND $high " .
"AND (c.clusterid IS NULL OR c.clusterid=?) GROUP BY 1");
$sth->execute($upg->{'id'}, $cid);
die "clusterid: $cid, " . $db->errstr if $db->err;
while ($_ = $sth->fetchrow_hashref) {
$ret{$_->{'value'}} += $_->{'count'};
}
print LJ::Stats::block_status_line($block, $blocks);
}
return \%ret;
},
});
# run stats
LJ::Stats::run_stats(@which);
#### dump to text file
print "-I- Dumping to a text file.\n";
{
my $dbh = LJ::Stats::get_db("dbh");
my $sth = $dbh->prepare("SELECT statcat, statkey, statval FROM stats ORDER BY 1, 2");
$sth->execute;
die $dbh->errstr if $dbh->err;
open (OUT, ">$LJ::HTDOCS/stats/stats.txt");
while (my @row = $sth->fetchrow_array) {
next if grep { $row[0] eq $_ } @LJ::PRIVATE_STATS;
print OUT join("\t", @row), "\n";
}
close OUT;
}
print "-I- Done.\n";
};
$maint{'genstats_size'} = sub {
LJ::Stats::register_stat
({ 'type' => "global",
'jobname' => "size-accounts",
'statname' => "size",
'handler' =>
sub {
my $db_getter = shift;
return undef unless ref $db_getter eq 'CODE';
my $db = $db_getter->();
return undef unless $db;
my $tsql = "SELECT MAX(userid) FROM user";
$tsql .= " where userid < " . $LJ::LJR_IMPORTED_USERIDS if $LJ::LJR_IMPORTED_USERIDS;
# not that this isn't a total of current accounts (some rows may have
# been deleted), but rather a total of accounts ever created
my $size = $db->selectrow_array($tsql);
return { 'accounts' => $size };
},
});
LJ::Stats::register_stat
({ 'type' => "clustered",
'jobname' => "size-accounts_active",
'statname' => "size",
'handler' =>
sub {
my $db_getter = shift;
return undef unless ref $db_getter eq 'CODE';
my $db = $db_getter->();
return undef unless $db;
my $period = 30; # one month is considered active
my $active = $db->selectrow_array
("SELECT COUNT(*) FROM clustertrack2 WHERE ".
"timeactive > UNIX_TIMESTAMP()-86400*$period");
return { 'accounts_active' => $active };
},
});
print "-I- Generating account size stats.\n";
LJ::Stats::run_stats("size-accounts", "size-accounts_active");
print "-I- Done.\n";
};
$maint{'genstats_weekly'} = sub
{
LJ::Stats::register_stat
({ 'type' => "global",
'jobname' => "supportrank",
'statname' => "supportrank",
'handler' =>
sub {
my $db_getter = shift;
return undef unless ref $db_getter eq 'CODE';
my $db = $db_getter->();
return undef unless $db;
my %supportrank;
my $rank = 0;
my $lastpoints = 0;
my $buildup = 0;
my $sth = $db->prepare
("SELECT u.userid, SUM(sp.points) AS 'points' " .
"FROM user u, supportpoints sp " .
"WHERE u.userid=sp.userid GROUP BY 1 ORDER BY 2 DESC");
$sth->execute;
die $db->errstr if $db->err;
while ($_ = $sth->fetchrow_hashref) {
if ($lastpoints != $_->{'points'}) {
$lastpoints = $_->{'points'};
$rank += (1 + $buildup);
$buildup = 0;
} else {
$buildup++;
}
$supportrank{$_->{'userid'}} = $rank;
}
# move old 'supportrank' stat to supportrank_prev
# no API for this :-/
{
my $dbh = LJ::Stats::get_db("dbh");
$dbh->do("DELETE FROM stats WHERE statcat='supportrank_prev'");
$dbh->do("UPDATE stats SET statcat='supportrank_prev' WHERE statcat='supportrank'");
}
return \%supportrank;
}
});
print "-I- Generating weekly stats.\n";
LJ::Stats::run_stats('supportrank');
print "-I- Done.\n";
};
$maint{'build_randomuserset'} = sub
{
## this sets up the randomuserset table daily (or whenever) that htdocs/random.bml uses to
## find a random user that is both 1) publicly listed in the directory, and 2) updated
## within the past 24 hours.
## note that if a user changes their privacy setting to not be in the database, it'll take
## up to 24 hours for them to be removed from the random.bml listing, but that's acceptable.
my $dbh = LJ::get_db_writer();
print "-I- Building randomuserset.\n";
$dbh->do("TRUNCATE TABLE randomuserset");
$dbh->do("REPLACE INTO randomuserset (userid) " .
"SELECT uu.userid FROM userusage uu, user u " .
"WHERE u.userid=uu.userid AND u.allow_infoshow='Y' " .
"AND uu.timeupdate > DATE_SUB(NOW(), INTERVAL 1 DAY) ORDER BY RAND() LIMIT 5000");
my $num = $dbh->selectrow_array("SELECT MAX(rid) FROM randomuserset");
$dbh->do("REPLACE INTO stats (statcat, statkey, statval) " .
"VALUES ('userinfo', 'randomcount', $num)");
print "-I- Done.\n";
};
$maint{'memeclean'} = sub
{
my $dbh = LJ::get_db_writer();
print "-I- Cleaning memes.\n";
my $sth = $dbh->prepare("SELECT statkey FROM stats WHERE statcat='popmeme'");
$sth->execute;
die $dbh->errstr if $dbh->err;
while (my $url = $sth->fetchrow_array) {
my $copy = $url;
LJ::run_hooks("canonicalize_url", \$copy);
unless ($copy) {
my $d = $dbh->quote($url);
$dbh->do("DELETE FROM stats WHERE statcat='popmeme' AND statkey=$d");
print " deleting: $url\n";
}
}
print "-I- Done.\n";
};
1;

655
local/bin/maint/synsuck.pl Executable file
View File

@@ -0,0 +1,655 @@
#!/usr/bin/perl
#
use strict;
use vars qw(%maint %maintinfo);
use lib "$ENV{'LJHOME'}/cgi-bin"; # extra XML::Encoding files in cgi-bin/XML/*
use LWP::UserAgent;
use XML::RSS;
use HTTP::Status;
use Image::Size;
require "ljprotocol.pl";
require "parsefeed.pl";
require "cleanhtml.pl";
require "talklib.pl";
require LWPx::ParanoidAgent;
require LJR::unicode;
use utf8;
binmode STDOUT, ":utf8";
my $dumpxml = sub {
my ($xdata, $username) = @_;
open(my $outfile, ">$ENV{'LJHOME'}/logs/syn_err_" . $username . ".xml");
print $outfile "$xdata";
close($outfile);
};
my $err = sub {
my ($msg) = @_;
print $msg . "\n";
return;
};
my $get_picture = sub {
my ($userid, $url) = @_;
my $MAX_UPLOAD = 102400;
my $ua = LWPx::ParanoidAgent->new(timeout => 30, max_size => $MAX_UPLOAD + 1024);
$ua->agent("Synsuck::Userpic; $LJ::SITENAME; $LJ::ADMIN_EMAIL");
my $res = $ua->get($url);
my $picdata = $res->content;
return $err->("some error while getting userpic") if !($res && $res->is_success);
return $err->("404 while getting userpic") if ($res && $res->{"_rc"} eq 404);
return $err->("userpic size is bigger than we want") if length($picdata) > $MAX_UPLOAD;
my ($sx, $sy, $filetype) = Image::Size::imgsize(\$picdata);
return $err->("can't ge userpic size") unless defined $sx;
return $err->("unknown userpic filetype") unless $filetype eq "GIF" || $filetype eq "JPG" || $filetype eq "PNG";
return $err->("userpic is bigger than we want") if $sx > 150 || $sy > 150;
my $contenttype;
if ($filetype eq "GIF") { $contenttype = 'G'; }
elsif ($filetype eq "PNG") { $contenttype = 'P'; }
elsif ($filetype eq "JPG") { $contenttype = 'J'; }
my $base64 = Digest::MD5::md5_base64($picdata);
my $picid = LJ::alloc_global_counter('P') or return;
my $dbh = LJ::get_db_writer();
$dbh->do(
"INSERT INTO userpic2" .
"(picid, userid, fmt, width, height, picdate, md5base64, location, state, url) " .
"VALUES (?, ?, ?, ?, ?, NOW(), ?, ?, 'N', ?)",
undef, $picid, $userid, $contenttype, $sx, $sy, $base64, undef, $url);
$dbh->do(
"INSERT INTO userpicblob2 (userid, picid, imagedata) VALUES (?,?,?)",
undef, $userid, $picid, $picdata);
my $su = LJ::load_userid($userid);
LJ::update_user($su, { defaultpicid => $picid });
};
$maintinfo{'synsuck'}{opts}{locking} = "per_host";
$maint{'synsuck'} = sub
{
my $maxcount = shift || 0;
my $verbose = $LJ::LJMAINT_VERBOSE;
my %child_jobs; # child pid => [ userid, lock ]
my $process_user = sub {
my $urow = shift;
return unless $urow;
my ($user, $userid, $synurl, $lastmod, $etag, $lastmod_feed, $readers) =
map { $urow->{$_} } qw(user userid synurl lastmod etag lastmod_feed numreaders);
# we're a child process now, need to invalidate caches and
# get a new database handle
LJ::start_request();
my $dbh = LJ::get_db_writer();
# see if things have changed since we last looked and acquired the lock.
# otherwise we could 1) check work, 2) get lock, and between 1 and 2 another
# process could do both steps. we don't want to duplicate work already done.
my $now_checknext = $dbh->selectrow_array("SELECT checknext FROM syndicated ".
"WHERE userid=?", undef, $userid);
return if $now_checknext ne $urow->{checknext};
my $ua = LWP::UserAgent->new("timeout" => 30);
my $reader_info = $readers ? "; $readers readers" : "";
$ua->agent("$LJ::SITENAME ($LJ::ADMIN_EMAIL; for $LJ::SITEROOT/users/$user/" . $reader_info . ")");
my $delay = sub {
my $minutes = shift;
my $status = shift;
# add some random backoff to avoid waves building up
$minutes += int(rand(5));
$dbh->do("UPDATE syndicated SET lastcheck=NOW(), checknext=DATE_ADD(NOW(), ".
"INTERVAL ? MINUTE), laststatus=? WHERE userid=?",
undef, $minutes, $status, $userid);
};
print "[$$] Synsuck: fetching $user ($synurl)\n" if $verbose;
my $req = HTTP::Request->new("GET", $synurl);
$req->header('If-Modified-Since', $lastmod)
if $lastmod;
$req->header('If-None-Match', $etag)
if $etag;
my ($content, $too_big);
my $max_size = $LJ::SYNSUCK_MAX_SIZE || 500; # in kb
my $res = eval {
$ua->request($req, sub {
if (length($content) > 1024*$max_size) { $too_big = 1; return; }
$content .= $_[0];
}, 4096);
};
if ($@) { $delay->(120, "lwp_death"); return; }
if ($too_big) { $delay->(60, "toobig"); return; }
if ($res->is_error()) {
# http error
print " HTTP error! " . $res->status_line() . "\n" if $verbose;
$delay->(3*60, "httperror");
# overload rssparseerror here because it's already there -- we'll
# never have both an http error and a parse error on the
# same request
LJ::set_userprop($userid, "rssparseerror", $res->status_line());
return;
}
# check if not modified
if ($res->code() == RC_NOT_MODIFIED) {
print " not modified.\n" if $verbose;
$delay->($readers ? 30 : 12*60, "notmodified");
return;
}
my $r_lastmod = $res->header('Last-Modified');
my $r_etag = $res->header('ETag');
# check again (feedburner.com, blogspot.com, etc.)
if (($etag && $etag eq $r_etag) || ($lastmod && $lastmod eq $r_lastmod)) {
print " not modified.\n" if $verbose;
$delay->($readers ? 30 : 12*60, "notmodified");
return;
}
# force utf8; this helps from time to time ???
LJR::unicode::force_utf8(\$content);
# parsing time...
my ($feed, $error) = LJ::ParseFeed::parse_feed($content);
if ($error) {
# parse error!
print "Parse error! $error\n" if $verbose;
$delay->(3*60, "parseerror");
$error =~ s! at /.*!!;
$error =~ s/^\n//; # cleanup of newline at the beggining of the line
LJ::set_userprop($userid, "rssparseerror", $error);
$dumpxml->($content, $user);
return;
}
my $r_lastmod_feed = $feed->{'lastmod'};
my $r_lastmod_lastBuildDate = $feed->{'lastBuildDate'};
print " $lastmod \n $r_lastmod \n $etag \n $r_etag \n $lastmod_feed \n $r_lastmod_feed \n $r_lastmod_lastBuildDate \n ";
# check last-modified for bogus web-servers
if ($lastmod_feed && $lastmod_feed eq $r_lastmod_feed) {
print " not modified..\n" if $verbose;
$delay->($readers ? 30 : 12*60, "notmodified");
return;
}
# print " $lastmod \n $r_lastmod \n $etag \n $r_etag \n $lastmod_feed \n $r_lastmod_feed \n $r_lastmod_lastBuildDate \n ";
# another sanity check
unless (ref $feed->{'items'} eq "ARRAY") {
$delay->(3*60, "noitems");
return;
}
# update userpic
my $cur_pic = $dbh->selectrow_array(
"SELECT url FROM userpic2, user WHERE user.userid=? and
userpic2.userid=user.userid and userpic2.picid=user.defaultpicid",
undef, $userid);
if (
($feed->{'image'} && $cur_pic && $cur_pic ne $feed->{'image'}) ||
($feed->{'image'} && !$cur_pic)
) {
$dbh->do("delete from userpic2 WHERE userid=?", undef, $userid);
$dbh->do("delete from userpicblob2 WHERE userid=?", undef, $userid);
$dbh->do("update user set user.defaultpicid=NULL where userid=?", undef, $userid);
print "[$$] Synsuck: $user -- trying to fetch userpic from: " .
$feed->{'image'} . " \n" if $verbose;
$get_picture->($userid, $feed->{'image'});
}
my @items = reverse @{$feed->{'items'}};
# delete existing items older than the age which can show on a
# friends view.
my $su = LJ::load_userid($userid);
my $udbh = LJ::get_cluster_master($su);
unless ($udbh) {
$delay->(15, "nodb");
return;
}
# TAG:LOG2:synsuck_delete_olderitems
# my $secs = ($LJ::MAX_FRIENDS_VIEW_AGE || 3600*24*14)+0; # 2 week default.
# my $sth = $udbh->prepare("SELECT jitemid, anum FROM log2 WHERE journalid=? AND ".
# "logtime < DATE_SUB(NOW(), INTERVAL $secs SECOND)");
# $sth->execute($userid);
# die $udbh->errstr if $udbh->err;
# while (my ($jitemid, $anum) = $sth->fetchrow_array) {
# print "DELETE itemid: $jitemid, anum: $anum... \n" if $verbose;
# if (LJ::delete_entry($su, $jitemid, 0, $anum)) {
# print "success.\n" if $verbose;
# } else {
# print "fail.\n" if $verbose;
# }
# }
my $count = $udbh->selectrow_array("SELECT COUNT(*) FROM log2 WHERE journalid=$userid");
print "count = $count \n";
my $extra = $count - $LJ::MAX_SCROLLBACK_FRIENDS_SINGLE_USER_ACTIVITY;
if ($extra > 0) {
my $sth = $udbh->prepare("SELECT jitemid FROM logprop2 WHERE journalid=$userid".
" ORDER BY jitemid ASC LIMIT $extra");
$sth->execute();
while (my ($jitemid) = $sth->fetchrow_array) {
print "DELETE itemid: $jitemid... \n" if $verbose;
if (LJ::delete_entry($su, $jitemid)) {
print "success.\n" if $verbose;
} else {
print "fail.\n" if $verbose;
}
}
}
# determine if link tags are good or not, where good means
# "likely to be a unique per item". some feeds have the same
# <link> element for each item, which isn't good.
# if we have unique ids, we don't compare link tags
my ($compare_links, $have_ids) = 0;
{
my %link_seen;
foreach my $it (@items) {
$have_ids = 1 if $it->{'id'};
next unless $it->{'link'};
$link_seen{$it->{'link'}} = 1;
}
$compare_links = 1 if !$have_ids and $feed->{'type'} eq 'rss' and
scalar(keys %link_seen) == scalar(@items);
}
# if we have unique links/ids, load them for syndicated
# items we already have on the server. then, if we have one
# already later and see it's changed, we'll do an editevent
# instead of a new post.
my %existing_item = ();
if ($have_ids || $compare_links) {
my $p = $have_ids ? LJ::get_prop("log", "syn_id") :
LJ::get_prop("log", "syn_link");
my $sth = $udbh->prepare("SELECT jitemid, value FROM logprop2 WHERE ".
"journalid=? AND propid=? ORDER BY jitemid DESC LIMIT 1000"); # need last 100
$sth->execute($su->{'userid'}, $p->{'id'});
while (my ($jitemid, $id) = $sth->fetchrow_array) {
if (!defined $existing_item{$id}) {
$existing_item{$id} = $jitemid;
# print "Got it: $jitemid, $id\n" if $verbose;
} else {
# remove duplicates - if any:
print "DELETE duplicated itemid: $jitemid, $id ...\n" if $verbose;
if (LJ::delete_entry($su, $jitemid)) {
print "success.\n" if $verbose;
} else {
print "fail.\n" if $verbose;
}
}
}
}
# post these items
my $newcount = 0;
my $errorflag = 0;
my $mindate; # "yyyy-mm-dd hh:mm:ss";
my $notedate = sub {
my $date = shift;
$mindate = $date if ! $mindate || $date lt $mindate;
};
LJ::load_user_props($su, { use_master => 1 }, "newesteventtime");
### if ($su->{'newesteventtime'} eq $oldevent->{'eventtime'}) {
### LJ::set_userprop($su, "newesteventtime", undef);
### }
foreach my $it (@items) {
if ($it->{'time'} && $it->{'time'} lt $su->{'newesteventtime'}) {
## print "---- " . $it->{'subject'} . "\n" if $verbose;
next;
} elsif ($it->{'time'} && $it->{'time'} eq $su->{'newesteventtime'}) {
print "==== " . $it->{'subject'} . "\n" if $verbose;
} else {
print "++++ " . $it->{'subject'} . "\n" if $verbose;
}
my $dig = LJ::md5_struct($it)->b64digest;
my $prevadd = $dbh->selectrow_array("SELECT MAX(dateadd) FROM synitem WHERE ".
"userid=? AND item=?", undef,
$userid, $dig);
if ($prevadd) {
$notedate->($prevadd);
next;
}
my $now_dateadd = $dbh->selectrow_array("SELECT NOW()");
die "unexpected format" unless $now_dateadd =~ /^\d\d\d\d\-\d\d\-\d\d \d\d:\d\d:\d\d$/;
$dbh->do("INSERT INTO synitem (userid, item, dateadd) VALUES (?,?,?)",
undef, $userid, $dig, $now_dateadd);
$notedate->($now_dateadd);
$newcount++;
print "[$$] $dig - $it->{'subject'}\n" if $verbose;
$it->{'text'} =~ s/^\s+//;
$it->{'text'} =~ s/\s+$//;
# process lj-cuts
while ($it->{'text'} =~ /\G(.*?)<a\ name\=\"cutid(\d+)\"\>\<\/a\>(.*)/sg) {
my $before = $1;
my $cutid = $2;
my $rcut = $3;
$rcut =~ s/<a\ name\=\"cutid$cutid\"\>\<\/a\>/\<\/lj\-cut\>/;
$it->{'text'} = $before . "<lj-cut>" . $rcut;
}
my $htmllink;
if (defined $it->{'link'}) {
$htmllink = "<p class='ljsyndicationlink'>" .
"<a href='$it->{'link'}'>$it->{'link'}</a></p>";
}
# Show the <guid> link if it's present and different than the
# <link>.
# [zilla: 267] Patch: Chaz Meyers <lj-zilla@thechaz.net>
if ( defined $it->{'id'} && $it->{'id'} ne $it->{'link'}
&& $it->{'id'} =~ m!^http://! )
{
$htmllink .= "<p class='ljsyndicationlink'>" .
"<a href='$it->{'id'}'>$it->{'id'}</a></p>";
}
# rewrite relative URLs to absolute URLs, but only invoke the HTML parser
# if we see there's some image or link tag, to save us some work if it's
# unnecessary (the common case)
if ($it->{'text'} =~ /<(?:img|a)\b/i) {
# TODO: support XML Base? http://www.w3.org/TR/xmlbase/
my $base_href = $it->{'link'} || $synurl;
LJ::CleanHTML::resolve_relative_urls(\$it->{'text'}, $base_href);
}
# $own_time==1 means we took the time from the feed rather than localtime
my ($own_time, $year, $mon, $day, $hour, $min);
if ($it->{'time'} &&
$it->{'time'} =~ m!^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d)!) {
$own_time = 1;
($year, $mon, $day, $hour, $min) = ($1,$2,$3,$4,$5);
} else {
$own_time = 0;
my @now = localtime();
($year, $mon, $day, $hour, $min) =
($now[5]+1900, $now[4]+1, $now[3], $now[2], $now[1]);
}
my $command = "postevent";
my $req = {
'username' => $user,
'ver' => 1,
'subject' => $it->{'subject'},
'event' => "$it->{'text'}",
'year' => $year,
'mon' => $mon,
'day' => $day,
'hour' => $hour,
'min' => $min,
'props' => {
'syn_link' => $it->{'link'},
'opt_nocomments' => 1,
},
};
$req->{'props'}->{'syn_id'} = $it->{'id'}
if $it->{'id'};
my $flags = {
'nopassword' => 1,
};
# if the post contains html linebreaks, assume it's preformatted.
if ($it->{'text'} =~ /<(?:p|br)\b/i) {
$req->{'props'}->{'opt_preformatted'} = 1;
}
# do an editevent if we've seen this item before
my $id = $have_ids ? $it->{'id'} : $it->{'link'};
my $old_itemid = $existing_item{$id};
if ($id && $old_itemid) {
$newcount--; # cancel increment above
$command = "editevent";
$req->{'itemid'} = $old_itemid;
# the editevent requires us to resend the date info, which
# we have to go fetch first, in case the feed doesn't have it
# TAG:LOG2:synsuck_fetch_itemdates
unless($own_time) {
my $origtime =
$udbh->selectrow_array("SELECT eventtime FROM log2 WHERE ".
"journalid=? AND jitemid=?", undef,
$su->{'userid'}, $old_itemid);
$origtime =~ /(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d)/;
$req->{'year'} = $1;
$req->{'mon'} = $2;
$req->{'day'} = $3;
$req->{'hour'} = $4;
$req->{'min'} = $5;
}
}
my $err;
my $res = LJ::Protocol::do_request($command, $req, \$err, $flags);
unless ($res && ! $err) {
print " Error: $err\n" if $verbose;
$errorflag = 1;
}
}
# delete some unneeded synitems. the limit 1000 is because
# historically we never deleted and there are accounts with
# 222,000 items on a myisam table, and that'd be quite the
# delete hit.
# the 14 day interval is because if a remote site deleted an
# entry, it's possible for the oldest item that was previously
# gone to reappear, and we want to protect against that a
# little.
if ($LJ::SYNITEM_CLEAN) {
$dbh->do("DELETE FROM synitem WHERE userid=? AND ".
"dateadd < ? - INTERVAL 14 DAY LIMIT 1000",
undef, $userid, $mindate);
}
$dbh->do("UPDATE syndicated SET oldest_ourdate=? WHERE userid=?",
undef, $mindate, $userid);
# bail out if errors, and try again shortly
if ($errorflag) {
$delay->(30, "posterror");
return;
}
# update syndicated account's userinfo if necessary
LJ::load_user_props($su, "url", "urlname");
{
my $title = $feed->{'title'};
$title = $su->{'user'} unless LJ::is_utf8($title);
$title =~ s/[\n\r]//g;
if ($title && $title ne $su->{'name'}) {
LJ::update_user($su, { name => $title });
}
if ($title) {
LJ::set_userprop($su, "urlname", $title);
} else {
LJ::set_userprop($su, "urlname", $su->{'url'});
}
my $link = $feed->{'link'};
if ($link && $link ne $su->{'url'}) {
LJ::set_userprop($su, "url", $link);
}
my $des = $feed->{'description'};
if ($des) {
my $bio;
if ($su->{'has_bio'} eq "Y") {
$bio = $udbh->selectrow_array("SELECT bio FROM userbio WHERE userid=?", undef,
$su->{'userid'});
}
if ($bio ne $des && $bio !~ /\[LJ:KEEP\]/) {
if ($des) {
$su->do("REPLACE INTO userbio (userid, bio) VALUES (?,?)", undef,
$su->{'userid'}, $des);
} else {
$su->do("DELETE FROM userbio WHERE userid=?", undef, $su->{'userid'});
}
LJ::update_user($su, { has_bio => ($des ? "Y" : "N") });
LJ::MemCache::delete([$su->{'userid'}, "bio:$su->{'userid'}"]);
}
}
}
# decide when to poll next (in minutes).
# FIXME: this is super lame. (use hints in RSS file!)
my $int = $newcount ? 15 : 30;
my $status = $newcount ? "ok" : "nonew";
my $updatenew = $newcount ? ", lastnew=NOW()" : "";
# update reader count while we're changing things, but not
# if feed is stale (minimize DB work for inactive things)
if ($newcount || ! defined $readers) {
$readers = $dbh->selectrow_array("SELECT COUNT(*) FROM friends WHERE ".
"friendid=?", undef, $userid);
}
# if readers are gone, don't check for a whole day
$int = 60*24 if $readers && $readers < 2 || !$readers;
$dbh->do("UPDATE syndicated SET checknext=DATE_ADD(NOW(), INTERVAL $int MINUTE), ".
"lastcheck=NOW(), lastmod=?, etag=?, lastmod_feed=? , laststatus=?, numreaders=? $updatenew ".
"WHERE userid=$userid", undef, $r_lastmod, $r_etag, $r_lastmod_feed, $status, $readers);
};
###
### child process management
###
# get the next user to be processed
my @all_users;
my $get_next_user = sub {
return shift @all_users if @all_users;
# need to get some more rows
my $dbh = LJ::get_db_writer();
my $current_jobs = join(",", map { $dbh->quote($_->[0]) } values %child_jobs);
my $in_sql = " AND u.userid NOT IN ($current_jobs)" if $current_jobs;
my $sth = $dbh->prepare("SELECT u.user, s.userid, s.synurl, s.lastmod, " .
" s.etag, s.lastmod_feed, s.numreaders, s.checknext " .
"FROM user u, syndicated s " .
"WHERE u.userid=s.userid AND u.statusvis='V' " .
"AND s.checknext < NOW()$in_sql " .
"ORDER BY RAND() LIMIT 500");
$sth->execute;
while (my $urow = $sth->fetchrow_hashref) {
push @all_users, $urow;
}
return undef unless @all_users;
return shift @all_users;
};
# fork and manage child processes
my $max_threads = $LJ::SYNSUCK_MAX_THREADS || 1;
print "[$$] PARENT -- using $max_threads workers\n" if $verbose;
my $threads = 0;
my $userct = 0;
my $keep_forking = 1;
while ( $maxcount == 0 || $userct < $maxcount ) {
if ($threads < $max_threads && $keep_forking) {
my $urow = $get_next_user->();
unless ($urow) {
$keep_forking = 0;
next;
}
my $lockname = "synsuck-user-" . $urow->{user};
my $lock = LJ::locker()->trylock($lockname);
next unless $lock;
print "Got lock on '$lockname'. Running\n" if $verbose;
# spawn a new process
if (my $pid = fork) {
# we are a parent, nothing to do?
$child_jobs{$pid} = [$urow->{'userid'}, $lock];
$threads++;
$userct++;
} else {
# handles won't survive the fork
LJ::disconnect_dbs();
$process_user->($urow);
exit 0;
}
# wait for child(ren) to die
} else {
my $child = wait();
last if $child == -1;
delete $child_jobs{$child};
$threads--;
}
}
# Now wait on any remaining children so we don't leave zombies behind.
while ( %child_jobs ) {
my $child = wait();
last if $child == -1;
delete $child_jobs{ $child };
$threads--;
}
print "[$$] $userct users processed\n" if $verbose;
return;
};
1;
# Local Variables:
# mode: perl
# c-basic-indent: 4
# indent-tabs-mode: nil
# End:

30
local/bin/maint/taskinfo.txt Executable file
View File

@@ -0,0 +1,30 @@
bday.pl:
bdaymail - Sends people birthday wishes & notifications
stats.pl:
build_randomuserset - builds/cleans table of users applicable for inclusion in random listings
genstats - Generates the nightly statistics
genstats_size - Generates the site size stats
genstats_weekly - Generates the weekly statistics
memeclean - Removes things from meme summary that are excluded by new URL cleaner rules
statspics.pl:
genstatspics - Makes a bunch of graphs to show on the statistics page.
clean_caches.pl:
clean_caches - removes old cache files
synsuck.pl:
synsuck - Polls needed remote, syndicated RSS/etc and updates journals.
captcha.pl:
gen_audio_captchas - Generate any needed new audio challenges.
gen_image_captchas - Generate any needed new graphical challenges.
clean_captchas - Purge old challenges from the database.
generic.pl:
joinmail - Generates daily email digests for community join requests
clean_spamreports - Clean out data from the spamreports table older than 90 days.
clean_challenges.pl:
clean_challenges - Deletes old records from challenges table

254
local/bin/qbufferd.pl Executable file
View File

@@ -0,0 +1,254 @@
#!/usr/bin/perl
#
# <LJDEP>
# lib: Proc::ProcessTable, cgi-bin/ljlib.pl
# </LJDEP>
use strict;
use Getopt::Long
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
require "$ENV{'LJHOME'}/cgi-bin/supportlib.pl";
require "$ENV{'LJHOME'}/cgi-bin/ljcmdbuffer.pl";
require "$ENV{'LJHOME'}/cgi-bin/talklib.pl";
my $opt_foreground;
my $opt_debug;
my $opt_stop;
exit 1 unless GetOptions('foreground' => \$opt_foreground,
'debug' => \$opt_debug,
'stop' => \$opt_stop,
);
BEGIN {
$LJ::OPTMOD_PROCTABLE = eval "use Proc::ProcessTable; 1;";
}
my $DELAY = $LJ::QBUFFERD_DELAY || 15;
my $pidfile = $LJ::QBUFFERD_PIDFILE || "$ENV{'LJHOME'}/var/qbufferd.pid";
my $pid;
if (-e $pidfile) {
open (PID, $pidfile);
chomp ($pid = <PID>);
close PID;
if ($opt_stop) {
if (kill 15, $pid) {
print "Shutting down qbufferd.\n";
} else {
print "qbufferd not running?\n";
}
exit;
}
if ($LJ::OPTMOD_PROCTABLE) {
my $processes = Proc::ProcessTable->new()->table;
if (grep { $_->cmndline =~ /perl.+qbufferd/ && $_->pid != $$ } @$processes) {
exit;
}
} else {
if (kill 0, $pid) {
# seems to still be running (at least something is with that pid)
exit;
}
}
}
if ($opt_stop) {
print "qbufferd not running?\n";
exit;
}
$SIG{'INT'} = \&stop_qbufferd;
$SIG{'TERM'} = \&stop_qbufferd;
$SIG{'HUP'} = sub {
# nothing. maybe later make a HUP force a flush?
};
if (!$opt_foreground && ($pid = fork))
{
unless (open (PID, ">$pidfile")) {
kill 15, $pid;
die "Couldn't write PID file. Exiting.\n";
}
print PID $pid, "\n";
close PID;
print "qbufferd started with pid $pid\n";
if (-s $pidfile) { print "pid file written ($pidfile)\n"; }
exit;
}
# Close filehandles unless running in --debug or --foreground mode.
unless ( $opt_debug || $opt_foreground ) {
close STDIN && open STDIN, "</dev/null";
close STDOUT && open STDOUT, "+>&STDIN";
close STDERR && open STDERR, "+>&STDIN";
}
# fork off a separate qbufferd process for all specified
# job types in @LJ::QBUFFERD_ISOLATE, and then
# another process for all other job types. The current process
# will keep tabs on all of those
my %isolated;
my %pids; # job -> pid
my %jobs; # pid -> job
my $working = 0; # 1 for processes that do actual work
my $my_job;
foreach my $job (@LJ::QBUFFERD_ISOLATE) {
$isolated{$job} = 1;
}
foreach my $job (@LJ::QBUFFERD_ISOLATE, "_others_") {
if (my $child = fork) {
# parent.
$pids{$job} = $child;
$jobs{$child} = $job;
next;
} else {
# child.
$0 .= " [$job]";
$my_job = $job;
$working = 1;
last;
}
}
# at this point, $my_job is either the specialized 'cmd' to run, or
# '_others_' to mean everything besides stuff with their own processes.
# $working is 1 for nonempty values of $my_job .
sub stop_qbufferd
{
# stop children
unless ($working) {
foreach my $job (keys %pids) {
my $child = $pids{$job};
print "Killing child pid $child job: $job\n" if $opt_debug;
kill 15, $child;
}
unlink $pidfile;
}
print "Quitting: " . ($working ? "job $my_job" : "parent") . "\n" if $opt_debug;
exit;
}
while(not $working) {
# controlling process's cycle
my $pid;
$pid = wait();
print "Child exited, pid $pid, job $jobs{$pid}\n" if $opt_debug;
if ($jobs{$pid}) {
my $job = $jobs{$pid};
print "Restarting job $job\n" if $opt_debug;
delete $pids{$job};
delete $jobs{$pid};
if (my $child = fork) {
# parent.
$pids{$job} = $child;
$jobs{$child} = $job;
} else {
# child.
$0 .= " [$job]";
$my_job = $job;
$working = 1; # go work
}
}
}
# the actual work begins here
my @all_jobs = qw(delitem weblogscom send_mail support_notify dirty);
foreach my $hook (keys %LJ::HOOKS) {
next unless $hook =~ /^cmdbuf:(\w+):run$/;
push @all_jobs, $1;
}
while (LJ::start_request())
{
my $cycle_start = time();
print "Starting cycle. Job $my_job\n" if $opt_debug;
# syndication (checks RSS that need to be checked)
if ($my_job eq "synsuck") {
system("$ENV{'LJHOME'}/bin/ljmaint.pl", "-v0", "synsuck");
print "Sleeping. Job $my_job\n" if $opt_debug;
my $elapsed = time() - $cycle_start;
sleep ($DELAY-$elapsed) if $elapsed < $DELAY;
next;
}
# do main cluster updates
my $dbh = LJ::get_dbh("master");
unless ($dbh) {
sleep 10;
next;
}
# keep track of what commands we've run the start hook for
my %started;
# handle clusters
foreach my $c (@LJ::CLUSTERS) {
print "Cluster: $c Job: $my_job\n" if $opt_debug;
my $db = LJ::get_cluster_master($c);
next unless $db;
my @check_jobs = ($my_job);
if ($my_job eq "_others_") { @check_jobs = grep { ! $isolated{$_} } @all_jobs; }
foreach my $cmd (@check_jobs) {
my $have_jobs = $db->selectrow_array("SELECT cbid FROM cmdbuffer WHERE cmd=? LIMIT 1",
undef, $cmd);
next unless $have_jobs;
print " Starting $cmd...\n" if $opt_debug;
unless ($started{$cmd}++) {
LJ::Cmdbuffer::flush($dbh, undef, "$cmd:start");
}
LJ::Cmdbuffer::flush($dbh, $db, $cmd);
print " Finished $cmd.\n" if $opt_debug;
# monitor process size and job counts to suicide if necessary
my $size = 0;
if (open(S, "/proc/$$/status")) {
my $file;
{ local $/ = undef; $file = <S>; }
$size = $1 if $file =~ /VmSize:.+?(\d+)/;
close S;
}
# is it our time to go?
my $kill_job_ct = LJ::Cmdbuffer::get_property($cmd, 'kill_job_ct') || 0;
my $kill_mem_size = LJ::Cmdbuffer::get_property($cmd, 'kill_mem_size') || 0;
if ($kill_job_ct && $started{$cmd} >= $kill_job_ct ||
$kill_mem_size && $size >= $kill_mem_size)
{
# trigger reload of current child process
print "Job suicide: $cmd. (size=$size, rpcs=" . ($started{dirty}+0) . ")\n"
if $opt_debug;
# run end hooks before dying
foreach my $cmd (keys %started) {
LJ::Cmdbuffer::flush($dbh, undef, "$cmd:finish");
}
exit 0;
}
}
}
# run the end hook for all commands we've run
foreach my $cmd (keys %started) {
LJ::Cmdbuffer::flush($dbh, undef, "$cmd:finish");
}
print "Sleeping. Job $my_job\n" if $opt_debug;
my $elapsed = time() - $cycle_start;
sleep ($DELAY-$elapsed) if $elapsed < $DELAY;
};

5240
local/bin/upgrading/en.dat Executable file

File diff suppressed because it is too large Load Diff

2103
local/bin/upgrading/en_LJ.dat Executable file

File diff suppressed because it is too large Load Diff

5072
local/bin/upgrading/ru.dat Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
################################################################
# LiveJournal.com's non-free (not GPL) layers. You can use the
# source to learn from, but not copy.
################################################################
# base filename layer type parent
3column/layout layout core1
3column/themes theme+ 3column/layout
anovelconundrum/layout layout core1
anovelconundrum/themes theme+ anovelconundrum/layout
boxer/layout layout core1
boxer/themes theme+ boxer/layout
component/layout layout core1
component/themes theme+ component/layout
cuteness/layout layout core1
flexiblesquares/layout layout core1
flexiblesquares/themes theme+ flexiblesquares/layout
nebula/layout layout core1
nebula/themes theme+ nebula/layout
opal/layout layout core1
opal/themes theme+ opal/layout
smoothsailing/layout layout core1
smoothsailing/themes theme+ smoothsailing/layout
tranquilityii/layout layout core1
tranquilityii/themes theme+ tranquilityii/layout
unearthed/layout layout core1
unearthed/themes theme+ unearthed/layout
s2layers-ljcomint.dat INCLUDE

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,233 @@
#NEWLAYER: 3column/blue
layerinfo "type" = "theme";
layerinfo "name" = "Blue";
layerinfo "redist_uniq" = "3column/blue";
set color_bg = "#e9f3fa";
set font_color = "#0d446b";
set link_color = "#0d446b";
set link_hover = "#0d446b";
set link_side = "#0d446b";
set link_side_h = "#0d446b";
set side_bg = "#e9f3fa";
set entries_bg = "#e9f3fa";
set entries_border = "#0d446b";
set side_t_color = "#0d446b";
set button_bg = "#e9f3fa";
set button_bg_h = "#b0cce0";
set entries_font_color = "#0d446b";
set side_border = "#0d446b";
set c_sub_color = "#b0cce0";
set c_sub_bg = "#0d446b";
set side_h_color = "#0d446b";
set side_h_border = "#0d446b";
set side_h_bg = "#b0cce0";
set sub_color = "#0d446b";
#NEWLAYER: 3column/dark
layerinfo "type" = "theme";
layerinfo "name" = "Dark";
layerinfo "redist_uniq" = "3column/dark";
set color_bg = "#000000";
set font_color = "#c0c0c0";
set link_color = "#202020";
set link_hover = "#FFFFFF";
set link_side = "#95432D";
set link_side_h = "#BA7625";
set side_bg = "#000000";
set side_t_color = "C0C0C0";
set side_border = "#000000";
set side_h_color = "#C0C0C0";
set side_h_border = "#C0C0C0";
set side_h_bg = "#000000";
set entries_bg = "#58494E";
set entries_border = "#FFFFFF";
set button_bg = "#FFFFFF";
set button_bg_h = "#c0c0c0";
set entries_font_color = "#000000";
set c_sub_color = "#000000";
set c_sub_bg = "#ffffff";
set sub_color = "#C0C0C0";
#NEWLAYER: 3column/earth
layerinfo "type" = "theme";
layerinfo "name" = "Earth";
layerinfo "redist_uniq" = "3column/earth";
set color_bg = "#ECECEA";
set font_color = "#4F4637";
set link_color = "#4F4637";
set link_hover = "#1D4629";
set link_side = "#7B6E59";
set link_side_h = "#1D4629";
set side_bg = "#DBCEB9";
set side_t_color = "4F4637";
set side_border = "#7B6E59";
set side_h_color = "#ECECEA";
set side_h_border = "#ECECEA";
set side_h_bg = "#7B6E59";
set entries_bg = "#AB9F8B";
set entries_border = "#7B6E59";
set button_bg = "#ECECEA";
set button_bg_h = "#4F4637";
set entries_font_color = "#4F4637";
set c_sub_color = "#4F4637";
set c_sub_bg = "#ECECEA";
set sub_color = "#4F4637";
#NEWLAYER: 3column/unnamed
layerinfo "type" = "theme";
layerinfo "name" = "Unnamed";
layerinfo "redist_uniq" = "3column/unnamed";
set color_bg = "#E5D5C6";
set font_color = "#000000";
set link_color = "#202020";
set link_hover = "#000000";
set link_side = "#95432D";
set link_side_h = "#D63C3C";
set side_bg = "#E5D5C6";
set side_t_color = "#000000";
set side_border = "#E5D5C6";
set side_h_color = "#000000";
set side_h_border = "#000000";
set side_h_bg = "#E5D5C6";
set entries_bg = "#E5D5C6";
set entries_border = "#E5D5C6";
set button_bg = "#E5D5C6";
set button_bg_h = "#ccab8a";
set entries_font_color = "#000000";
set c_sub_color = "#ccab8a";
set c_sub_bg = "#E5D5C6";
set sub_color = "#000000";
#NEWLAYER: 3column/greenenvy
layerinfo "type" = "theme";
layerinfo "name" = "Green of Envy";
layerinfo "redist_uniq" = "3column/greenenvy";
set color_bg = "#d8ece7";
set font_color = "#1b2d29";
set link_color = "#1b2d29";
set link_hover = "#1b2d29";
set link_side = "#1b2d29";
set link_side_h = "#1b2d29";
set side_bg = "#d8ece7";
set entries_bg = "#d8ece7";
set entries_border = "#1b2d29";
set side_t_color = "#1b2d29";
set button_bg = "#d8ece7";
set button_bg_h = "#b1d5cb";
set entries_font_color = "#1b2d29";
set side_border = "#1b2d29";
set c_sub_color = "#b1d5cb";
set c_sub_bg = "#1b2d29";
set side_h_color = "#1b2d29";
set side_h_border = "#1b2d29";
set side_h_bg = "#b1d5cb";
set sub_color = "#1b2d29";
#NEWLAYER: 3column/blackwhite
layerinfo "type" = "theme";
layerinfo "name" = "Black and White";
layerinfo "redist_uniq" = "3column/blackwhite";
set color_bg = "#FFFFFF";
set font_color = "#808080";
set link_color = "#808080";
set link_hover = "#202020";
set link_side = "#c0c0c0";
set link_side_h = "#FFFFFF";
set side_bg = "#000000";
set side_t_color = "808080";
set side_border = "#ffffff";
set side_h_color = "#c0c0c0";
set side_h_border = "#c0c0c0";
set side_h_bg = "#808080";
set entries_bg = "#ffffff";
set entries_border = "#000000";
set button_bg = "#c0c0c0";
set button_bg_h = "#808080";
set entries_font_color = "#000000";
set c_sub_color = "#ffffff";
set c_sub_bg = "#000000";
set sub_color = "#202020";
#NEWLAYER: 3column/agentorange
layerinfo "type" = "theme";
layerinfo "name" = "Agent Orange";
layerinfo "redist_uniq" = "3column/agentorange";
set color_bg = "#f7e6d3";
set font_color = "#582604";
set link_color = "#582604";
set link_hover = "#582604";
set link_side = "#582604";
set link_side_h = "#582604";
set side_bg = "#f7e6d3";
set entries_bg = "#f7e6d3";
set entries_border = "#582604";
set side_t_color = "#582604";
set button_bg = "#f7e6d3";
set button_bg_h = "#e0c7aa";
set entries_font_color = "#582604";
set side_border = "#582604";
set c_sub_color = "#e0c7aa";
set c_sub_bg = "#582604";
set side_h_color = "#582604";
set side_h_border = "#582604";
set side_h_bg = "#e0c7aa";
set sub_color = "#b64c06";
#NEWLAYER: 3column/purple
layerinfo "type" = "theme";
layerinfo "name" = "Purple";
layerinfo "redist_uniq" = "3column/purple";
set color_bg = "#e8cff1";
set font_color = "#410458";
set link_color = "#410458";
set link_hover = "#410458";
set link_side = "#410458";
set link_side_h = "#410458";
set side_bg = "#e8cff1";
set entries_bg = "#e8cff1";
set entries_border = "#410458";
set side_t_color = "#410458";
set button_bg = "#e8cff1";
set button_bg_h = "#d1aae0";
set entries_font_color = "#410458";
set side_border = "#410458";
set c_sub_color = "#d1aae0";
set c_sub_bg = "#410458";
set side_h_color = "#410458";
set side_h_border = "#410458";
set side_h_bg = "#d1aae0";
set sub_color = "#410458";
#NEWLAYER: 3column/mellowyellow
layerinfo "type" = "theme";
layerinfo "name" = "Mellow Yellow";
layerinfo "redist_uniq" = "3column/mellowyellow";
set color_bg = "#f8f6da";
set font_color = "#42331e";
set link_color = "#42331e";
set link_hover = "#8d452f";
set link_side = "#8d452f";
set link_side_h = "#42331e";
set side_bg = "#f2c98e";
set entries_bg = "#f8f6da";
set entries_border = "#42331e";
set side_t_color = "#42331e";
set button_bg = "#f2c98e";
set button_bg_h = "#e8c098";
set entries_font_color = "#42331e";
set side_border = "#42331e";
set c_sub_color = "#42331e";
set c_sub_bg = "#f2c98e";
set side_h_color = "#333333";
set side_h_border = "#333333";
set side_h_bg = "#f8f6da";
set sub_color = "#d39945";

View File

@@ -0,0 +1,999 @@
# -*-s2-*-
layerinfo "type" = "layout";
layerinfo "name" = "A Novel Conundrum";
layerinfo "source_viewable" = 1;
layerinfo "redist_uniq" = "anovelconundrum/layout";
layerinfo "author_name" = "taion";
propgroup colors {
property Color page_back {
des = "Page background";
}
property Color entry_text {
des = "Entry text color";
}
property Color text_weaker {
des = "Weaker text color";
}
property Color page_link {
des = "Link color";
}
property Color page_vlink {
des = "Visited link color";
}
property Color page_alink {
des = "Active link color";
}
}
# From my last e-mail with Taion, the plan was to rasterize the leading fonts so that
# appearance issues could be avoided. However, I don't have access to many of the fonts
# that he tested with, so I'll have to put that off for later.
# You will need access to Microsoft provided fonts for most accurate rendering, but
# we are working on specifying usable alternatives that are cross platform friendly.
propgroup fonts {
property use font_base;
property string font_fallback {
des = "Alternative font style";
}
property string font_type {
des = "Body font type";
note = "General font class for body text";
}
property int font_size {
des = "Body font size (points)";
}
property int font_leading {
des = "Body font leading (points)";
}
property string title_letterspacing {
des = "Letterspacing in titles";
}
property bool title_smallcaps {
des = "Smallcaps in titles";
}
property bool title_underline {
des = "Underlined titles";
}
property string font_flourish_base {
des = "Font face for decorative flourishes";
}
property string font_flourish_fallback {
des = "Alternate font face for decorative flourishes";
}
property string font_flourish_type {
des = "Font type for decorative flourishes";
}
property string font_secondary_base {
des = "Font face for secondary text";
}
property string font_secondary_fallback {
des = "Alternate font face for secondary text";
}
property string font_secondary_type {
des = "Font type for secondary text";
}
property int font_secondary_size {
des = "Secondary font size (points)";
note = "For best results, match optical x-height with the body font";
}
property string flourish_rm {
des = "Right margin for flourishes";
}
property string dc_rm {
des = "Right margin for drop caps";
}
}
propgroup presentation {
property string dingbar_url {
des = "URL to spacer image between portions of content";
note = "A default will be chosen for you if left blank.";
}
property use page_recent_items;
property use page_friends_items;
property string body_width {
des = "Text body width";
}
property int dcLen {
des = "Minimum length in characters before using drop caps";
}
property use view_entry_disabled;
property use use_shared_pic;
property use comment_userpic_style;
property bool show_entrynav_icons {
des = "Toggle to show the next, memory, edit, etc icons on the entry view page";
}
property string page_background_image {
des = "URL to an image to be used for the page background";
}
property use external_stylesheet;
}
propgroup text {
property use text_post_comment;
property use text_read_comments;
property use text_post_comment_friends;
property use text_read_comments_friends;
property use text_meta_music;
property use text_meta_mood;
property string text_dingbar_alt {
des = "Alternative text for dingbar images";
noui = 1;
}
}
# Set default colors
set entry_text = "#000000";
set text_weaker = "#666666";
set page_link = "#000000";
set page_vlink = "#666666";
set page_alink = "#333333";
set page_back = "#F5F5DC";
set body_width = "35em";
set dcLen = 200;
set show_entrynav_icons = true;
set page_background_image = "";
set font_base = "Palatino Linotype";
set font_fallback = "Book Antiqua";
set font_type = "serif";
set font_flourish_base = "Edwardian Script ITC\", \"Edwardian Script ITC Semi-Expanded";
set font_flourish_fallback = "Zapfino\", \"Viner Hand ITC";
set font_flourish_type = "cursive";
set font_secondary_base = "Frutiger Linotype";
set font_secondary_fallback = "Tahoma";
set font_secondary_type = "sans-serif";
set font_size = 10;
set font_leading = 14;
set title_smallcaps = true;
set title_underline = false;
set title_letterspacing = "0.08em";
set font_secondary_size = 9;
set flourish_rm = "0.093em";
set dc_rm = "0.2em";
set dingbar_url = "";
set text_poster_anonymous = "an anonymous reader";
set text_dingbar_alt = "* * *";
set text_view_recent = "Entries";
set text_view_friends = "Friends";
set text_view_archive = "Archive";
set text_view_userinfo = "Profile";
function prop_init() {
var PalItem start = PalItem(0, $*entry_text);
var PalItem end = PalItem(13, $*page_back);
if ($*dingbar_url == "") { $*dingbar_url = palimg_gradient("anovelconundrum/dingbar.gif", $start, $end); }
}
function print_stylesheet() {
print clean_url($*page_background_image) != "" ? "body { background-image: url($*page_background_image); }" : "";
"""
body {
margin-top: 1in;
margin-bottom: 0.6in;
}
body, td, h2, .caption, h1, h3 {
""";
if ($*font_base != "" or $*font_fallback != "" or $*font_type != "") {
"font-family: ";
if ($*font_base != "") {
"\"$*font_base\"";
if ($*font_fallback != "" or $*font_type != "") {
", ";
}
}
if ($*font_fallback != "") {
"\"$*font_fallback\"";
if ($*font_type != "") {
", ";
}
}
if ($*font_type != "") {
"$*font_type";
}
";\n";
}
"""
font-size: ${*font_size}pt;
line-height: ${*font_leading}pt;
font-weight: normal;
}
.caption, h1, h3 {
"""; if($*title_smallcaps) {"""
font-variant: small-caps;
text-transform: lowercase;
"""; }
""" letter-spacing: $*title_letterspacing;
}
h1 { font-size: 16pt; }
h3 { font-size: 12pt; }
h2, .noul, .ult {
font-style: italic;
margin: 0px;
}
.caption {
"""; if($*title_underline) {"""
text-decoration: underline;
"""; }
""" }
.flourish, .bodyl:first-letter {
""";
if ($*font_flourish_base != "" or $*font_flourish_fallback != "" or $*font_flourish_type != "") {
"font-family: ";
if ($*font_flourish_base != "") {
"\"$*font_flourish_base\"";
if ($*font_flourish_fallback != "" or $*font_flourish_type != "") {
", ";
}
}
if ($*font_flourish_fallback != "") {
"\"$*font_flourish_fallback\"";
if ($*font_flourish_type != "") {
", ";
}
}
if ($*font_flourish_type != "") {
"$*font_flourish_type";
}
";\n";
}
"""
}
.flourish {
margin-right: ${*flourish_rm};
z-index: 1;
font-size: 34pt;
position: relative;
top: 0.1em;
text-transform: uppercase;
}
.sfon, .index, .author, select, input {
""";
if ($*font_secondary_base != "" or $*font_secondary_fallback != "" or $*font_secondary_type != "") {
"font-family: ";
if ($*font_secondary_base != "") {
"\"$*font_secondary_base\"";
if ($*font_secondary_fallback != "" or $*font_secondary_type != "") {
", ";
}
}
if ($*font_secondary_fallback != "") {
"\"$*font_secondary_fallback\"";
if ($*font_secondary_type != "") {
", ";
}
}
if ($*font_secondary_type != "") {
"$*font_secondary_type";
}
";\n";
}
""" font-size: ${*font_secondary_size}pt;
line-height: ${*font_leading}pt;
}
.index {
width: 10em;
margin-right: 1.2em;
}
.bodybox { width: $*body_width; }
.body, .bodyl, .bodyns {
text-align: justify;
}
.bodyl:first-letter {
font-size: """ + (2* $*font_leading) + """pt;
margin-bottom: -""" + $*font_size + """pt;
margin-right: ${*dc_rm};
float: left;
border-bottom: none;
text-transform: uppercase;
line-height: """ + (2* $*font_leading) + """pt;
}
.bodyns:first-line, .sc, small, .sct {
"""; if($*title_smallcaps) {"""
font-variant: small-caps;
text-transform: lowercase;
"""; }
if($*title_underline) {"""
text-decoration: underline;
"""; }
""" letter-spacing: 0.05em;
}
.sct {
letter-spacing: $*title_letterspacing;
text-align: center;
}
.author {
float: right;
text-align: center;
margin-left: 1.5em;
margin-bottom: 0.5em;
}
.ywp {
width: 2em;
margin-left: 0.5em;
margin-right: 0.5em;
}
blockquote {
margin-top: ${*font_leading}pt;
margin-bottom: ${*font_leading}pt;
margin-left: 2em;
}
tt, pre, textarea {
font-family: "Lucida Console", monospace;
font-size:"""+ ((${*font_size}*4)/5) + """pt;
}
a {text-decoration: none;}
.body a, .bodyl a, .bodyns a, .bodynsl a, .author a, .ult a, .uts a { border-bottom: 1px dotted; }
.ljuser a, a img, .smallbar a, .noul a { border-bottom: none; }
a:hover, .ljuser a:hover { border-bottom: 1px solid; }
p {
text-indent: 1.5em;
margin: 0px;
padding: 0px;
}
blockquote + p { text-indent: 0px; }
.uts {
font-size: 80%;
font-style: italic;
text-align: center;
line-height: """ + $*font_size + """pt;
margin-bottom: """ + ($*font_leading-$*font_size) + """pt;
}
.smallbar {
font-size: 80%;
font-style: italic;
text-align: center;
line-height: """ + (2*$*font_leading) + """pt;
clear: right;
}
.ljcomsel {
position: relative;
top: 0.75pt;
height: 7.5pt;
padding-left: 1pt;
}
input#username, input#password { margin-right: 0.5em; }
.bs {
margin-top: """ + (2*$*font_leading) + """pt;
margin-bottom: """ + (2*$*font_leading) + """pt;
text-align: center;
line-height: ${*font_leading}pt;
}
""";
}
function find_lpar(string t) : int {
foreach var int i (reverse (0 .. ($t->length()-1))) {
if($t->substr($i,1)=="(") { return $i; }
}
return -1;
}
function render_title(string t, int len) {
foreach var int i (0 .. ($len-1)) {
var string pc = $t->substr($i-1,1);
var string cc = $t->substr($i,1);
if($cc==" ") { " &middot; "; }
elseif( $i > 0 and $pc != " ") { "$cc"; }
elseif ($cc=="A" or $cc=="B" or $cc=="C" or $cc=="D" or $cc=="E" or $cc=="F" or $cc=="G" or $cc=="H" or $cc=="I" or $cc=="J" or $cc=="K" or $cc=="L" or $cc=="M" or $cc=="N" or $cc=="O" or $cc=="P" or $cc=="Q" or $cc=="R" or $cc=="S" or $cc=="T" or $cc=="U" or $cc=="V" or $cc=="W" or $cc=="X" or $cc=="Y" or $cc=="Z") {
"<span class='flourish'>$cc</span>";
}
else { "$cc"; }
}
}
function render_body(string t) {
var int str=0;
var bool par=false;
var bool pars=false;
$str = ($t->substr(0,6) == "<br />" ? 6 : 0);
if($t->substr(0,3) == "<p>") { $str = 3; $pars=true; }
foreach var int i ($str .. ($t->length()-1)) {
if($t->substr($i,12) == "<br /><br />") {
$str=$i+12;
if($par) { "</p><p>"; }
else { "<p>"; $par=true; }
}
elseif($pars and $t->substr($i,4) == "</p>") { $str=$i+4; $pars=false; }
elseif($i >= $str) { print $t->substr($i,1); }
}
if($par) { "</p>"; }
}
function display_title(Page p) {
var string dtitle = $p.global_title;
var string stitle = $p->view_title();
$stitle = ($p.view == "recent" ? $p.global_subtitle : $stitle);
var int lenm=$stitle->length()-1;
var int i=$dtitle->length()+1;
if ($dtitle == "") {
$dtitle = $p.journal.name;
$i=$dtitle->length()+1;
}
if ($p.view == "friends") {
$dtitle = $p->view_title();
$i=find_lpar($dtitle);
if($i==-1) { $i = $lenm+2; }
}
"""<div align="center">
<h1>"""; render_title($dtitle,$i-1); """</h1>""";
if($p.view != "friends" and $stitle != "") { """<br /><h3 style="margin-top:-1em;">$stitle</h3>"""; }
elseif($p.view == "friends" and $i<$lenm) { "<br /><h3 style='margin-top:-1em;'>" + $dtitle->substr($i+1,($lenm-$i)-1) + "</h3>"; }
"""</div>""";
}
function Page::print() {
var string title = $this->title();
var string links;
var bool firstlink = true;
foreach var string v ($.views_order) {
if ($firstlink == false) {
$links = "$links &middot; ";
}
else {
$firstlink = false;
}
$links = $links + ("<a href='$.view_url{$v}'>"+lang_viewname($v)+"</a>");
}
"""<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\n<html>\n<head>\n""";
if ($*external_stylesheet) {
println """<link rel="stylesheet" href="$.stylesheet_url" type="text/css" />""";
} else {
println """<style type="text/css">"""; print_stylesheet(); "</style>";
}
$this->print_head();
"""<title>$title</title>
</head>
<body bgcolor="$*page_back" text="$*entry_text" link="$*page_link" vlink="$*page_vlink" alink="$*page_alink">""";
display_title($this);
"""<div style="text-align:center; margin-bottom: ${*font_leading}pt;">
<h2>$links</h2>
</div>
""";
$this->print_body();
"""
</body>
</html>
""";
}
function print_entry(Page p, Entry e) {
var string date=$e.time->date_format("short");
var string time=$e.time->time_format();
"""
<table cellpadding='0' cellspacing='0' border='0' align='center'>
<tr><td align="center" colspan="2"><img
src="$*dingbar_url" alt="$*text_dingbar_alt" class="bs"/></td></tr>
<tr>
<td align="right" valign="top" width="100"><div class="index">""";
""" <a href="$e.permalink_url">$time<br />
$date</a><br /><br />
""";
$e.comments->print();
""" </div></td>
<td valign="top">
<div class="bodybox">
<div class="author">""";
if (defined $e.userpic) {
"""<img border="0" src="$e.userpic.url" width="$e.userpic.width" height="$e.userpic.height" alt=""><br />""";
}
elseif ($e.poster.journal_type == "C") {
"""<img border="0" src="$*IMGDIR/community.gif" alt="" /><br />""";
}
elseif ($e.poster.journal_type == "Y") {
"""<img border="0" src="$*IMGDIR/syndicated.gif" alt="" /><br />""";
}
else {
"""<img border="0" src="$*IMGDIR/userinfo.gif" alt="" /><br />""";
}
"<a href=\"" +
$e.poster->base_url() + "/\">$e.poster.username</a>";
if ($e.security != "") {
$e.security_icon->print();
}
if ($e.poster.username != $e.journal.username and $e.journal.journal_type =="C") {
""",<br />
<img border="0" src="$*IMGDIR/community.gif" alt="" align="absmiddle" />
<a href=\"""" + $e.journal->base_url() + """/">$e.journal.username</a>""";
}
var string subject=$e.subject;
if($p.view=="entry") { $subject=""; }
"""</div>
<div class="caption">
$subject
</div>""";
if ($subject == "" and $p.view!="entry") {"<div class='bodyns'>";}
elseif ($e.text->length() > $*dcLen) {"<div class='bodyl'>";}
else {"<div class='body'>";}
render_body($e.text);
var string metadata;
if ($e.metadata) {
$metadata = "<div style='margin-top:${*font_leading}pt;'><table cellspacing='0' cellpadding='0' border='0'>";
foreach var string k ($e.metadata) {
var string text = $k;
var string val = $e.metadata{$k};
if ($k == "mood") {
$text = $*text_meta_mood;
} elseif ($k == "music") {
$text = $*text_meta_music;
}
if ($k == "mood" and defined $e.mood_icon) {
var Image i = $e.mood_icon;
$val = "<img src='$i.url' width='$i.width' height='$i.height' align='middle' alt='$val'> $val";
}
$metadata = """$metadata\n<tr><td align="right"><div class="sc" style="margin-right:1em;">$text:</div></td>
<td align="left">$val</td></tr>""";
}
$metadata = """$metadata</table></div>""";
}
"""$metadata</div></div></td>
</tr>""";
if ($p.view == "entry" and $*show_entrynav_icons)
{
"""<tr><td align="center" colspan="2" style="line-height:${*font_leading}pt;"><img
src="$*dingbar_url" alt="$*text_dingbar_alt" class="bs" /></td></tr>
<tr><td colspan="2"><div style='text-align: center; margin-top: 0px;'>""";
$e->print_linkbar();
"""</div></td></tr>""";
}
"</table>";
} # print_entry(Page,Entry,Color,Color)
function Entry::print_linkbar() {
## There's no point in showing previous/next links on pages which show
## multiple entries anyway, so we only print them on EntryPage and ReplyPage.
var Page p = get_page();
var Link link;
var bool show_interentry = ($p.view == "entry" or $p.view == "reply");
"<h2>";
if ($show_interentry) {
var Link prev = $this->get_link("nav_prev");
"""<a href="$prev.url">$prev.caption</a> &middot """;
}
if ($p.view == "entry" and $.comments.enabled) {
if ($.comments.maxcomments) {
"Maximum Comments Reached";
} else {
"<a href=\"$.comments.post_url\">Leave a Comment</a>";
}
" &middot; ";
}
var int i=0;
foreach var string k ($.link_keyseq) {
$link = $this->get_link($k);
if($link.caption != "") {
if($i>0) { " &middot; "; }
"<a href='$link.url'>$link.caption</a>";
$i++;
}
}
if ($show_interentry) {
var Link next = $this->get_link("nav_next");
""" &middot <a href="$next.url">$next.caption</a>""";
}
"</h2>";
}
function Page::print_entry(Entry e) {
print_entry($this, $e);
}
function FriendsPage::print_entry(Entry e) {
print_entry($this, $e);
}
function RecentPage::print_body() {
foreach var Entry e ($.entries) {
$this->print_entry($e);
}
"""
<div align="center" class="bs" style="line-height: ${*font_leading}pt;"><img
src="$*dingbar_url" style="text-align:center;" alt="$*text_dingbar_alt" /></div>
<div align="center"><h2>
""";
# go forward/backward if possible
if ($.nav.forward_url != "" or $.nav.backward_url != "") {
var string sep;
var string back;
var string forward;
if ($.nav.backward_url != "") {
$back = """<a href="$.nav.backward_url">Previous</a>""";
}
if ($.nav.forward_url != "") {
$forward = """<a href="$.nav.forward_url">Next</a>""";
}
if ($back != "" and $forward != "") { $sep = " &middot; "; }
"$back$sep$forward";
}
"</h2></div>";
}
function CommentInfo::print() {
if (not $.enabled) { return; }
if ($.count > 0 or $.screened) {
$this->print_readlink(); "<br />";
}
$this->print_postlink();
}
function YearPage::print_year_links() {
"""<div class="bs">
<img src="$*dingbar_url" alt="$*text_dingbar_alt" />
</div><div class="sct">Years</div><h2 style="text-align:center;">""";
var bool d=false;
foreach var YearYear y ($.years) {
if($d) { " &middot; "; }
else { $d=true; }
if ($y.displayed) {
"$y.year";
} else {
"<a href=\"$y.url\">$y.year</a>";
}
}
"</h2>";
}
function YearPage::print_month(YearMonth m) {
if (not $m.has_entries) { return; }
"""<div class="bs">
<table cellpadding="0" cellspacing="0" border="0" summary="" align="center">
<tr><center class="noul">
<a href="$m.url">""";
print $m->month_format();
"""</a>
<!-- now the headings for the week -->
<table align="center" cellpadding="0" cellspacing="0" border="0" summary="">
<tr align="center">
""";
foreach var int d (weekdays()) {
"<td align='center'>"+$*lang_dayname_short[$d]+"</td>\n";
}
"</tr>";
foreach var YearWeek w ($m.weeks) {
$w->print();
}
"""</table></center>""";
}
function YearWeek::print() {
"<tr valign='top'>";
if ($.pre_empty) { "<td colspan='$.pre_empty'></td>"; }
foreach var YearDay d ($.days) {
"""<td><div class="ywp"><div class="sfon">$d.day</div>""";
if ($d.num_entries) {
"""<div class="uts"><a href="$d.url">$d.num_entries</a></div>""";
} else {
"&nbsp;";
}
"</div></td>";
}
if ($.post_empty) { "<td colspan='$.post_empty'></td>"; }
"</tr>";
}
function DayPage::print_body() {
if (not $.has_entries) { print "<div class='sct'>" + ehtml($*text_noentries_day) + "</div>"; }
foreach var Entry e ($.entries) {
$this->print_entry($e);
}
"""<div class="bs">
<img src="$*dingbar_url" alt="$*text_dingbar_alt" />
</div>""";
var string tprev = ehtml($*text_day_prev);
var string tnext = ehtml($*text_day_next);
"""<center><h2><a href="$.prev_url">$tprev</a> &middot; <a href="$.next_url">$tnext</a></h2></center>""";
}
function MonthPage::print_body() {
"""<div class="bs">
<img src="$*dingbar_url" alt="$*text_dingbar_alt" />
</div>""";
"<center><div class='bodybox'><center><table border='0' cellspacing='0' cellpadding='0'><tr><td><dl>";
foreach var MonthDay d ($.days) {
if ($d.has_entries) {
"<dt><a href=\"$d.url\"><i>";
print lang_ordinal($d.day);
"</i></a>:</dt>\n<dd>";
$d->print_subjectlist();
"</dd>\n";
}
}
"</dl></td></tr></table></center></div></center>\n";
"""<div class="bs">
<img src="$*dingbar_url" alt="$*text_dingbar_alt" />
</div>""";
"<form method='post' action='$.redir.url'><center>";
$.redir->print_hiddens();
if ($.prev_url != "") { "<a href='$.prev_url' style='font-size:12pt;'>&#9756;</a> "; }
if (size $.months > 1) {
"<select name='redir_key'>\n";
foreach var MonthEntryInfo mei ($.months) {
var string sel;
if ($mei.date.year == $.date.year and $mei.date.month == $.date.month) {
$sel = " selected='selected'";
}
"<option value='$mei.redir_key'$sel>" + $mei.date->date_format($*lang_fmt_month_long) + "</option>";
}
"</select>\n<input type='submit' value='View' />";
}
if ($.next_url != "") { " <a href='$.next_url' style='font-size:12pt;'>&#9758;</a>\n"; }
"</center></form>";
}
function EntryPage::print_body() {
print_entry($this, $.entry);
if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0) {
$.comment_pages->print();
$this->print_multiform_start();
"<div style='margin-top: 7pt;'></div>";
"<table align='center' cellspacing='0' border='0' cellpadding='0' style='display: none;'><tr><td>";
$this->print_comments($.comments);
"</td></tr></table>";
$.comment_pages->print();
if ($*show_entrynav_icons) {
"""<div class="bs">
<img src="$*dingbar_url" alt="$*text_dingbar_alt" />
</div>""";
"""<div class="bs">""";
$.entry->print_linkbar();
"""</div>""";
}
if ($this.multiform_on) {"""
<div class="bs">
<img src="$*dingbar_url" alt="$*text_dingbar_alt" />
</div>
<div style="text-align: center;">""";
$this->print_multiform_actionline();
$this->print_multiform_end();
"</div>";
}
}
}
function ItemRange::print() {
if ($.all_subitems_displayed) { return; }
"""<div class="bs">
<img src="$*dingbar_url" alt="$*text_dingbar_alt" />
</div>""";
"<center>";
"<a name='comments'></a><div style='width: $*body_width; text-align:center;'>";
"<h2>" + lang_page_of_pages($.current, $.total) + "</h2>";
var string url_prev = $this->url_of($.current - 1);
"<table cellspacing='0' cellpadding='0' border='0' align='center'><tr><td align='center' style='font-size: 14pt'>";
if ($.current != 1) {
print "<a href='$url_prev#comments'>&#9756;</a>";
} else {
print "&#9756;";
}
print " </td><td align='center'>";
foreach var int i (1..$.total) {
if ($i == $.current) { "$i"; }
else {
var string url_of = $this->url_of($i);
"<a href='$url_of#comments'>$i</a>";
}
if ($i != $.total) { ", "; }
}
"</td><td align='center' style='font-size: 14pt'> ";
var string url_next = $this->url_of($.current + 1);
if ($.current != $.total) {
print "<a href='$url_next#comments'>&#9758;</a>";
} else {
print "&#9758;";
}
"</td></tr></table></div></center>";
}
function EntryPage::print_comments(Comment[] cs) {
if (size $cs == 0) { return; }
foreach var Comment c ($cs) {
if($c.depth==1) {
"</td></tr></table>";
"""<div class="bs">
<img src="$*dingbar_url" alt="$*text_dingbar_alt" />
</div>""";
"<table align='center' cellspacing='0' border='0' cellpadding='0'><tr><td>";
}
var int indent = ($c.depth - 1) * 21;
"<div style='margin-left: ${indent}pt;'>\n";
if ($c.full) {
$this->print_comment($c);
} else {
$this->print_comment_partial($c);
}
"</div>";
$this->print_comments($c.replies);
}
}
function EntryPage::print_comment(Comment c) {
var string poster = defined $c.poster ? $c.poster->as_string() : $*text_poster_anonymous;
var string sub_icon;
if (defined $c.subject_icon) {
$sub_icon = $c.subject_icon->as_string();
}
"<a name='$c.anchor'></a>";
"<div class='bodybox'" + ($c.depth>1? " style='margin-top:${*font_leading}pt;'" : "") + ">";
if (defined $c.userpic and $*comment_userpic_style != "off") {
var int w = $c.userpic.width;
var int h = $c.userpic.height;
# WARNING: this will later be done by the system (it'll be a
# constructional property), so don't copy this hack into your
# layout layers or you'll be messed up later.
if ($*comment_userpic_style == "small") {
$w = $w / 2;
$h = $h / 2;
}
"<img src='$c.userpic.url' width='$w' height='$h' alt='[User Picture]' style='float: right;' class='author' />";
}
### From, date, etc
"<div class='noul'>";
if ($c.screened) { "<span style='color:$*text_weaker;'>(Screened) </span>"; }
"On " + $c.time->date_format("long") + ", " + $c.time->time_format() + ", $poster ";
if ($c.metadata{"poster_ip"}) { "(" + $c.metadata{"poster_ip"} + ") "; }
"<a href='$c.permalink_url'>";
if ($c.depth == 1) { "commented"; }
else { "replied"; }
"</a>:</div>";
print (defined $c.subject_icon or $c.subject != "") ? "<div class='caption'>$c.subject_icon $c.subject</div>" : "";
"<div class='body'>";
render_body($c.text);
print "</div><div class='smallbar'>";
if ($c.frozen) {
"Replies Frozen";
} else {
"<a href='$c.reply_url'>Reply</a>";
}
if ($c.parent_url != "") { " &middot; <a href='$c.parent_url'>Parent</a>"; }
if ($c.thread_url != "") { " &middot; <a href='$c.thread_url'>Thread</a>"; }
$c->print_linkbar();
if ($this.multiform_on) {
" &middot; ";
"<label for='ljcomsel_$c.talkid'>$*text_multiform_check</label>";
$c->print_multiform_check();
}
"</div></div>";
}
function EntryPage::print_comment_partial(Comment c) {
var string poster = defined $c.poster ? $c.poster->as_string() : $*text_poster_anonymous;
var bool subj = $c.subject != "";
"<div class='ult' style='width:$*body_width; margin-top:${*font_leading}pt;'>";
"&mdash;&thinsp;On " + $c.time->date_format("long") + ", " + $c.time->time_format() + ", $poster ";
if ($c.metadata{"poster_ip"}) { "(" + $c.metadata{"poster_ip"} + ") "; }
if($subj) { """replied, <a href="$c.permalink_url">&ldquo;$c.subject&rdquo;</a>"""; }
else { """posted <a href="$c.permalink_url">a reply</a>"""; }
".</div>";
}
function Comment::print_linkbar() {
var Link link;
foreach var string k ($.link_keyseq) {
$link = $this->get_link($k);
($link.caption != "") ? " &middot; <a href='$link.url'>$link.caption</a>" : "";
}
}
function ReplyPage::print_body() {
var bool ent = $.replyto.permalink_url == $.entry.permalink_url;
if($ent) {
print_entry($this, $.entry);
}
else {
"""<div class="bs">
<img src="$*dingbar_url" alt="$*text_dingbar_alt" />
</div>""";
var EntryLite c = $.replyto;
var string poster = defined $c.poster ? $c.poster->as_string() : $*text_poster_anonymous;
"<center><div style='width: $*body_width;'>";
if (defined $c.userpic and $*comment_userpic_style != "off") {
var int w = $c.userpic.width;
var int h = $c.userpic.height;
# WARNING: this will later be done by the system (it'll be a
# constructional property), so don't copy this hack into your
# layout layers or you'll be messed up later.
if ($*comment_userpic_style == "small") {
$w = $w / 2;
$h = $h / 2;
}
"<img src='$c.userpic.url' width='$w' height='$h' alt='[User Picture]' style='float: right;' class='author' />";
}
### From, date, etc
"<div class='noul'>";
"On " + $c.time->date_format("long") + ", " + $c.time->time_format() + ", $poster ";
if ($c.metadata{"poster_ip"}) { "(" + $c.metadata{"poster_ip"} + ") "; }
"<a href='$c.permalink_url'>commented:</a></div>";
print ($c.subject != "") ? "<div class='caption'>$c.subject</div>" : "";
"<div class='body'>";
render_body($c.text);
"</div></div></center>";
}
"""<div class="bs">
<img src="$*dingbar_url" alt="$*text_dingbar_alt" />
</div>""";
"<div style='text-align:center;'><h2><a href='$.entry.comments.read_url'>Read Comments</a></h2></div>";
"""<div class="bs">
<img src="$*dingbar_url" alt="$*text_dingbar_alt" />
</div>""";
if (not $.entry.comments.enabled) {
print "<div class='sct'>$*text_reply_nocomments</div>";
return;
}
"<center><h3 style='margin-top:0px; line-height:" + (2*$*font_leading) + "pt;'>Reply " + ($ent ? "to this entry" : "to this comment") + ":</h3>";
$.form->print();
"</center>";
}

View File

@@ -0,0 +1,179 @@
#NEWLAYER: anovelconundrum/renaissance
layerinfo "type" = "theme";
layerinfo "name" = "Renaissance";
layerinfo "redist_uniq" = "anovelconundrum/renaissance";
set font_secondary_fallback = "";
set font_secondary_size = 10;
set font_secondary_type = "serif";
set font_leading = 12;
set page_back = "#FAF2C8";
set font_fallback = "";
set font_secondary_base = "Garamond";
set font_base = "Garamond";
#NEWLAYER: anovelconundrum/modern
layerinfo "type" = "theme";
layerinfo "name" = "Modern";
layerinfo "redist_uniq" = "anovelconundrum/modern";
set font_leading = 14;
set page_back = "#F5F5E8";
set font_fallback = "";
set font_base = "Georgia";
set font_flourish_base = "";
set font_flourish_fallback = "";
set font_flourish_type = "";
set flourish_rm = "0.05em";
set dc_rm = "0.1em";
set dcLen = 5000;
#NEWLAYER: anovelconundrum/clippy
layerinfo "type" = "theme";
layerinfo "name" = "Clippy";
layerinfo "redist_uniq" = "anovelconundrum/clippy";
set font_leading = 13;
set page_back = "#FFFFFF";
set font_fallback = "Times";
set font_base = "Times New Roman";
set font_secondary_base = "Helvetica";
set font_secondary_fallback = "Arial";
set font_secondary_type = "sans-serif";
set font_secondary_size = 8;
set font_flourish_base = "";
set font_flourish_fallback = "";
set font_flourish_type = "";
set flourish_rm = "0.05em";
set dc_rm = "0.1em";
set flourish_rm = "0.08em";
set dcLen = 99999;
set body_width = "65ex";
#NEWLAYER: anovelconundrum/childsplay
layerinfo "type" = "theme";
layerinfo "name" = "Child's Play";
layerinfo "redist_uniq" = "anovelconundrum/childsplay";
set page_back = "#FFE6FF";
set font_base = "Comic Sans";
set font_fallback = "Chalkboard";
set font_type = "cursive";
set font_secondary_base = "";
set font_secondary_fallback = "";
set font_secondary_type = "";
set font_flourish_base = "";
set font_flourish_fallback = "";
set font_flourish_type = "";
set flourish_rm = "0.05em";
set dc_rm = "0.12em";
set flourish_rm = "0.08em";
set dcLen = 1000;
#NEWLAYER: anovelconundrum/laketahoe
layerinfo "type" = "theme";
layerinfo "name" = "Lake Tahoe";
layerinfo "redist_uniq" = "anovelconundrum/laketahoe";
set page_back = "#E6E6FF";
set font_base = "Tahoma";
set font_fallback = "Verdana";
set font_type = "sans-serif";
set font_secondary_base = "";
set font_secondary_fallback = "";
set font_secondary_type = "";
set font_flourish_base = "";
set font_flourish_fallback = "";
set font_flourish_type = "";
set flourish_rm = "0.05em";
set dc_rm = "0.14em";
set flourish_rm = "0.08em";
set dcLen = 500;
#NEWLAYER: anovelconundrum/deardiary
layerinfo "type" = "theme";
layerinfo "name" = "Dear Diary";
layerinfo "redist_uniq" = "anovelconundrum/deardiary";
set page_back = "#f9f7d6";
set font_base = "Lucida Handwriting";
set font_fallback = "";
set font_type = "cursive";
set font_leading = 16;
set body_width = "38em";
set font_secondary_base = "";
set font_secondary_fallback = "";
set font_secondary_type = "";
set font_flourish_base = "";
set font_flourish_fallback = "";
set font_flourish_type = "";
set flourish_rm = "0.05em";
set dc_rm = "0.12em";
set flourish_rm = "0.05em";
set dcLen = 500;
#NEWLAYER: anovelconundrum/scribal
layerinfo "type" = "theme";
layerinfo "name" = "Scribal";
layerinfo "redist_uniq" = "anovelconundrum/scribal";
set page_back = "#FAF2C8";
set font_base = "Lucida Calligraphy";
set font_fallback = "";
set font_type = "cursive";
set font_leading = 15;
set title_smallcaps = false;
set title_underline = true;
set font_secondary_base = "";
set font_secondary_fallback = "";
set font_secondary_type = "";
set font_flourish_base = "";
set font_flourish_fallback = "";
set font_flourish_type = "";
set flourish_rm = "0.05em";
set dc_rm = "0.12em";
set flourish_rm = "0.05em";
set dcLen = 500;
#NEWLAYER: anovelconundrum/glossy
layerinfo "type" = "theme";
layerinfo "name" = "Glossy Magazine";
layerinfo "redist_uniq" = "anovelconundrum/glossy";
set page_back = "#F4FBFF";
set font_base = "Lucida Bright";
set font_fallback = "Georgia";
set font_type = "serif";
set font_secondary_base = "Lucida Sans";
set font_secondary_fallback = "";
set font_secondary_type = "sans-serif";
set font_secondary_size = 9;
set font_flourish_base = "Agency FB";
set font_flourish_fallback = "";
set font_flourish_type = "";
set flourish_rm = "0.05em";
set dc_rm = "0.08em";
set flourish_rm = "0.02em";
set dcLen = 1200;
#NEWLAYER: anovelconundrum/retro
layerinfo "type" = "theme";
layerinfo "name" = "Retrossential";
layerinfo "redist_uniq" = "anovelconundrum/retro";
set page_back = "#f9f9e3";
set font_base = "Rockwell";
set font_fallback = "";
set font_type = "serif";
set font_size = 11;
set font_secondary_base = "";
set font_secondary_fallback = "";
set font_secondary_type = "";
set font_secondary_size = 10;
set font_flourish_base = "";
set font_flourish_fallback = "";
set font_flourish_type = "";
set flourish_rm = "0.05em";
set dc_rm = "0.12em";
set flourish_rm = "0.05em";
set dcLen = 500;

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,225 @@
#NEWLAYER: boxer/lipstick
layerinfo "type" = "theme";
layerinfo "name" = "Lipstick";
layerinfo redist_uniq = "boxer/lipstick";
layerinfo "source_viewable" = 0;
set color_nav_bg = "#B46F60";
set entry_link = "#ffeae5";
set entry_bg = "#eebbaf";
set nav_scale = "darker";
set info_font = "#A55745";
set bg_color = "#fac7bb";
set entry_font = "#A55745";
set info_link_visited = "#ffeae5";
set page_background_pattern = "background-hearts.gif";
set entry_link_visited = "#ffffff";
set info_bg = "#e5a799";
set info_link = "#FFF9F8";
#NEWLAYER: boxer/greyskies
layerinfo "type" = "theme";
layerinfo "name" = "Grey Skies";
layerinfo redist_uniq = "boxer/greyskies";
layerinfo "source_viewable" = 0;
set color_nav_bg = "#9aaeb6";
set entry_link = "#997D63";
set entry_bg = "#f2eae2";
set nav_scale = "lighter";
set info_font = "#627a84";
set bg_color = "#dde1e3";
set entry_font = "#7f97a0";
set info_link_visited = "#CEDBDF";
set page_background_pattern = "background-vert-stripes.gif";
set entry_link_visited = "#b4a18f";
set info_bg = "#8c9ca2";
set info_link = "#b9c7cc";
#NEWLAYER: boxer/eggplant
layerinfo "type" = "theme";
layerinfo "name" = "Eggplant";
layerinfo redist_uniq = "boxer/eggplant";
layerinfo "source_viewable" = 0;
set color_nav_bg = "#4e6559";
set entry_link = "#9FAE8D";
set entry_bg = "#635A48";
set nav_scale = "lighter";
set info_font = "#899BA3";
set bg_color = "#9fae8d";
set entry_font = "#E7DFCF";
set info_link_visited = "#b9c7cc";
set entry_link_visited = "#A6B2AC";
set info_bg = "#464640";
set info_link = "#b9c7cc";
#NEWLAYER: boxer/lonelyturquoise
layerinfo "type" = "theme";
layerinfo "name" = "Lonely Turquoise";
layerinfo redist_uniq = "boxer/lonelyturquoise";
layerinfo "source_viewable" = 0;
set page_background_pattern = "background-lg-boxes.gif";
set color_nav_bg = "#7f7f7f";
set entry_link_visited = "#ededed";
set entry_link = "#ffffff";
set entry_bg = "#ABABAB";
set info_font = "#000000";
set info_bg = "#00b1ae";
set bg_color = "#ffffff";
set entry_font = "#363636";
set info_link = "#006260";
#NEWLAYER: boxer/legallypink
layerinfo "type" = "theme";
layerinfo "name" = "Legally Pink";
layerinfo redist_uniq = "boxer/legallypink";
layerinfo "source_viewable" = 0;
set color_nav_bg = "#ff089b";
set entry_link_visited = "#70086F";
set entry_link = "#4D0870";
set entry_bg = "#ec008c";
set nav_scale = "lighter";
set info_font = "#ec008c";
set bg_color = "#f49ac1";
set entry_font = "#fbdbee";
set info_link_visited = "#CE1182";
set page_background_pattern = "background-hearts.gif";
set info_bg = "#ffadde";
set info_link = "#E3026A";
#NEWLAYER: boxer/greybrowngreen
layerinfo "type" = "theme";
layerinfo "name" = "Grey Brown Green";
layerinfo redist_uniq = "boxer/greybrowngreen";
layerinfo "source_viewable" = 0;
set color_nav_bg = "#2f372e";
set entry_link = "#212919";
set entry_bg = "#586C44";
set nav_scale = "lighter";
set info_font = "#A1926C";
set bg_color = "#000000";
set entry_font = "#D9E1D2";
set info_link_visited = "#B1AD9B";
set entry_link_visited = "#2C3F28";
set info_bg = "#433a1e";
set info_link = "#B1AD9B";
#NEWLAYER: boxer/precious
layerinfo "type" = "theme";
layerinfo "name" = "Precious";
layerinfo redist_uniq = "boxer/precious";
layerinfo "source_viewable" = 0;
set color_nav_bg = "#A17682";
set entry_link = "#0F486E";
set entry_bg = "#c6cfd5";
set nav_scale = "lighter";
set info_font = "#F7FDFC";
set bg_color = "#d9e1d9";
set entry_font = "#6C7982";
set info_link_visited = "#E4ECEB";
set entry_link_visited = "#3F6A86";
set info_bg = "#a2b2b1";
set info_link = "#E4ECEB";
#NEWLAYER: boxer/purple
layerinfo "type" = "theme";
layerinfo "name" = "Purple";
layerinfo redist_uniq = "boxer/purple";
layerinfo "source_viewable" = 0;
set color_nav_bg = "#78629C";
set entry_link = "#F9F5FC";
set entry_bg = "#62536C";
set nav_scale = "lighter";
set info_font = "#A38FA3";
set bg_color = "#8B77A9";
set entry_font = "#DCD3E2";
set info_link_visited = "#A799BF";
set entry_link_visited = "#ffffff";
set info_bg = "#472B47";
set info_link = "#A799BF";
#NEWLAYER: boxer/green
layerinfo "type" = "theme";
layerinfo "name" = "Green";
layerinfo redist_uniq = "boxer/green";
layerinfo "source_viewable" = 0;
set color_nav_bg = "#748A25";
set entry_link = "#EAF9D4";
set entry_bg = "#748A25";
set nav_scale = "lighter";
set info_font = "#004C3C";
set bg_color = "#254634";
set entry_font = "#E2EED0";
set info_link_visited = "#00EEBC";
set entry_link_visited = "#EAF9D4";
set info_bg = "#0E9B7D";
set info_link = "#61EFD1";
#NEWLAYER: boxer/purpange
layerinfo "type" = "theme";
layerinfo "name" = "Purpange";
layerinfo redist_uniq = "boxer/purpange";
layerinfo "source_viewable" = 0;
set color_nav_bg = "#151e1a";
set nav_scale = "lighter";
set entry_link = "#ffffff";
set entry_bg = "#E7513E";
set info_font = "#f6cab7";
set bg_color = "#ffffff";
set entry_font = "#FDE9E6";
set info_link_visited = "#afe900";
set page_background_pattern = "background-stitched.gif";
set entry_link_visited = "#ffffff";
set info_bg = "#91125f";
set info_link = "#afe900";
#NEWLAYER: boxer/purplesalmon
layerinfo "type" = "theme";
layerinfo "name" = "Purple Salmon";
layerinfo redist_uniq = "boxer/purplesalmon";
layerinfo "source_viewable" = 0;
set color_nav_bg = "#AA6B90";
set entry_link = "#633F4B";
set entry_bg = "#CEADB8";
set nav_scale = "same";
set info_font = "#F0B4AA";
set bg_color = "#151E1A";
set entry_font = "#6D5B61";
set info_link_visited = "#7E3D33";
set entry_link_visited = "#633F4B";
set info_bg = "#D26E5E";
set info_link = "#7E3D33";
#NEWLAYER: boxer/refriedtribute
layerinfo "type" = "theme";
layerinfo "name" = "Refried Tribute";
layerinfo redist_uniq = "boxer/refriedtribute";
layerinfo "source_viewable" = 0;
set color_nav_bg = "#666666";
set entry_link = "#336699";
set entry_bg = "#e6e6e6";
set info_font = "#999966";
set bg_color = "#ffffff";
set entry_font = "#656565";
set info_link_visited = "#4d4d4d";
set page_background_pattern = "none";
set entry_link_visited = "#336699";
set info_bg = "#cccc99";
set info_link = "#666666";
#NEWLAYER: boxer/blue
layerinfo "type" = "theme";
layerinfo "name" = "Blue";
layerinfo redist_uniq = "boxer/blue";
layerinfo "source_viewable" = 0;
set color_nav_bg = "#3A6A74";
set entry_link = "#E0DFCE";
set entry_bg = "#4F7B8A";
set info_font = "#908F78";
set bg_color = "#435754";
set entry_font = "#E7EEF0";
set info_link_visited = "#5D5C50";
set entry_link_visited = "#E0DFCE";
set info_bg = "#E0DFCE";
set info_link = "#4E5964";

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,187 @@
#NEWLAYER: component/aquatic
layerinfo "type" = "theme";
layerinfo "name" = "Aquatic";
layerinfo redist_uniq = "component/aquatic";
layerinfo "source_viewable" = 0;
set entry_fgcolor = "#515151";
set comp_bgcolor = "#51ada6";
set header_link = "#ffffff";
set entry_link = "#0C5D57";
set entry_bgcolor = "#ffffff";
set header_fgcolor = "#c7d1cc";
set main_bgcolor = "#51ada6";
set calendar_active = "#318D86";
set header_bgcolor = "#0e3b4a";
set calendar_inactive = "#ffffff";
set comp_fgcolor = "#F7FEFF";
#NEWLAYER: component/bluetiful
layerinfo "type" = "theme";
layerinfo "name" = "Bluetiful";
layerinfo redist_uniq = "component/bluetiful";
layerinfo "source_viewable" = 0;
set entry_fgcolor = "#606060";
set comp_bgcolor = "#f4f4f4";
set header_link = "#f7fcfb";
set entry_link = "#2d3679";
set entry_bgcolor = "#eff5ff";
set header_fgcolor = "#327192";
set main_bgcolor = "#a2c5e3";
set header_bgcolor = "#6da6c4";
set comments_bgcolor = "#84b5d2";
#NEWLAYER: component/darkness
layerinfo "type" = "theme";
layerinfo "name" = "Darkness";
layerinfo redist_uniq = "component/darkness";
layerinfo "source_viewable" = 0;
set comments_screened_bgcolor = "#22620e";
set calendar_fgcolor = "#5b6c7a";
set calendar_active = "#5b6c7a";
set calendar_inactive = "#adbac5";
set comp_fgcolor = "#dadde0";
set entry_fgcolor = "#dddcd6";
set comp_bgcolor = "#758491";
set entry_link = "#adb6be";
set header_link = "#c7ccd1";
set entry_bgcolor = "#32343d";
set main_bgcolor = "#71837A";
set header_fgcolor = "#c7d1cc";
set header_bgcolor = "#728d80";
set comments_bgcolor = "#5a5a5a";
#NEWLAYER: component/jedicloak
layerinfo "type" = "theme";
layerinfo "name" = "Jedi Cloak";
layerinfo redist_uniq = "component/jedicloak";
layerinfo "source_viewable" = 0;
set entry_fgcolor = "#F1EDE5";
set comp_bgcolor = "#988b67";
set header_link = "#dddbd6";
set entry_link = "#615020";
set entry_bgcolor = "#ada386";
set comments_screened_bgcolor = "#a29f97";
set header_fgcolor = "#bcb59f";
set main_bgcolor = "#6e5845";
set calendar_active = "#817452";
set header_bgcolor = "#6e6449";
set calendar_inactive = "#988b67";
set comp_fgcolor = "#383325";
set comments_bgcolor = "#948B6F";
#NEWLAYER: component/mellow
layerinfo "type" = "theme";
layerinfo "name" = "Mellow";
layerinfo redist_uniq = "component/mellow";
layerinfo "source_viewable" = 0;
set comments_screened_bgcolor = "#D6C8CC";
set page_background_image = "";
set calendar_active = "#D9E1D9";
set calendar_inactive = "#A2B2B1";
set comp_fgcolor = "878D8D";
set entry_fgcolor = "#355351";
set comp_bgcolor = "#C6CFD5";
set entry_link = "#6B7F8D";
set header_link = "6B7F8D";
set entry_bgcolor = "#A2B2B1";
set main_bgcolor = "#D6C8CC";
set header_fgcolor = "#96A891";
set header_bgcolor = "#D9E1D9";
set comments_bgcolor = "#BCC4C3";
#NEWLAYER: component/mocha
layerinfo "type" = "theme";
layerinfo "name" = "Mocha";
layerinfo redist_uniq = "component/mocha";
layerinfo "source_viewable" = 0;
set page_background_image = "";
set entry_fgcolor = "#807C75";
set comp_bgcolor = "#b1bbb4";
set comp_fgcolor = "#78746e";
set header_link = "#716C53";
set entry_link = "#67716a";
set entry_bgcolor = "#ebe6d1";
set comments_screened_bgcolor = "#b2c9b9";
set header_fgcolor = "#7a6f43";
set main_bgcolor = "#d8d0ae";
set calendar_active = "#8da193";
set header_bgcolor = "#d8d0ae";
set calendar_inactive = "#d3e1d7";
set comments_bgcolor = "#dbdedc";
#NEWLAYER: component/orangesoda
layerinfo "type" = "theme";
layerinfo "name" = "Orange Soda";
layerinfo redist_uniq = "component/orangesoda";
layerinfo "source_viewable" = 0;
set entry_fgcolor = "#8a5b33";
set comp_bgcolor = "#c4bd8e";
set header_link = "#FFFFFF";
set entry_link = "#613815";
set entry_bgcolor = "#dbd7b9";
set comments_screened_bgcolor = "#cbc9b9";
set header_fgcolor = "#d7d2af";
set main_bgcolor = "#cd9338";
set calendar_active = "#cd9338";
set header_bgcolor = "#c6710a";
set calendar_inactive = "#dbd7b9";
set comments_bgcolor = "#e4deb5";
#NEWLAYER: component/pinkelephants
layerinfo "type" = "theme";
layerinfo "name" = "Pink Elephants";
layerinfo redist_uniq = "component/pinkelephants";
layerinfo "source_viewable" = 0;
set comments_screened_bgcolor = "#e29994";
set page_background_image = "";
set calendar_active = "#a8a8a7";
set calendar_inactive = "#e29994";
set comp_fgcolor = "#ad5a55";
set entry_fgcolor = "#ffffff";
set comp_bgcolor = "#f7b3ae";
set entry_link = "#777776";
set header_link = "#FFFFFF";
set entry_bgcolor = "#a8a8a7";
set main_bgcolor = "#e29994";
set header_fgcolor = "#ad5a55";
set header_bgcolor = "#e29994";
set comments_bgcolor = "#9c9c9c";
#NEWLAYER: component/sugarspice
layerinfo "type" = "theme";
layerinfo "name" = "Sugar and Spice";
layerinfo redist_uniq = "component/sugarspice";
layerinfo "source_viewable" = 0;
set entry_fgcolor = "#927DAD";
set comp_bgcolor = "#D5EBFA";
set header_link = "#6e5593";
set entry_link = "#759EBA";
set entry_bgcolor = "#D5E9D7";
set comments_screened_bgcolor = "#BEC9BF";
set header_fgcolor = "#6E5593";
set main_bgcolor = "#FCD9C4";
set calendar_active = "#FCD9C4";
set header_bgcolor = "#D4CAE1";
set calendar_inactive = "#D4CAE1";
set comp_fgcolor = "AA9ABF";
set comments_bgcolor = "#B9DABC";
#NEWLAYER: component/greensuperhero
layerinfo "type" = "theme";
layerinfo "name" = "That Green Superhero";
layerinfo redist_uniq = "component/greensuperhero";
layerinfo "source_viewable" = 0;
set comments_screened_bgcolor = "#c99bd7";
set page_background_image = "";
set calendar_active = "#bc6ed4";
set calendar_inactive = "#c99bd7";
set comp_fgcolor = "#bc87cb";
set entry_fgcolor = "#424242";
set comp_bgcolor = "#efefe1";
set entry_link = "#027040";
set header_link = "#ffffff";
set entry_bgcolor = "#e4ede9";
set main_bgcolor = "#16b16c";
set header_fgcolor = "#d0efe2";
set header_bgcolor = "#049957";
set comments_bgcolor = "#bed8cc";

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,615 @@
#NEWLAYER: flexiblesquares/autumn
layerinfo "redist_uniq" = "flexiblesquares/autumn";
layerinfo "type" = "theme";
layerinfo "name" = "Autumn";
layerinfo author_name = "sub_divided/cyrnelle";
set page_bgcolor = "#351805";
set page_fgcolor = "#000000";
set content_bgcolor = "#6a3106";
set entry_bgcolor = "#eee293";
set entry_fgcolor = "#661f0c";
set border_color = "#000000";
set entrytitle_bgcolor = "#8b4e1d";
set outer_table_bgcolor = "#c47b51";
set sidebar_header_bgcolor = "#8b4e1d";
set sidebar_fgcolor = "#000000";
set header_footer_bgcolor = "#eee293";
set header_footer_fgcolor = "#661f0c";
set link_color = "#608729";
set link_hover_color = "#661f0c";
set comments_link_color = "#FFFFFF";
set comments_link_hover = "#c47b51";
set sidebar_link_color = "#608729";
set sidebar_link_hover = "#eee293";
set header_footer_link_color = "#608729";
set header_footer_link_hover = "#661f0c";
#NEWLAYER: flexiblesquares/blackwhite
layerinfo "redist_uniq" = "flexiblesquares/blackwhite";
layerinfo "type" = "theme";
layerinfo "name" = "Black and White and Red All Over";
layerinfo author_name = "sub_divided/cyrnelle";
set page_bgcolor = "#cccccc";
set page_fgcolor = "#ff0000";
set content_bgcolor = "#000000";
set entry_bgcolor = "#ffffff";
set entry_fgcolor = "#000000";
set border_color = "#ffffff";
set entrytitle_bgcolor = "#cc0000";
set outer_table_bgcolor = "#666666";
set sidebar_header_bgcolor = "#cc0000";
set sidebar_fgcolor = "#ffffff";
set header_footer_bgcolor = "#000000";
set header_footer_fgcolor = "#cc0000";
set date_fgcolor = "#000000";
set subject_fgcolor = "#000000";
set link_color = "#999999";
set link_hover_color = "#000000";
set comments_link_color = "#FFFFFF";
set comments_link_hover = "#000000";
set sidebar_link_color = "#999999";
set sidebar_link_hover = "#ffffff";
set header_footer_link_color = "#ffffff";
set header_footer_link_hover = "#999999";
#NEWLAYER: flexiblesquares/freshpaint
layerinfo "redist_uniq" = "flexiblesquares/freshpaint";
layerinfo "type" = "theme";
layerinfo "name" = "Fresh Paint";
layerinfo author_name = "sub_divided/cyrnelle";
set page_bgcolor = "#993366";
set page_fgcolor = "#006633";
set content_bgcolor = "#ff9933";
set entry_bgcolor = "#ffff99";
set entry_fgcolor = "#000000";
set border_color = "#6699cc";
set entrytitle_bgcolor = "#ccff66";
set outer_table_bgcolor = "#330033";
set sidebar_header_bgcolor = "#ccff66";
set sidebar_fgcolor = "#000000";
set header_footer_bgcolor = "#ffff99";
set header_footer_fgcolor = "#006633";
set date_fgcolor = "#000000";
set subject_fgcolor = "#000000";
set link_color = "#993333";
set link_hover_color = "#330033";
set comments_link_color = "#993333";
set comments_link_hover = "#330033";
set sidebar_link_color = "#993333";
set sidebar_link_hover = "#330033";
set header_footer_link_color = "#993333";
set header_footer_link_hover = "#330033";
#NEWLAYER: flexiblesquares/nautical
layerinfo "redist_uniq" = "flexiblesquares/nautical";
layerinfo "type" = "theme";
layerinfo "name" = "Nautical";
layerinfo author_name = "sub_divided/cyrnelle";
set page_bgcolor = "#bad2f6";
set page_fgcolor = "#000000";
set content_bgcolor = "#213659";
set entry_bgcolor = "#ffffff";
set entry_fgcolor = "#000000";
set border_color = "#d4e2f8";
set entrytitle_bgcolor = "#f0ef8e";
set outer_table_bgcolor = "#335288";
set sidebar_header_bgcolor = "#f0ef8e";
set sidebar_fgcolor = "#7fa1d5";
set header_footer_bgcolor = "#213659";
set header_footer_fgcolor = "#f0ef8e";
set date_fgcolor = "#000000";
set subject_fgcolor = "#000000";
set link_color = "#7fa1d5";
set link_hover_color = "#000000";
set comments_link_color = "#335288";
set comments_link_hover = "#7fa1d5";
set sidebar_link_color = "#f0ef8e";
set sidebar_link_hover = "#000000";
set header_footer_link_color = "#7fa1d5";
set header_footer_link_hover = "#ffffff";
#NEWLAYER: flexiblesquares/machine
layerinfo "redist_uniq" = "flexiblesquares/machine";
layerinfo "type" = "theme";
layerinfo "name" = "Machine";
layerinfo author_name = "sub_divided/cyrnelle";
set page_bgcolor = "#000000";
set page_fgcolor = "#C1C1C1";
set content_bgcolor = "#000000";
set entry_bgcolor = "#000000";
set entry_fgcolor = "#cbd3d8";
set border_color = "#7e8997";
set entrytitle_bgcolor = "#555a60";
set outer_table_bgcolor = "#000000";
set sidebar_header_bgcolor = "#555a60";
set sidebar_fgcolor = "#C1C1C1";
set header_footer_bgcolor = "#000000";
set header_footer_fgcolor = "#C1C1C1";
set date_fgcolor = "#C1C1C1";
set subject_fgcolor = "#C1C1C1";
set link_color = "#8797a0";
set link_hover_color = "#ffffff";
set comments_link_color = "#8797a0";
set comments_link_hover = "#ffffff";
set sidebar_link_color = "#8797a0";
set sidebar_link_hover = "#ffffff";
set header_footer_link_color = "#8797a0";
set header_footer_link_hover = "#ffffff";
#NEWLAYER: flexiblesquares/pastelspring
layerinfo "redist_uniq" = "flexiblesquares/pastelspring";
layerinfo "type" = "theme";
layerinfo "name" = "Pastel Spring";
layerinfo author_name = "sub_divided/cyrnelle";
set page_bgcolor = "#ffffff";
set page_fgcolor = "#993333";
set content_bgcolor = "#ffffcc";
set entry_bgcolor = "#ffffff";
set entry_fgcolor = "#000000";
set border_color = "#ebccb1";
set entrytitle_bgcolor = "#ebccb1";
set outer_table_bgcolor = "#dae3b2";
set sidebar_header_bgcolor = "#ebccb1";
set sidebar_fgcolor = "#993333";
set header_footer_bgcolor = "#ffffff";
set header_footer_fgcolor = "#9FA876";
set date_fgcolor = "#993333";
set subject_fgcolor = "#993333";
set link_color = "#9d7980";
set link_hover_color = "#000000";
set comments_link_color = "#993333";
set comments_link_hover = "#ffffff";
set sidebar_link_color = "#9d7980";
set sidebar_link_hover = "#9FA876";
set header_footer_link_color = "#9F3E3E";
set header_footer_link_hover = "#ebccb1";
#NEWLAYER: flexiblesquares/pinkpunk
layerinfo "redist_uniq" = "flexiblesquares/pinkpunk";
layerinfo "type" = "theme";
layerinfo "name" = "Pink Punk";
layerinfo author_name = "sub_divided/cyrnelle";
set page_bgcolor = "#000000";
set page_fgcolor = "#cc0066";
set content_bgcolor = "#000000";
set entry_bgcolor = "#ffccff";
set entry_fgcolor = "#000000";
set border_color = "#000000";
set entrytitle_bgcolor = "#ff6699";
set outer_table_bgcolor = "#cc0066";
set sidebar_header_bgcolor = "#ff6699";
set sidebar_fgcolor = "#ffccff";
set header_footer_bgcolor = "#ffccff";
set header_footer_fgcolor = "#000000";
set date_fgcolor = "#000000";
set subject_fgcolor = "#000000";
set link_color = "#6666cc";
set link_hover_color = "#ff6699";
set comments_link_color = "#ffccff";
set comments_link_hover = "#6666cc";
set sidebar_link_color = "#6666cc";
set sidebar_link_hover = "#ff6699";
set header_footer_link_color = "#6666cc";
set header_footer_link_hover = "#ff6699";
#NEWLAYER: flexiblesquares/purpleperiwinkle
layerinfo "redist_uniq" = "flexiblesquares/purpleperiwinkle";
layerinfo "type" = "theme";
layerinfo "name" = "Purple Periwinkle";
layerinfo author_name = "sub_divided/cyrnelle";
set page_bgcolor = "#2f0b31";
set page_fgcolor = "#2f0b31";
set content_bgcolor = "#671368";
set entry_bgcolor = "#f4a3e9";
set entry_fgcolor = "#2f0b31";
set border_color = "#2f0b31";
set entrytitle_bgcolor = "#9488d8";
set outer_table_bgcolor = "#a13ea7";
set sidebar_header_bgcolor = "#9488d8";
set sidebar_fgcolor = "#DADADA";
set header_footer_bgcolor = "#f4a3e9";
set header_footer_fgcolor = "#2f0b31";
set date_fgcolor = "#2f0b31";
set subject_fgcolor = "#2f0b31";
set link_color = "#dc039d";
set link_hover_color = "#7e025a";
set comments_link_color = "#7e025a";
set comments_link_hover = "#f4a3e9";
set sidebar_link_color = "#dc039d";
set sidebar_link_hover = "#FFCCCC";
set header_footer_link_color = "#dc039d";
set header_footer_link_hover = "#7e025a";
#NEWLAYER: flexiblesquares/grays
layerinfo "redist_uniq" = "flexiblesquares/grays";
layerinfo "type" = "theme";
layerinfo "name" = "Grays";
layerinfo author_name = "sub_divided/cyrnelle";
set page_bgcolor = "#111111";
set page_fgcolor = "#ffffff";
set content_bgcolor = "#333333";
set entry_bgcolor = "#666666";
set entry_fgcolor = "#ffffff";
set border_color = "#ffffff";
set entrytitle_bgcolor = "#000000";
set outer_table_bgcolor = "#222222";
set sidebar_header_bgcolor = "#000000";
set sidebar_fgcolor = "#ffffff";
set header_footer_bgcolor = "#666666";
set header_footer_fgcolor = "#ffffff";
set date_fgcolor = "#ffffff";
set subject_fgcolor = "#ffffff";
set link_color = "#ffcc33";
set link_hover_color = "#ff9933";
set comments_link_color = "#ffcc33";
set comments_link_hover = "#ff9933";
set sidebar_link_color = "#ffcc33";
set sidebar_link_hover = "#ff9933";
set header_footer_link_color = "#ffcc33";
set header_footer_link_hover = "#ff9933";
#NEWLAYER: flexiblesquares/lemongrapetang
layerinfo "redist_uniq" = "flexiblesquares/lemongrapetang";
layerinfo "type" = "theme";
layerinfo "name" = "Lemon Grapefruit Tangerine";
layerinfo author_name = "sub_divided/cyrnelle";
set page_bgcolor = "#ffff66";
set page_fgcolor = "#993333";
set content_bgcolor = "#cc3333";
set entry_bgcolor = "#ffffcc";
set entry_fgcolor = "#000000";
set border_color = "#ff9999";
set entrytitle_bgcolor = "#ff9933";
set outer_table_bgcolor = "#ffcc33";
set sidebar_header_bgcolor = "#ff9933";
set sidebar_fgcolor = "#000000";
set header_footer_bgcolor = "#ffffcc";
set header_footer_fgcolor = "#993333";
set date_fgcolor = "#000000";
set subject_fgcolor = "#000000";
set link_color = "#ff9999";
set link_hover_color = "#993333";
set comments_link_color = "#993333";
set comments_link_hover = "#000000";
set sidebar_link_color = "#ff9999";
set sidebar_link_hover = "#000000";
set header_footer_link_color = "#ff9999";
set header_footer_link_hover = "#993333";
#NEWLAYER: flexiblesquares/tanteal
layerinfo "redist_uniq" = "flexiblesquares/tanteal";
layerinfo "type" = "theme";
layerinfo "name" = "Tan and Teal";
layerinfo author_name = "sub_divided/cyrnelle";
set page_bgcolor = "#003333";
set page_fgcolor = "#000000";
set content_bgcolor = "#cc9966";
set entry_bgcolor = "#ffffcc";
set entry_fgcolor = "#000000";
set border_color = "#ffffff";
set entrytitle_bgcolor = "#996633";
set outer_table_bgcolor = "#ffcc99";
set sidebar_header_bgcolor = "#996633";
set sidebar_fgcolor = "#000000";
set header_footer_bgcolor = "#ffffcc";
set header_footer_fgcolor = "#000000";
set date_fgcolor = "#000000";
set subject_fgcolor = "#000000";
set link_color = "#993333";
set link_hover_color = "#603913";
set comments_link_color = "#ffffcc";
set comments_link_hover = "#000000";
set sidebar_link_color = "#993333";
set sidebar_link_hover = "#000000";
set header_footer_link_color = "#993333";
set header_footer_link_hover = "#000000";
#NEWLAYER: flexiblesquares/gentledawn
layerinfo "redist_uniq" = "flexiblesquares/gentledawn";
layerinfo "type" = "theme";
layerinfo "name" = "Gentle Dawn";
layerinfo author_name = "Yati Mansor";
set page_bgcolor = "#747D86";
set page_fgcolor = "#605734";
set content_bgcolor = "#FCCA7D";
set entry_bgcolor = "#FFD3B9";
set entry_fgcolor = "#605734";
set border_color = "#908350";
set entrytitle_bgcolor = "#BAA969";
set outer_table_bgcolor = "#DABD63";
set sidebar_header_bgcolor = "#BAA969";
set sidebar_fgcolor = "#605734";
set header_footer_bgcolor = "#FFD3B9";
set header_footer_fgcolor = "#605734";
set link_color = "#7E858D";
set link_hover_color = "#C68DA5";
set comments_link_color = "#FFFFFF";
set comments_link_hover = "#605734";
set sidebar_link_color = "#7E858D";
set sidebar_link_hover = "#C68DA5";
set header_footer_link_color = "#7E858D";
set header_footer_link_hover = "#C68DA5";
#NEWLAYER: flexiblesquares/icyblue
layerinfo "redist_uniq" = "flexiblesquares/icyblue";
layerinfo "type" = "theme";
layerinfo "name" = "Icy Blue";
layerinfo author_name = "Yati Mansor";
set page_bgcolor = "#C6C2F8";
set page_fgcolor = "#4F4D65";
set content_bgcolor = "#D3DCFC";
set entry_bgcolor = "#DDEFFF";
set entry_fgcolor = "#4F4D65";
set border_color = "#FFFFFF";
set entrytitle_bgcolor = "#FFFFFF";
set date_fgcolor = "#4F4D65";
set subject_fgcolor = "#4F4D65";
set outer_table_bgcolor = "#CED2FA";
set sidebar_header_bgcolor = "#FFFFFF";
set sidebar_fgcolor = "#4F4D65";
set header_footer_bgcolor = "#FFFFFF";
set header_footer_fgcolor = "#4F4D65";
set link_color = "#5DABAA";
set link_hover_color = "#779595";
set comments_link_color = "#5DABAA";
set comments_link_hover = "#779595";
set sidebar_link_color = "#5DABAA";
set sidebar_link_hover = "#779595";
set header_footer_link_color = "#5DABAA";
set header_footer_link_hover = "#779595";
#NEWLAYER: flexiblesquares/chocolatemilkshake
layerinfo "redist_uniq" = "flexiblesquares/chocolatemilkshake";
layerinfo "type" = "theme";
layerinfo "name" = "Chocolate Milkshake";
layerinfo author_name = "Yati Mansor";
set page_bgcolor = "#746E4A";
set page_fgcolor = "#000000";
set content_bgcolor = "#BEA16D";
set entry_bgcolor = "#ECD6B2";
set entry_fgcolor = "#000000";
set border_color = "#FFFFFF";
set entrytitle_bgcolor = "#867A52";
set date_fgcolor = "#000000";
set subject_fgcolor = "#000000";
set outer_table_bgcolor = "#A18D5F";
set sidebar_header_bgcolor = "#867A52";
set sidebar_fgcolor = "#000000";
set header_footer_bgcolor = "#ECD6B2";
set header_footer_fgcolor = "#000000";
set link_color = "#867A52";
set link_hover_color = "#790000";
set comments_link_color = "#ECD6B2";
set comments_link_hover = "#790000";
set sidebar_link_color = "#790000";
set sidebar_link_hover = "#ECD6B2";
set header_footer_link_color = "#867A52";
set header_footer_link_hover = "#790000";
#NEWLAYER: flexiblesquares/eclipse
layerinfo "redist_uniq" = "flexiblesquares/eclipse";
layerinfo "type" = "theme";
layerinfo "name" = "Eclipse";
layerinfo author_name = "Yati Mansor";
set page_bgcolor = "#000000";
set page_fgcolor = "#000000";
set content_bgcolor = "#EEA802";
set entry_bgcolor = "#FBE274";
set entry_fgcolor = "#000000";
set border_color = "#000000";
set entrytitle_bgcolor = "#CA5D00";
set date_fgcolor = "#000000";
set subject_fgcolor = "#000000";
set outer_table_bgcolor = "#921800";
set sidebar_header_bgcolor = "#CA5D00";
set sidebar_fgcolor = "#000000";
set header_footer_bgcolor = "#EEA802";
set header_footer_fgcolor = "#000000";
set link_color = "#790000";
set link_hover_color = "#000000";
set comments_link_color = "#ECD6B2";
set comments_link_hover = "#790000";
set sidebar_link_color = "#790000";
set sidebar_link_hover = "#ffffff";
set header_footer_link_color = "#790000";
set header_footer_link_hover = "#ffffff";

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,269 @@
#NEWLAYER: nebula/ohblue
layerinfo "type" = "theme";
layerinfo "name" = "Oh blue";
layerinfo "redist_uniq" = "nebula/ohblue";
set col_entry_bg = "#44366d";
set col_stronger_fg = "#1b0c66";
set col_cmtbarscrn_bg = "#ffffff";
set col_cmtbarone_bg = "#9f9cfd";
set col_neutral_fg = "#2f2e55";
set col_cmtbartwo_bg = "#adb3e5";
set col_sidebar_link = "#2f2e55";
set col_weaker_bg = "#d9dcff";
set col_strong_fg = "#2f2e55";
set col_neutral_bg = "#ab5c90";
set col_cmtbarscrn_fg = "#1b0c66";
set col_stronger_bg = "#b8bef8";
set col_cmtbartwo_fg = "#000000";
set col_weak_bg = "#404380";
set col_cmtbarone_fg = "#000000";
set col_weaker_fg = "#04025a";
set col_entry_link = "#000000";
set col_entry_vlink = "#000000";
set col_strong_bg = "#7e7cb1";
set col_weak_fg = "#9ba2e8";
set col_sidebar_vlink = "#1f1d46";
#NEWLAYER: nebula/ohgreen
layerinfo "type" = "theme";
layerinfo "name" = "Oh green";
layerinfo "redist_uniq" = "nebula/ohgreen";
set col_entry_bg = "#4ca65b";
set col_stronger_fg = "#12661a";
set col_cmtbarscrn_bg = "#ffffff";
set col_cmtbarone_bg = "#bffdbe";
set col_neutral_fg = "#12661a";
set col_cmtbartwo_bg = "#72e580";
set col_sidebar_link = "#12661a";
set col_weaker_bg = "#0d6315";
set col_strong_fg = "#12661a";
set col_neutral_bg = "#000000";
set col_cmtbarscrn_fg = "#000000";
set col_stronger_bg = "#9df89f";
set col_cmtbartwo_fg = "#000000";
set col_weak_bg = "#08390b";
set col_cmtbarone_fg = "#000000";
set col_weaker_fg = "#0e2a05";
set col_entry_link = "#000000";
set col_entry_vlink = "#000000";
set col_strong_bg = "#4f9f58";
set col_weak_fg = "#08390b";
set col_sidebar_vlink = "#12661a";
#NEWLAYER: nebula/ohpurple
layerinfo "type" = "theme";
layerinfo "name" = "Oh purple";
layerinfo "redist_uniq" = "nebula/ohpurple";
set col_cmtbartwo_bg = "#D89EE5";
set col_cmtbarscrn_fg = "#000000";
set col_entry_bg = "#eebfed";
set col_weaker_bg = "#eebfed";
set col_stronger_bg = "#efd5f8";
set col_cmtbartwo_fg = "#000000";
set col_sidebar_link = "#592b7d";
set col_strong_bg = "#9c6e9f";
set col_cmtbarone_bg = "#EECCFD";
set col_stronger_fg = "#c459d1";
set col_weaker_fg = "#0e2a05";
set col_entry_link = "#000000";
set col_entry_vlink = "#000000";
set col_sidebar_vlink = "#2d1e41";
set col_strong_fg = "#614a62";
set col_weak_bg = "#614a62";
set col_neutral_bg = "#000000";
set col_cmtbarone_fg = "#000000";
set col_cmtbarscrn_bg = "#ffffff";
set col_weak_fg = "#a1319a";
set col_neutral_fg = "#614a62";
#NEWLAYER: nebula/ohblack
layerinfo "type" = "theme";
layerinfo "name" = "Oh black";
layerinfo "redist_uniq" = "nebula/ohblack";
set col_cmtbartwo_bg = "#ffffff";
set col_cmtbarscrn_fg = "#000000";
set col_entry_bg = "#ffffff";
set col_weaker_bg = "#ffffff";
set col_stronger_bg = "#ffffff";
set col_cmtbartwo_fg = "#000000";
set col_sidebar_link = "#606060";
set col_strong_bg = "#ffffff";
set col_cmtbarone_bg = "#ffffff";
set col_stronger_fg = "#000000";
set col_weaker_fg = "#000000";
set col_entry_link = "#606060";
set col_entry_vlink = "#606060";
set col_sidebar_vlink = "#606060";
set col_strong_fg = "#000000";
set col_weak_bg = "#ffffff";
set col_neutral_bg = "#ffffff";
set col_cmtbarone_fg = "#000000";
set col_cmtbarscrn_bg = "#ffffff";
set col_weak_fg = "#000000";
set col_neutral_fg = "#000000";
#NEWLAYER: nebula/ohcontrast
layerinfo "type" = "theme";
layerinfo "name" = "Oh contrast";
layerinfo "redist_uniq" = "nebula/ohcontrast";
set col_cmtbartwo_bg = "#000000";
set col_cmtbarscrn_fg = "#ffffff";
set col_entry_bg = "#000000";
set col_weaker_bg = "#000000";
set col_stronger_bg = "#000000";
set col_cmtbartwo_fg = "#ffffff";
set col_sidebar_link = "#c0c0c0";
set col_strong_bg = "#000000";
set col_cmtbarone_bg = "#000000";
set col_stronger_fg = "#ffffff";
set col_weaker_fg = "#000000";
set col_entry_link = "#c0c0c0";
set col_entry_vlink = "#c0c0c0";
set col_sidebar_vlink = "#c0c0c0";
set col_strong_fg = "#ffffff";
set col_weak_bg = "#000000";
set col_neutral_bg = "#000000";
set col_cmtbarone_fg = "#ffffff";
set col_cmtbarscrn_bg = "#000000";
set col_weak_fg = "#ffffff";
set col_neutral_fg = "#ffffff";
#NEWLAYER: nebula/ohbedtime
layerinfo "type" = "theme";
layerinfo "name" = "Oh bed time";
layerinfo "redist_uniq" = "nebula/ohbedtime";
set col_cmtbartwo_bg = "#5c60b6";
set col_cmtbarscrn_fg = "#ffffff";
set col_entry_bg = "#ffffff";
set col_weaker_bg = "#5e5b7d";
set col_stronger_bg = "#8381da";
set col_cmtbartwo_fg = "#ffffff";
set col_sidebar_link = "#000000";
set col_strong_bg = "#8381da";
set col_cmtbarone_bg = "#605f9a";
set col_stronger_fg = "#ffffff";
set col_weaker_fg = "#000000";
set col_entry_link = "#000000";
set col_entry_vlink = "#000000";
set col_sidebar_vlink = "#000000";
set col_strong_fg = "#ffffff";
set col_weak_bg = "#ffffff";
set col_neutral_bg = "#000000";
set col_cmtbarone_fg = "#ffffff";
set col_cmtbarscrn_bg = "#879afa";
set col_weak_fg = "#3c3c60";
set col_neutral_fg = "#080255";
#NEWLAYER: nebula/ohgreenywhite
layerinfo "type" = "theme";
layerinfo "name" = "Oh greeny white";
layerinfo "redist_uniq" = "nebula/ohgreenywhite";
set col_entry_bg = "#ffffff";
set col_stronger_fg = "#ffffff";
set col_cmtbarscrn_bg = "#93f390";
set col_cmtbarone_bg = "#7fe278";
set col_neutral_fg = "#550301";
set col_cmtbartwo_bg = "#4a8f41";
set col_sidebar_link = "#000000";
set col_weaker_bg = "#546847";
set col_strong_fg = "#ffffff";
set col_neutral_bg = "#000000";
set col_cmtbarscrn_fg = "#ffffff";
set col_stronger_bg = "#69ac59";
set col_cmtbartwo_fg = "#ffffff";
set col_weak_bg = "#ffffff";
set col_cmtbarone_fg = "#ffffff";
set col_weaker_fg = "#000000";
set col_entry_link = "#000000";
set col_entry_vlink = "#000000";
set col_strong_bg = "#69ac59";
set col_weak_fg = "#366030";
set col_sidebar_vlink = "#000000";
#NEWLAYER: nebula/ohchocchip
layerinfo "type" = "theme";
layerinfo "name" = "Oh choc chip";
layerinfo "redist_uniq" = "nebula/ohchocchip";
set col_cmtbartwo_bg = "#4A8F41";
set col_cmtbarscrn_fg = "#ffffff";
set col_entry_bg = "#977e3b";
set col_weaker_bg = "#546847";
set col_stronger_bg = "#69ac59";
set col_cmtbartwo_fg = "#ffffff";
set col_sidebar_link = "#000000";
set col_strong_bg = "#69ac59";
set col_cmtbarone_bg = "#7FE278";
set col_stronger_fg = "#5b4b26";
set col_weaker_fg = "#000000";
set col_entry_link = "#000000";
set col_entry_vlink = "#000000";
set col_sidebar_vlink = "#000000";
set col_strong_fg = "#5b4b26";
set col_weak_bg = "#5b4b26";
set col_neutral_bg = "#000000";
set col_cmtbarone_fg = "#ffffff";
set col_cmtbarscrn_bg = "#93F390";
set col_weak_fg = "#ffffff";
set col_neutral_fg = "#550301";
#NEWLAYER: nebula/ohcoffee
layerinfo "type" = "theme";
layerinfo "name" = "Oh coffee";
layerinfo "redist_uniq" = "nebula/ohcoffee";
set col_cmtbartwo_bg = "#AFB13E";
set col_cmtbarscrn_fg = "#ffffff";
set col_entry_bg = "#977e3b";
set col_weaker_bg = "#effe8f";
set col_stronger_bg = "#fbe46a";
set col_cmtbartwo_fg = "#ffffff";
set col_sidebar_link = "#000000";
set col_strong_bg = "#fbe46a";
set col_cmtbarone_bg = "#E2C956";
set col_stronger_fg = "#5b4b26";
set col_weaker_fg = "#000000";
set col_entry_link = "#000000";
set col_entry_vlink = "#000000";
set col_sidebar_vlink = "#000000";
set col_strong_fg = "#5b4b26";
set col_weak_bg = "#5b4b26";
set col_neutral_bg = "#000000";
set col_cmtbarone_fg = "#ffffff";
set col_cmtbarscrn_bg = "#FCDA3E";
set col_weak_fg = "#ffffff";
set col_neutral_fg = "#550301";
#NEWLAYER: nebula/ohred
layerinfo "type" = "theme";
layerinfo "name" = "Oh red";
layerinfo "redist_uniq" = "nebula/ohred";
set col_cmtbartwo_bg = "#983035";
set col_cmtbarscrn_fg = "#ffffff";
set col_entry_bg = "#d90d12";
set col_weaker_bg = "#fe0410";
set col_stronger_bg = "#dd6568";
set col_cmtbartwo_fg = "#ffffff";
set col_sidebar_link = "#000000";
set col_strong_bg = "#dd6568";
set col_cmtbarone_bg = "#d25c64";
set col_stronger_fg = "#ffffff";
set col_weaker_fg = "#000000";
set col_entry_link = "#000000";
set col_entry_vlink = "#000000";
set col_sidebar_vlink = "#000000";
set col_strong_fg = "#ffffff";
set col_weak_bg = "#bc0811";
set col_neutral_bg = "#000000";
set col_cmtbarone_fg = "#ffffff";
set col_cmtbarscrn_bg = "#D38086";
set col_weak_fg = "#ffffff";
set col_neutral_fg = "#550301";

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,105 @@
#NEWLAYER: opal/irishluck
layerinfo "type" = "theme";
layerinfo "name" = "The Luck of the Irish";
layerinfo redist_uniq = "opal/irishluck";
layerinfo "source_viewable" = 1;
set color_med = "#8BA485";
set color_fg_font = "#01331E";
set color_fg = "#A1CB78";
set color_med_font = "#E5FCDE";
set color_bg = "#0B4107";
#NEWLAYER: opal/undersea
layerinfo "type" = "theme";
layerinfo redist_uniq = "opal/undersea";
layerinfo "source_viewable" = 1;
layerinfo "name" = "Under the Sea";
set color_med = "#98A3A4";
set color_fg = "#93CBCA";
set color_med_font = "#526160";
set color_bg = "#124D51";
#NEWLAYER: opal/forest
layerinfo "type" = "theme";
layerinfo redist_uniq = "opal/forest";
layerinfo "source_viewable" = 1;
layerinfo "name" = "Natural Forest";
set color_link = "#4C6502";
set color_med = "#90a47a";
set color_bg_font = "#ffeabf";
set color_fg = "#cacba9";
set color_med_font = "#eaf2cc";
set color_bg = "#514541";
set color_visited = "#846D06";
#NEWLAYER: opal/greybeard
layerinfo "type" = "theme";
layerinfo redist_uniq = "opal/greybeard";
layerinfo "source_viewable" = 1;
layerinfo "name" = "Greybeard";
set color_link = "#05445C";
set color_med = "#6a6a6a";
set color_fg_font = "#dddddd";
set color_bg = "#424242";
set color_visited = "#390856";
set color_fg = "#7c7c7c";
set color_med_font = "#E2E2E2";
#NEWLAYER: opal/desert
layerinfo "type" = "theme";
layerinfo redist_uniq = "opal/desert";
layerinfo "source_viewable" = 1;
layerinfo "name" = "Spring Desert";
set color_link = "#4c6502";
set color_med = "#bc7f48";
set color_fg_font = "#794234";
set color_fg = "#cea36f";
set color_med_font = "#F2E6C8";
set color_bg = "#795021";
#NEWLAYER: opal/carnvial
layerinfo "type" = "theme";
layerinfo redist_uniq = "opal/carnvial";
layerinfo "source_viewable" = 1;
layerinfo "name" = "Carnvial";
set color_med = "#9681b7";
set color_fg = "#E9973F";
set color_bg = "#2d4b9b";
#NEWLAYER: opal/snowcone
layerinfo "type" = "theme";
layerinfo redist_uniq = "opal/snowcone";
layerinfo "source_viewable" = 1;
layerinfo "name" = "Snow Cone";
set color_med = "#7c9bc1";
set color_fg_font = "#4F6C9C";
set color_fg = "#bfe2f8";
set color_bg = "#8d54a0";
#NEWLAYER: opal/adobeclay
layerinfo "type" = "theme";
layerinfo redist_uniq = "opal/adobeclay";
layerinfo "source_viewable" = 1;
layerinfo "name" = "Adobe Clay";
set color_link = "#FF9422";
set color_med = "#a4562b";
set color_fg_font = "#33100b";
set color_fg = "#c1643b";
set color_med_font = "#fce7d5";
set color_bg = "#7b4832";
set color_visited = "#FFC437";
#NEWLAYER: opal/gentle
layerinfo "type" = "theme";
layerinfo redist_uniq = "opal/gentle";
layerinfo "source_viewable" = 1;
layerinfo "name" = "Gentle";
set color_bg_font = "#616568";
set color_fg = "#ebdbd0";
set color_visited = "#A97F63";
set color_link = "#bd9a82";
set color_med = "#b3c5c5";
set color_bg = "#a2b2b1";
set color_med_font = "#878894";
set color_fg_font = "#757575";

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,612 @@
#NEWLAYER: smoothsailing/starry
layerinfo "redist_uniq" = "smoothsailing/starry";
layerinfo "type" = "theme";
layerinfo "name" = "Starry Night";
layerinfo author_name = "Michael Raffoul";
layerinfo author_email = "masterslacker@livejournal.com";
set color_header_title_background = "#000000";
set color_header_title_text = "#FFFFB9";
set color_header_subtitle_text = "#dddddd";
set color_header_menubar_background = "#000044";
set color_header_menubar_text = "#FFFFB9";
set color_header_menubar_background_hover = "#000000";
set color_header_menubar_text_hover = "#dddddd";
set color_header_borders = "#89a2be";
set color_body_links = "#ffffb9";
set color_body_links_visited = "#dddddd";
set color_body_titlebar_background = "#aaaaaa";
set color_body_titlebar_text = "#000044";
set color_body_footer_background = "#000000";
set color_body_footer_text = "#ffffb9";
set color_body_background = "#000044";
set color_body_text = "#FFFFB9";
set color_body_entrytitle_background = "#000000";
set color_body_entrytitle_background_alternate = "#aaaaaa";
set color_body_entrytitle_border = "#89A2BE";
set color_body_entrytitle_text = "#89a2be";
set color_body_entrytitle_links = "#89a2be";
set color_body_entry_background = "#000044";
set color_body_entry_userinfo_background = "#000044";
set color_body_entry_text = "#FFFFB9";
set color_month_borders = "#89A2BE";
set color_month_title_background = "#aaaaaa";
set color_month_title_text = "#000000";
set color_month_dates = "#aaaaaa";
set color_month_postcount = "#FFFFB9";
#NEWLAYER: smoothsailing/pink
layerinfo "redist_uniq" = "smoothsailing/pink";
layerinfo "type" = "theme";
layerinfo "name" = "Pretty in Pink";
layerinfo author_name = "Michael Raffoul";
layerinfo author_email = "masterslacker@livejournal.com";
set color_header_title_background = "#CC4E5C";
set color_header_title_text = "#FFEEFF";
set color_header_subtitle_text = "#FFB6C1";
set color_header_menubar_background = "#e6828f";
set color_header_menubar_text = "#FFEEFF";
set color_header_menubar_background_hover = "#CC4E5C";
set color_header_menubar_text_hover = "#FFEEFF";
set color_header_borders = "#FFEEFF";
set color_body_links = "#CC4E5C";
set color_body_links_visited = "#CC4E5C";
set color_body_titlebar_background = "#FFB6C1";
set color_body_titlebar_text = "#CC4E5C";
set color_body_footer_background = "#FFB6C1";
set color_body_footer_text = "#CC4E5C";
set color_body_background = "#FFEEFF";
set color_body_text = "#CC4E5C";
set color_body_entrytitle_background = "#FFB6C1";
set color_body_entrytitle_background_alternate = "#e6828f";
set color_body_entrytitle_border = "#CC4E5C";
set color_body_entrytitle_text = "#CC4E5C";
set color_body_entrytitle_links = "#CC4E5C";
set color_body_entry_text = "#CC4E5C";
set color_body_entry_background = "#FFEEFF";
set color_body_entry_userinfo_background = "#FFEEFF";
set color_month_borders = "#CC4E5C";
set color_month_title_background = "#FFB6C1";
set color_month_title_text = "#CC4E5C";
set color_month_dates = "#CC4E5C";
set color_month_postcount = "#e6828f";
#NEWLAYER: smoothsailing/easter
layerinfo "redist_uniq" = "smoothsailing/easter";
layerinfo "type" = "theme";
layerinfo "name" = "Easter Basket";
layerinfo author_name = "Michael Raffoul";
layerinfo author_email = "masterslacker@livejournal.com";
set color_header_title_background = "#00B789";
set color_header_title_text = "#FFFF82";
set color_header_subtitle_text = "#005100";
set color_header_menubar_background = "#FFFF82";
set color_header_menubar_text = "#005100";
set color_header_menubar_background_hover = "#C7A0CB";
set color_header_menubar_text_hover = "#005100";
set color_header_borders = "#009300";
set color_body_links = "#005100";
set color_body_links_visited = "#005100";
set color_body_titlebar_background = "#C7A0CB";
set color_body_titlebar_text = "#005100";
set color_body_footer_background = "#C7A0CB";
set color_body_footer_text = "#005100";
set color_body_background = "#DDDFF0";
set color_body_text = "#005100";
set color_body_entrytitle_background = "#FFFF82";
set color_body_entrytitle_background_alternate = "#C7A0CB";
set color_body_entrytitle_border = "#009300";
set color_body_entrytitle_text = "#005100";
set color_body_entrytitle_links = "#005100";
set color_body_entry_text = "#005100";
set color_body_entry_background = "#DDDFF0";
set color_body_entry_userinfo_background = "#DDDFF0";
set color_month_borders = "#00B789";
set color_month_title_background = "#FFFF82";
set color_month_title_text = "#005100";
set color_month_dates = "#C7A0CB";
set color_month_postcount = "#005100";
#NEWLAYER: smoothsailing/mocha
layerinfo "redist_uniq" = "smoothsailing/mocha";
layerinfo "type" = "theme";
layerinfo "name" = "Mochachino";
layerinfo author_name = "Michael Raffoul";
layerinfo author_email = "masterslacker@livejournal.com";
set color_header_title_background = "#666666";
set color_header_title_text = "#e6e6e6";
set color_header_subtitle_text = "#B1A68B";
set color_header_menubar_background = "#635a48";
set color_header_menubar_text = "#b1a68b";
set color_header_menubar_background_hover = "#b1a68b";
set color_header_menubar_text_hover = "#666666";
set color_header_borders = "#e6e6e6";
set color_body_links = "#464640";
set color_body_links_visited = "#000000";
set color_body_titlebar_background = "#B1A68B";
set color_body_titlebar_text = "#e6e6e6";
set color_body_footer_background = "#b1a68b";
set color_body_footer_text = "#e6e6e6";
set color_body_background = "#e6e6e6";
set color_body_entrytitle_background = "#b1a68b";
set color_body_entrytitle_background_alternate = "#796D51";
set color_body_entrytitle_border = "#666666";
set color_body_entrytitle_text = "#e6e6e6";
set color_body_entrytitle_links = "#e6e6e6";
set color_body_entry_text = "#464640";
set color_body_entry_background = "#e6e6e6";
set color_body_entry_userinfo_background = "#e6e6e6";
set color_month_borders = "#666666";
set color_month_title_background = "#e6e6e6";
set color_month_title_text = "#464640";
set color_month_dates = "#464640";
set color_month_postcount = "#796D51";
#NEWLAYER: smoothsailing/yellow
layerinfo "redist_uniq" = "smoothsailing/yellow";
layerinfo "type" = "theme";
layerinfo "name" = "Insane Yellow";
layerinfo author_name = "Michael Raffoul";
layerinfo author_email = "masterslacker@livejournal.com";
set color_header_title_background = "#202020";
set color_header_title_text = "#FFFF04";
set color_header_subtitle_text = "#dddddd";
set color_header_menubar_background = "#000000";
set color_header_menubar_text = "#FFFFB9";
set color_header_menubar_background_hover = "#202020";
set color_header_menubar_text_hover = "#FFFFB9";
set color_header_borders = "#FFFF04";
set color_body_links = "#aaaaaa";
set color_body_links_visited = "#dddddd";
set color_body_titlebar_background = "#aaaaaa";
set color_body_titlebar_text = "#000000";
set color_body_footer_background = "#202020";
set color_body_footer_text = "#ffffb9";
set color_body_background = "#000000";
set color_body_text = "#FFFFB9";
set color_body_entrytitle_background = "#202020";
set color_body_entrytitle_background_alternate = "#aaaaaa";
set color_body_entrytitle_border = "#FFFF04";
set color_body_entrytitle_text = "#FFFF04";
set color_body_entrytitle_links = "#FFFF04";
set color_body_entry_background = "#000000";
set color_body_entry_userinfo_background = "#000000";
set color_body_entry_text = "#aaaaaa";
set color_month_borders = "#FFFFB9";
set color_month_title_background = "#aaaaaa";
set color_month_title_text = "#000000";
set color_month_dates = "#aaaaaa";
set color_month_postcount = "#FFFFB9";
#NEWLAYER: smoothsailing/forest
layerinfo "redist_uniq" = "smoothsailing/forest";
layerinfo "type" = "theme";
layerinfo "name" = "In the Forest";
layerinfo author_name = "Michael Raffoul";
layerinfo author_email = "masterslacker@livejournal.com";
set color_header_title_background = "#635a48";
set color_header_title_text = "#e7dfcf";
set color_header_subtitle_text = "#607c6d";
set color_header_menubar_background = "#899ba3";
set color_header_menubar_text = "#464640";
set color_header_menubar_background_hover = "#e7dfcf";
set color_header_menubar_text_hover = "#464640";
set color_header_borders = "#464640";
set color_body_links = "#e7dfcf";
set color_body_links_visited = "#e7dfcf";
set color_body_titlebar_background = "#e7dfcf";
set color_body_titlebar_text = "#464640";
set color_body_footer_background = "#e7dfcf";
set color_body_footer_text = "#464640";
set color_body_background = "#607c6d";
set color_body_text = "#e7dfcf";
set color_body_entrytitle_background = "#635a48";
set color_body_entrytitle_background_alternate = "#464640";
set color_body_entrytitle_border = "#e7dfcf";
set color_body_entrytitle_text = "#e7dfcf";
set color_body_entrytitle_links = "#e7dfcf";
set color_body_entry_userinfo_background = "#626b5b";
set color_body_entry_background = "#626b5b";
set color_body_entry_text = "#e7dfcf";
set color_month_borders = "#464640";
set color_month_title_background = "#e7dfcf";
set color_month_title_text = "#464640";
set color_month_dates = "#899ba3";
set color_month_postcount = "#e7dfcf";
#NEWLAYER: smoothsailing/red
layerinfo "redist_uniq" = "smoothsailing/red";
layerinfo "type" = "theme";
layerinfo "name" = "Seeing Red";
layerinfo author_name = "Michael Raffoul";
layerinfo author_email = "masterslacker@livejournal.com";
set color_header_title_background = "#bb0000";
set color_header_title_text = "#ffffff";
set color_header_subtitle_text = "#ffffff";
set color_header_menubar_background = "#880000";
set color_header_menubar_text = "#ffffff";
set color_header_menubar_background_hover = "#ffffff";
set color_header_menubar_text_hover = "#bb0000";
set color_header_borders = "#ffffff";
set color_body_links = "#880000";
set color_body_links_visited = "#000000";
set color_body_titlebar_background = "#bb0000";
set color_body_titlebar_text = "#ffffff";
set color_body_footer_background = "#bb0000";
set color_body_footer_text = "#ffffff";
set color_body_background = "#f6f6f6";
set color_body_text = "#880000";
set color_body_entrytitle_background = "#bb0000";
set color_body_entrytitle_background_alternate = "#880000";
set color_body_entrytitle_border = "#000000";
set color_body_entrytitle_text = "#ffffff";
set color_body_entrytitle_links = "#ffffff";
set color_body_entry_background = "#f6f6f6";
set color_body_entry_text = "#880000";
set color_month_borders = "#880000";
set color_month_title_background = "#bb0000";
set color_month_title_text = "#ffffff";
set color_month_dates = "#880000";
set color_month_postcount = "#bb0000";
#NEWLAYER: smoothsailing/army
layerinfo "redist_uniq" = "smoothsailing/army";
layerinfo "type" = "theme";
layerinfo "name" = "Army Attire";
layerinfo author_name = "Michael Raffoul";
layerinfo author_email = "masterslacker@livejournal.com";
set color_header_title_background = "#444444";
set color_header_title_text = "#cccc99";
set color_header_subtitle_text = "#e6e6e6";
set color_header_menubar_background = "#665d34";
set color_header_menubar_text = "#cccc99";
set color_header_menubar_background_hover = "#cccc99";
set color_header_menubar_text_hover = "#444444";
set color_header_borders = "#e6e6e6";
set color_body_links = "#444444";
set color_body_links_visited = "#000000";
set color_body_titlebar_background = "#cccc99";
set color_body_titlebar_text = "#665d34";
set color_body_footer_background = "#cccc99";
set color_body_footer_text = "#665d34";
set color_body_background = "#e6e6e6";
set color_body_entrytitle_background = "#cccc99";
set color_body_entrytitle_background_alternate = "#665d34";
set color_body_entrytitle_border = "#444444";
set color_body_entrytitle_text = "#665d34";
set color_body_entrytitle_links = "#665d34";
set color_body_entry_text = "#444444";
set color_body_entry_background = "#e6e6e6";
set color_body_entry_userinfo_background = "#e6e6e6";
set color_month_borders = "#444444";
set color_month_title_background = "#e6e6e6";
set color_month_title_text = "#444444";
set color_month_dates = "#444444";
set color_month_postcount = "#665d34";
#NEWLAYER: smoothsailing/midnight
layerinfo "redist_uniq" = "smoothsailing/midnight";
layerinfo "type" = "theme";
layerinfo "name" = "Midnight";
layerinfo author_name = "Michael Raffoul";
layerinfo author_email = "masterslacker@livejournal.com";
set color_header_title_background = "#000000";
set color_header_title_text = "#BEAA61";
set color_header_subtitle_text = "#76456B";
set color_header_menubar_background = "#76456B";
set color_header_menubar_text = "#dddddd";
set color_header_menubar_background_hover = "#000000";
set color_header_menubar_text_hover = "#dddddd";
set color_header_borders = "#dddddd";
set color_body_links = "#aaaaaa";
set color_body_links_visited = "#dddddd";
set color_body_titlebar_background = "#BEAA61";
set color_body_titlebar_text = "#000000";
set color_body_footer_background = "#76456B";
set color_body_footer_text = "#dddddd";
set color_body_background = "#000000";
set color_body_text = "#aaaaaa";
set color_body_entrytitle_background = "#76456B";
set color_body_entrytitle_background_alternate = "#888888";
set color_body_entrytitle_border = "#cccccc";
set color_body_entrytitle_text = "#dddddd";
set color_body_entrytitle_links = "#dddddd";
set color_body_entry_userinfo_background = "#000000";
set color_body_entry_background = "#000000";
set color_body_entry_text = "#aaaaaa";
set color_month_borders = "#dddddd";
set color_month_title_background = "#aaaaaa";
set color_month_title_text = "#000000";
set color_month_dates = "#aaaaaa";
set color_month_postcount = "#BEAA61";
#NEWLAYER: smoothsailing/violet
layerinfo "redist_uniq" = "smoothsailing/violet";
layerinfo "type" = "theme";
layerinfo "name" = "Very Violet";
layerinfo author_name = "Michael Raffoul";
layerinfo author_email = "masterslacker@livejournal.com";
set color_header_title_background = "#7c52ab";
set color_header_subtitle_text = "#dbcfe9";
set color_header_menubar_background = "#bfaad7";
set color_header_menubar_background_hover = "#7c52ab";
set color_body_links_visited = "#563976";
set color_body_titlebar_background = "#dbcfe9";
set color_body_footer_background = "#bfaad7";
set color_body_entrytitle_background = "#dbcfe9";
#NEWLAYER: smoothsailing/purple
layerinfo "redist_uniq" = "smoothsailing/purple";
layerinfo "type" = "theme";
layerinfo "name" = "Bruised Purple";
layerinfo author_name = "Michael Raffoul";
layerinfo author_email = "masterslacker@livejournal.com";
set color_body_entrytitle_border = "#d4ddee";
set color_body_footer_text = "#454b74";
set color_month_title_text = "#8792bd";
set color_header_borders = "#8792bd";
set color_body_links_visited = "#dddddd";
set color_header_menubar_text_hover = "#ffffff";
set color_body_titlebar_text = "#454b74";
set color_body_entrytitle_background_alternate = "#d4ddee";
set color_body_entrytitle_links = "#6b7da6";
set color_body_entry_background = "#454b74";
set color_header_title_background = "#454b74";
set color_body_entry_userinfo_background = "#454b74";
set color_month_dates = "#8792bd";
set color_body_links = "#ececec";
set color_body_background = "#6b7da6";
set color_month_postcount = "#8792bd";
set color_body_entry_text = "#8792bd";
set color_body_text = "#ffffff";
set color_body_entrytitle_background = "#d4ddee";
set color_header_menubar_text = "#ffffff";
set color_body_entrytitle_text = "#454b74";
#NEWLAYER: smoothsailing/parrot
layerinfo "redist_uniq" = "smoothsailing/parrot";
layerinfo "type" = "theme";
layerinfo "name" = "Parrot Feathers";
layerinfo author_name = "Michael Raffoul";
layerinfo author_email = "masterslacker@livejournal.com";
set color_header_title_background = "#009900";
set color_header_title_text = "#f8f8f8";
set color_header_subtitle_text = "#66ff66";
set color_header_menubar_background = "#33cc33";
set color_header_menubar_text = "#ffffff";
set color_header_menubar_background_hover = "#66ff66";
set color_header_menubar_text_hover = "#ffffff";
set color_header_borders = "#ffffff";
set color_body_links = "#006600";
set color_body_links_visited = "#000000";
set color_body_titlebar_background = "#66cc66";
set color_body_titlebar_text = "#ffffff";
set color_body_footer_background = "#66cc66";
set color_body_footer_text = "#ffffff";
set color_body_background = "#f8f8f8";
set color_body_text = "#000000";
set color_body_entrytitle_background = "#66cc66";
set color_body_entrytitle_background_alternate = "#66ff66";
set color_body_entrytitle_border = "#006600";
set color_body_entrytitle_text = "#000000";
set color_body_entrytitle_links = "#000000";
set color_body_entry_background = "#f8f8f8";
set color_body_entry_userinfo_background = "#f8f8f8";
set color_body_entry_text = "#000000";
set color_month_borders = "#006600";
set color_month_title_background = "#f8f8f8";
set color_month_title_text = "#000000";
set color_month_dates = "#000000";
set color_month_postcount = "#006600";
#NEWLAYER: smoothsailing/toxic
layerinfo "redist_uniq" = "smoothsailing/toxic";
layerinfo "type" = "theme";
layerinfo "name" = "Toxic Teal";
layerinfo author_name = "Michael Raffoul";
layerinfo author_email = "masterslacker@livejournal.com";
set color_header_title_background = "#7cb3b0";
set color_header_title_text = "#496a68";
set color_header_subtitle_text = "#c9eae8";
set color_header_menubar_background = "#aededb";
set color_header_menubar_text = "#496a68";
set color_header_menubar_background_hover = "#c9eae8";
set color_header_menubar_text_hover = "#496a68";
set color_header_borders = "#496a68";
set color_body_links = "#496a68";
set color_body_links_visited = "#000000";
set color_body_titlebar_background = "#c9eae8";
set color_body_titlebar_text = "#496a68";
set color_body_footer_background = "#c9eae8";
set color_body_footer_text = "#496a68";
set color_body_background = "#496a68";
set color_body_text = "#aededb";
set color_body_entrytitle_background = "#7cb3b0";
set color_body_entrytitle_background_alternate = "#6e9e9b";
set color_body_entrytitle_border = "#c9eae8";
set color_body_entrytitle_text = "#000000";
set color_body_entrytitle_links = "#000000";
set color_body_entry_background = "#aededb";
set color_body_entry_userinfo_background = "#aededb";
set color_body_entry_text = "#000000";
set color_month_borders = "#496a68";
set color_month_title_background = "#c9eae8";
set color_month_title_text = "#000000";
set color_month_dates = "#000000";
set color_month_postcount = "#496a68";
#NEWLAYER: smoothsailing/banana
layerinfo "redist_uniq" = "smoothsailing/banana";
layerinfo "type" = "theme";
layerinfo "name" = "Banana Tree";
layerinfo author_name = "Michael Raffoul";
layerinfo author_email = "masterslacker@livejournal.com";
set color_header_title_background = "#3D5D2E";
set color_header_title_text = "#F6F6BB";
set color_header_subtitle_text = "#E1D751";
set color_header_menubar_background = "#E1D751";
set color_header_menubar_text = "#3D5D2E";
set color_header_menubar_background_hover = "#9A722E";
set color_header_menubar_text_hover = "#F6F6BB";
set color_header_borders = "#F6F6BB";
set color_body_links = "#3D5D2E";
set color_body_links_visited = "#000000";
set color_body_titlebar_background = "#9A722E";
set color_body_titlebar_text = "#F6F6BB";
set color_body_footer_background = "#3D5D2E";
set color_body_footer_text = "#F6F6BB";
set color_body_background = "#F6F6BB";
set color_body_text = "#3D5D2E";
set color_body_entrytitle_background = "#3D5D2E";
set color_body_entrytitle_background_alternate = "#9A722E";
set color_body_entrytitle_border = "#9A722E";
set color_body_entrytitle_text = "#E1D751";
set color_body_entrytitle_links = "#E1D751";
set color_body_entry_background = "#F6F6BB";
set color_body_entry_userinfo_background = "#F6F6BB";
set color_body_entry_text = "#000000";
set color_month_borders = "#9A722E";
set color_month_title_background = "#F6F6BB";
set color_month_title_text = "#3D5D2E";
set color_month_dates = "#000000";
set color_month_postcount = "#3D5D2E";
#NEWLAYER: smoothsailing/fire
layerinfo "redist_uniq" = "smoothsailing/fire";
layerinfo "type" = "theme";
layerinfo "name" = "Under Fire";
layerinfo author_name = "Michael Raffoul";
layerinfo author_email = "masterslacker@livejournal.com";
set color_header_title_background = "#95261F";
set color_header_title_text = "#F5EBC2";
set color_header_subtitle_text = "#CA6036";
set color_header_menubar_background = "#CA6036";
set color_header_menubar_text = "#F5EBC2";
set color_header_menubar_background_hover = "#DEB450";
set color_header_menubar_text_hover = "#95261F";
set color_header_borders = "#F5EBC2";
set color_body_links = "#95261F";
set color_body_links_visited = "#000000";
set color_body_titlebar_background = "#DEB450";
set color_body_titlebar_text = "#95261F";
set color_body_footer_background = "#95261F";
set color_body_footer_text = "#F5EBC2";
set color_body_background = "#F5EBC2";
set color_body_text = "#000000";
set color_body_entrytitle_background = "#95261F";
set color_body_entrytitle_background_alternate = "#CA6036";
set color_body_entrytitle_border = "#DEB450";
set color_body_entrytitle_text = "#F5EBC2";
set color_body_entrytitle_links = "#F5EBC2";
set color_body_entry_background = "#F5EBC2";
set color_body_entry_userinfo_background = "#F5EBC2";
set color_body_entry_text = "#000000";
set color_month_borders = "#95261F";
set color_month_title_background = "#F5EBC2";
set color_month_title_text = "#95261F";
set color_month_dates = "#95261F";
set color_month_postcount = "#CA6036";
#NEWLAYER: smoothsailing/chocolate
layerinfo "redist_uniq" = "smoothsailing/chocolate";
layerinfo "type" = "theme";
layerinfo "name" = "Chocolate Caramel Creme";
layerinfo author_name = "Michael Raffoul";
layerinfo author_email = "masterslacker@livejournal.com";
set color_header_title_background = "#6D4506";
set color_header_title_text = "#E1D6C0";
set color_header_subtitle_text = "#CF9B48";
set color_header_menubar_background = "#A2701F";
set color_header_menubar_text = "#E1D6C0";
set color_header_menubar_background_hover = "#CF9B48";
set color_header_menubar_text_hover = "#E1D6C0";
set color_header_borders = "#E1D6C0";
set color_body_links = "#6D4506";
set color_body_links_visited = "#000000";
set color_body_titlebar_background = "#CF9B48";
set color_body_titlebar_text = "#E1D6C0";
set color_body_footer_background = "#6D4506";
set color_body_footer_text = "#E1D6C0";
set color_body_background = "#E1D6C0";
set color_body_text = "#000000";
set color_body_entrytitle_background = "#A2701F";
set color_body_entrytitle_background_alternate = "#CF9B48";
set color_body_entrytitle_border = "#6D4506";
set color_body_entrytitle_text = "#E1D6C0";
set color_body_entrytitle_links = "#E1D6C0";
set color_body_entry_background = "#E1D6C0";
set color_body_entry_userinfo_background = "#E1D6C0";
set color_body_entry_text = "#000000";
set color_month_borders = "#A2701F";
set color_month_title_background = "#E1D6C0";
set color_month_title_text = "#6D4506";
set color_month_dates = "#6D4506";
set color_month_postcount = "#A2701F";

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,707 @@
#NEWLAYER: tranquilityii/plain
layerinfo "redist_uniq" = "tranquilityii/plain";
layerinfo "type" = "theme";
layerinfo "name" = "Tranquility II - Plain Theme";
layerinfo "author_name" = "Matthew Vince";
set c_main_border = "#fff";
set c_menu_border = "#fff";
set c_header_background = "#fff";
set c_header_border = "#fff";
set c_page_title = "#000";
set c_page_background = "#fff";
set c_page_text = "#333";
set c_page_link = "#036";
set c_page_link_visited = "#036";
set c_page_link_hover = "#069";
set c_page_link_active = "#069";
set c_menu_background = "#fff";
set c_menu_link = "#000";
set c_menu_link_visited = "#000";
set c_menu_link_hover = "#f00";
set c_menu_link_active = "#f00";
set c_menu_text_color = "#000";
set c_menu_header_color = "#000";
set c_menu_current = "#000";
set c_entry_background = "#fff";
set c_entry_link = "#000";
set c_entry_link_visited = "#000";
set c_entry_link_hover = "#000";
set c_entry_link_active = "#000";
set c_entry_text_color = "#000";
set c_entry_title_color = "#000";
set c_entry_border = "#999";
set c_meta_background = "#fff";
set c_meta_link = "#000";
set c_meta_link_visited = "#000";
set c_meta_link_hover = "#000";
set c_meta_link_active = "#000";
set c_meta_text_color = "#000";
set c_footer_background = "#fff";
set c_footer_link = "#000";
set c_footer_link_visited = "#000";
set c_footer_link_hover = "#000";
set c_footer_link_active = "#000";
set c_footer_text_color = "#000";
set c_comment_one_link = "#000";
set c_comment_one_link_visited = "#000";
set c_comment_one_link_hover = "#000";
set c_comment_one_link_active = "#000";
set c_comment_one_text_color = "#000";
set c_comment_one_title_color = "#000";
set c_comment_one_background = "#fff";
set c_comment_one_border = "#999";
set c_comment_two_link = "#000";
set c_comment_two_link_visited = "#000";
set c_comment_two_link_hover = "#000";
set c_comment_two_link_active = "#000";
set c_comment_two_text_color = "#000";
set c_comment_two_title_color = "#000";
set c_comment_two_background = "#f2f2f2";
set c_comment_two_border = "#999";
set c_comment_screened_link = "#000";
set c_comment_screened_link_visited = "#000";
set c_comment_screened_link_hover = "#000";
set c_comment_screened_link_active = "#000";
set c_comment_screened_text_color = "#000";
set c_comment_screened_title_color = "#000";
set c_comment_screened_background = "#ccc";
set c_comment_screened_border = "#999";
#NEWLAYER: tranquilityii/earth
layerinfo "redist_uniq" = "tranquilityii/earth";
layerinfo "type" = "theme";
layerinfo "name" = "Tranquility II - Earth Theme";
layerinfo "author_name" = "Matthew Vince";
set c_main_border = "#424B15";
set c_header_background = "#667320";
set c_header_border = "#667320";
set c_page_title = "#fff";
set c_page_background = "#667320";
set c_page_text = "#333";
set c_page_link = "#000";
set c_page_link_visited = "#666";
set c_page_link_hover = "#999";
set c_page_link_active = "#999";
set c_menu_border = "#424B15";
set c_menu_background = "#88992B";
set c_menu_link = "#fff";
set c_menu_link_visited = "#424B15";
set c_menu_link_hover = "#424B15";
set c_menu_link_active = "#f00";
set c_menu_text_color = "#fff";
set c_menu_header_color = "#fff";
set c_menu_current = "#fff";
set f_menu_header_size = "140%";
set c_entry_background = "#fff";
set c_entry_link = "#99602B";
set c_entry_link_visited = "#BF7836";
set c_entry_link_hover = "#734820";
set c_entry_link_active = "#734820";
set c_entry_text_color = "#333";
set c_entry_title_color = "#000";
set c_entry_border = "#BFBFBF";
set c_meta_background = "#fff";
set c_meta_link = "#99602B";
set c_meta_link_visited = "#BF7836";
set c_meta_link_hover = "#734820";
set c_meta_link_active = "#734820";
set c_meta_text_color = "#666";
set c_footer_background = "#667320";
set c_footer_link = "#000";
set c_footer_link_visited = "#000";
set c_footer_link_hover = "#fff";
set c_footer_link_active = "#000";
set c_footer_text_color = "#000";
set c_comment_one_link = "#99602B";
set c_comment_one_link_visited = "#BF7836";
set c_comment_one_link_hover = "#734820";
set c_comment_one_link_active = "#734820";
set c_comment_one_text_color = "#333";
set c_comment_one_title_color = "#000";
set c_comment_one_background = "#fff";
set c_comment_one_border = "#999";
set c_comment_two_link = "#99602B";
set c_comment_two_link_visited = "#BF7836";
set c_comment_two_link_hover = "#734820";
set c_comment_two_link_active = "#734820";
set c_comment_two_text_color = "#333";
set c_comment_two_title_color = "#000";
set c_comment_two_background = "#f2f2f2";
set c_comment_two_border = "#999";
set c_comment_screened_link = "#99602B";
set c_comment_screened_link_visited = "#BF7836";
set c_comment_screened_link_hover = "#734820";
set c_comment_screened_link_active = "#734820";
set c_comment_screened_text_color = "#333";
set c_comment_screened_title_color = "#000";
set c_comment_screened_background = "#ccc";
set c_comment_screened_border = "#999";
#NEWLAYER: tranquilityii/money
layerinfo "redist_uniq" = "tranquilityii/money";
layerinfo "type" = "theme";
layerinfo "name" = "Tranquility II - Money Theme";
layerinfo "author_name" = "Matthew Vince";
set c_main_border = "#68754D";
set c_header_background = "#ACC280";
set c_header_border = "#ACC280";
set c_page_title = "#3D3D3D";
set c_page_background = "#ACC280";
set c_page_text = "#3D3D3D";
set c_page_link = "#000";
set c_page_link_visited = "#666";
set c_page_link_hover = "#999";
set c_page_link_active = "#999";
set c_menu_border = "#68754D";
set c_menu_background = "#8A9C67";
set c_menu_link = "#000";
set c_menu_link_visited = "#000";
set c_menu_link_hover = "#EBF7D4";
set c_menu_link_active = "#ebf7d4";
set c_menu_text_color = "#000";
set c_menu_header_color = "#000";
set c_menu_current = "#EBF7D4";
set f_menu_header_size = "140%";
set c_entry_background = "#fff";
set c_entry_link = "#679C67";
set c_entry_link_visited = "#80C280";
set c_entry_link_hover = "#4D754D";
set c_entry_link_active = "#4D754D";
set c_entry_text_color = "#000";
set c_entry_title_color = "#000";
set c_entry_border = "#3D3D3D";
set c_meta_background = "#fff";
set c_meta_link = "#679C67";
set c_meta_link_visited = "#80C280";
set c_meta_link_hover = "#4D754D";
set c_meta_link_active = "#4D754D";
set c_meta_text_color = "#3D3D3D";
set c_footer_background = "#ACC280";
set c_footer_link = "#000";
set c_footer_link_visited = "#000";
set c_footer_link_hover = "#fff";
set c_footer_link_active = "#000";
set c_footer_text_color = "#000";
set c_comment_one_link = "#679C67";
set c_comment_one_link_visited = "#80C280";
set c_comment_one_link_hover = "#4D754D";
set c_comment_one_link_active = "#4D754D";
set c_comment_one_text_color = "#000";
set c_comment_one_title_color = "#000";
set c_comment_one_background = "#fff";
set c_comment_one_border = "#999";
set c_comment_two_link = "#679C67";
set c_comment_two_link_visited = "#80C280";
set c_comment_two_link_hover = "#4D754D";
set c_comment_two_link_active = "#4D754D";
set c_comment_two_text_color = "#000";
set c_comment_two_title_color = "#000";
set c_comment_two_background = "#f2f2f2";
set c_comment_two_border = "#999";
set c_comment_screened_link = "#679C67";
set c_comment_screened_link_visited = "#80C280";
set c_comment_screened_link_hover = "#4D754D";
set c_comment_screened_link_active = "#4D754D";
set c_comment_screened_text_color = "#000";
set c_comment_screened_title_color = "#000";
set c_comment_screened_background = "#ccc";
set c_comment_screened_border = "#999";
set f_page = "Tahoma, Verdana, Helvetica, sans-serif";
set f_page_title = "Tahoma, Verdana, Helvetica, sans-serif";
set f_page_link = "Tahoma, Verdana, Helvetica, sans-serif";
set f_menu_link = "Verdana, Helvetica, sans-serif";
set f_menu = "Tahoma, Verdana, Helvetica, sans-serif";
set f_menu_header = "Tahoma, Verdana, Helvetica, sans-serif";
set f_menu_current = "Verdana, Helvetica, sans-serif";
set f_entry = "Tahoma, Verdana, Helvetica, sans-serif";
set f_entry_link = "Tahoma, Verdana, Helvetica, sans-serif";
set f_entry_title = "Tahoma, Verdana, Helvetica, sans-serif";
set f_meta = "Verdana, Helvetica, sans-serif";
set f_meta_link = "Verdana, Helvetica, sans-serif";
set f_footer = "Tahoma, Verdana, Helvetica, sans-serif";
set f_footer_link = "Tahoma, Verdana, Helvetica, sans-serif";
set f_comment = "Tahoma, Verdana, Helvetica, sans-serif";
set f_comment_title = "Tahoma, Verdana, Helvetica, sans-serif";
set f_comment_link = "Tahoma, Verdana, Helvetica, sans-serif";
#NEWLAYER: tranquilityii/winterice
layerinfo "redist_uniq" = "tranquilityii/winterice";
layerinfo "type" = "theme";
layerinfo "name" = "Tranquility II - WinterIce Theme";
layerinfo "author_name" = "Matthew Vince";
set c_main_border = "#000";
set c_header_background = "#694D73";
set c_header_border = "#694D73";
set c_page_title = "#000";
set c_page_background = "#694D73";
set c_page_text = "#3D3D3D";
set c_page_link = "#000";
set c_page_link_visited = "#666";
set c_page_link_hover = "#999";
set c_page_link_active = "#999";
set c_menu_border = "#694D73";
set c_menu_background = "#694D73";
set c_menu_link = "#fff";
set c_menu_link_visited = "#fff";
set c_menu_link_hover = "#C5A2D0";
set c_menu_link_active = "#C5A2D0";
set c_menu_text_color = "#fff";
set c_menu_header_color = "#fff";
set c_menu_current = "#C5A2D0";
set f_menu_header_size = "140%";
set c_entry_background = "#fff";
set c_entry_link = "#5E71AE";
set c_entry_link_visited = "#5E71AE";
set c_entry_link_hover = "#808FBF";
set c_entry_link_active = "#808FBF";
set c_entry_text_color = "#000";
set c_entry_title_color = "#000";
set c_entry_border = "#3D3D3D";
set c_meta_background = "#fff";
set c_meta_link = "#B080BF";
set c_meta_link_visited = "#C29FCB";
set c_meta_link_hover = "#854D93";
set c_meta_link_active = "#854D93";
set c_meta_text_color = "#3D3D3D";
set c_footer_background = "#694D73";
set c_footer_link = "#fff";
set c_footer_link_visited = "#fff";
set c_footer_link_hover = "#fff";
set c_footer_link_active = "#fff";
set c_footer_text_color = "#fff";
set c_comment_one_link = "#5E71AE";
set c_comment_one_link_visited = "#5E71AE";
set c_comment_one_link_hover = "#808FBF";
set c_comment_one_link_active = "#808FBF";
set c_comment_one_text_color = "#000";
set c_comment_one_title_color = "#000";
set c_comment_one_background = "#fff";
set c_comment_one_border = "#999";
set c_comment_two_link = "#5E71AE";
set c_comment_two_link_visited = "#5E71AE";
set c_comment_two_link_hover = "#808FBF";
set c_comment_two_link_active = "#808FBF";
set c_comment_two_text_color = "#000";
set c_comment_two_title_color = "#000";
set c_comment_two_background = "#f2f2f2";
set c_comment_two_border = "#999";
set c_comment_screened_link = "#5E71AE";
set c_comment_screened_link_visited = "#5E71AE";
set c_comment_screened_link_hover = "#808FBF";
set c_comment_screened_link_active = "#808FBF";
set c_comment_screened_text_color = "#000";
set c_comment_screened_title_color = "#000";
set c_comment_screened_background = "#ccc";
set c_comment_screened_border = "#999";
set f_page = "Tahoma, Verdana, Helvetica, sans-serif";
set f_page_title = "Tahoma, Verdana, Helvetica, sans-serif";
set f_page_link = "Tahoma, Verdana, Helvetica, sans-serif";
set f_menu_link = "Verdana, Helvetica, sans-serif";
set f_menu = "Tahoma, Verdana, Helvetica, sans-serif";
set f_menu_header = "Tahoma, Verdana, Helvetica, sans-serif";
set f_menu_current = "Verdana, Helvetica, sans-serif";
set f_entry = "Tahoma, Verdana, Helvetica, sans-serif";
set f_entry_link = "Tahoma, Verdana, Helvetica, sans-serif";
set f_entry_title = "Tahoma, Verdana, Helvetica, sans-serif";
set f_meta = "Verdana, Helvetica, sans-serif";
set f_meta_link = "Verdana, Helvetica, sans-serif";
set f_footer = "Tahoma, Verdana, Helvetica, sans-serif";
set f_footer_link = "Tahoma, Verdana, Helvetica, sans-serif";
set f_comment = "Tahoma, Verdana, Helvetica, sans-serif";
set f_comment_title = "Tahoma, Verdana, Helvetica, sans-serif";
set f_comment_link = "Tahoma, Verdana, Helvetica, sans-serif";
#NEWLAYER: tranquilityii/fire
layerinfo "redist_uniq" = "tranquilityii/fire";
layerinfo "type" = "theme";
layerinfo "name" = "Tranquility II - Fire Theme";
layerinfo "author_name" = "Matthew Vince";
set c_main_border = "#A65000";
set c_header_background = "#A65000";
set c_header_border = "#A65000";
set c_page_title = "#000";
set c_page_background = "#A65000";
set c_page_text = "#3D3D3D";
set c_page_link = "#000";
set c_page_link_visited = "#666";
set c_page_link_hover = "#999";
set c_page_link_active = "#999";
set c_menu_border = "#A68700";
set c_menu_background = "#CCA700";
set c_menu_link = "#fff";
set c_menu_link_visited = "#FFD100";
set c_menu_link_hover = "#CC4100";
set c_menu_link_active = "#CC4100";
set c_menu_text_color = "#fff";
set c_menu_header_color = "#fff";
set c_menu_current = "#CC4100";
set f_menu_header_size = "140%";
set c_entry_background = "#fff";
set c_entry_link = "#CC6300";
set c_entry_link_visited = "#F27500";
set c_entry_link_hover = "#A65000";
set c_entry_link_active = "#A65000";
set c_entry_text_color = "#333";
set c_entry_title_color = "#333";
set c_entry_border = "#666";
set c_meta_background = "#fff";
set c_meta_link = "#CCA700";
set c_meta_link_visited = "#F2C600";
set c_meta_link_hover = "#A68700";
set c_meta_link_active = "#A68700";
set c_meta_text_color = "#3D3D3D";
set c_footer_background = "#A65000";
set c_footer_link = "#fff";
set c_footer_link_visited = "#fff";
set c_footer_link_hover = "#fff";
set c_footer_link_active = "#fff";
set c_footer_text_color = "#fff";
set c_comment_one_link = "#CC6300";
set c_comment_one_link_visited = "#F27500";
set c_comment_one_link_hover = "#A65000";
set c_comment_one_link_active = "#A65000";
set c_comment_one_text_color = "#333";
set c_comment_one_title_color = "#000";
set c_comment_one_background = "#fff";
set c_comment_one_border = "#999";
set c_comment_two_link = "#CC6300";
set c_comment_two_link_visited = "#F27500";
set c_comment_two_link_hover = "#A65000";
set c_comment_two_link_active = "#A65000";
set c_comment_two_text_color = "#333";
set c_comment_two_title_color = "#000";
set c_comment_two_background = "#f2f2f2";
set c_comment_two_border = "#999";
set c_comment_screened_link = "#CC6300";
set c_comment_screened_link_visited = "#F27500";
set c_comment_screened_link_hover = "#A65000";
set c_comment_screened_link_active = "#A65000";
set c_comment_screened_text_color = "#333";
set c_comment_screened_title_color = "#000";
set c_comment_screened_background = "#ccc";
set c_comment_screened_border = "#999";
#NEWLAYER: tranquilityii/mobile
layerinfo "redist_uniq" = "tranquilityii/mobile";
layerinfo "type" = "theme";
layerinfo "name" = "Tranquility II - Mobile Theme";
layerinfo "author_name" = "Matthew Vince";
set c_main_border = "#fff";
set c_header_background = "#fff";
set c_header_border = "#fff";
set c_page_title = "#000";
set c_page_background = "#fff";
set c_page_text = "#000";
set c_page_link = "#00f";
set c_page_link_visited = "#999";
set c_page_link_hover = "#f00";
set c_page_link_active = "#f00";
set c_menu_border = "#fff";
set c_menu_background = "#fff";
set c_menu_link = "#00f";
set c_menu_link_visited = "#999";
set c_menu_link_hover = "#f00";
set c_menu_link_active = "#f00";
set c_menu_text_color = "#000";
set c_menu_header_color = "#00";
set c_menu_current = "#000";
set f_menu_header_size = "140%";
set c_entry_background = "#fff";
set c_entry_link = "#00f";
set c_entry_link_visited = "#999";
set c_entry_link_hover = "#f00";
set c_entry_link_active = "#f00";
set c_entry_text_color = "#000";
set c_entry_title_color = "#000";
set c_entry_border = "#fff";
set c_meta_background = "#fff";
set c_meta_link = "#00f";
set c_meta_link_visited = "#999";
set c_meta_link_hover = "#f00";
set c_meta_link_active = "#f00";
set c_meta_text_color = "#000";
set c_footer_background = "#fff";
set c_footer_link = "#00f";
set c_footer_link_visited = "#999";
set c_footer_link_hover = "#f00";
set c_footer_link_active = "#f00";
set c_footer_text_color = "#000";
set c_comment_one_link = "#00f";
set c_comment_one_link_visited = "#999";
set c_comment_one_link_hover = "#f00";
set c_comment_one_link_active = "#f00";
set c_comment_one_text_color = "#000";
set c_comment_one_title_color = "#000";
set c_comment_one_background = "#fff";
set c_comment_one_border = "#fff";
set c_comment_two_link = "#00f";
set c_comment_two_link_visited = "#999";
set c_comment_two_link_hover = "#f00";
set c_comment_two_link_active = "#f00";
set c_comment_two_text_color = "#000";
set c_comment_two_title_color = "#000";
set c_comment_two_background = "#f2f2f2";
set c_comment_two_border = "#fff";
set c_comment_screened_link = "#00f";
set c_comment_screened_link_visited = "#999";
set c_comment_screened_link_hover = "#f00";
set c_comment_screened_link_active = "#f00";
set c_comment_screened_text_color = "#000";
set c_comment_screened_title_color = "#000";
set c_comment_screened_background = "#999";
set c_comment_screened_border = "#fff";
set menu_disable_summary = true;
set css_style_overrides = "hr { display: block; } #menu { float: none; width: auto; } #content { margin-left: 0; } #container { margin: 0; padding: 0; text-align: left; width: 100%; }";
#NEWLAYER: tranquilityii/pinky
layerinfo "redist_uniq" = "tranquilityii/pinky";
layerinfo "type" = "theme";
layerinfo "name" = "Tranquility II - Pinky Theme";
layerinfo "author_name" = "Matthew Vince";
set c_main_border = "#242E35";
set c_header_background = "#242E35";
set c_header_border = "#242E35";
set c_page_title = "#fff";
set c_page_background = "#242E35";
set c_page_text = "#fff";
set c_page_link = "#f0c";
set c_page_link_visited = "#FF82E5";
set c_page_link_hover = "#B30090";
set c_page_link_active = "#B30090";
set c_menu_border = "#B4A361";
set c_menu_background = "#ECE9D8";
set c_menu_link = "#000";
set c_menu_link_visited = "#999";
set c_menu_link_hover = "#000";
set c_menu_link_active = "#000";
set c_menu_text_color = "#333";
set c_menu_header_color = "#333";
set c_menu_current = "#000";
set f_menu_header_size = "140%";
set c_entry_background = "#F8F7F1";
set c_entry_link = "#f0c";
set c_entry_link_visited = "#FF82E5";
set c_entry_link_hover = "#B30090";
set c_entry_link_active = "#B30090";
set c_entry_text_color = "#333";
set c_entry_title_color = "#666";
set c_entry_border = "000";
set c_meta_background = "#F8F7F1";
set c_meta_link = "#f0c";
set c_meta_link_visited = "#FF82E5";
set c_meta_link_hover = "#B30090";
set c_meta_link_active = "#B30090";
set c_meta_text_color = "#666";
set c_footer_background = "#242E35";
set c_footer_link = "#fff";
set c_footer_link_visited = "#fff";
set c_footer_link_hover = "#fff";
set c_footer_link_active = "#fff";
set c_footer_text_color = "#fff";
set c_comment_one_link = "#f0c";
set c_comment_one_link_visited = "#FF82E5";
set c_comment_one_link_hover = "#B30090";
set c_comment_one_link_active = "#B30090";
set c_comment_one_text_color = "#333";
set c_comment_one_title_color = "#666";
set c_comment_one_background = "#fff";
set c_comment_one_border = "#999";
set c_comment_two_link = "#f0c";
set c_comment_two_link_visited = "#FF82E5";
set c_comment_two_link_hover = "#B30090";
set c_comment_two_link_active = "#B30090";
set c_comment_two_text_color = "#333";
set c_comment_two_title_color = "#666";
set c_comment_two_background = "#f2f2f2";
set c_comment_two_border = "#999";
set c_comment_screened_link = "#f0c";
set c_comment_screened_link_visited = "#FF82E5";
set c_comment_screened_link_hover = "#B30090";
set c_comment_screened_link_active = "#B30090";
set c_comment_screened_text_color = "#333";
set c_comment_screened_title_color = "#666";
set c_comment_screened_background = "#ccc";
set c_comment_screened_border = "#999";
set f_page = "Tahoma, Verdana, Helvetica, sans-serif";
set f_page_title = "Tahoma, Verdana, Helvetica, sans-serif";
set f_page_link = "Tahoma, Verdana, Helvetica, sans-serif";
set f_menu_link = "Verdana, Helvetica, sans-serif";
set f_menu = "Tahoma, Verdana, Helvetica, sans-serif";
set f_menu_header = "Tahoma, Verdana, Helvetica, sans-serif";
set f_menu_current = "Verdana, Helvetica, sans-serif";
set f_entry = "Tahoma, Verdana, Helvetica, sans-serif";
set f_entry_link = "Tahoma, Verdana, Helvetica, sans-serif";
set f_entry_title = "Tahoma, Verdana, Helvetica, sans-serif";
set f_meta = "Verdana, Helvetica, sans-serif";
set f_meta_link = "Verdana, Helvetica, sans-serif";
set f_footer = "Tahoma, Verdana, Helvetica, sans-serif";
set f_footer_link = "Tahoma, Verdana, Helvetica, sans-serif";
set f_comment = "Tahoma, Verdana, Helvetica, sans-serif";
set f_comment_title = "Tahoma, Verdana, Helvetica, sans-serif";
set f_comment_link = "Tahoma, Verdana, Helvetica, sans-serif";
#NEWLAYER: tranquilityii/fresh
layerinfo "redist_uniq" = "tranquilityii/fresh";
layerinfo "type" = "theme";
layerinfo "name" = "Tranquility II - Fresh Theme";
layerinfo "author_name" = "Matthew Vince";
set c_main_border = "#7A97B2";
set c_header_background = "#7A97B2";
set c_header_border = "#7A97B2";
set c_page_title = "#273849";
set c_page_background = "#242E35";
set c_page_text = "#fff";
set c_page_link = "#036";
set c_page_link_visited = "#036";
set c_page_link_hover = "#069";
set c_page_link_active = "#069";
set c_menu_border = "#CFE0E6";
set c_menu_background = "#CFE0E6";
set c_menu_link = "#000";
set c_menu_link_visited = "#999";
set c_menu_link_hover = "#000";
set c_menu_link_active = "#000";
set c_menu_text_color = "#333";
set c_menu_header_color = "#333";
set c_menu_current = "#000";
set f_menu_header_size = "140%";
set c_entry_background = "#fff";
set c_entry_link = "#036";
set c_entry_link_visited = "#036";
set c_entry_link_hover = "#069";
set c_entry_link_active = "#069";
set c_entry_text_color = "#333";
set c_entry_title_color = "#999";
set c_entry_border = "000";
set c_meta_background = "#fff";
set c_meta_link = "#036";
set c_meta_link_visited = "#036";
set c_meta_link_hover = "#069";
set c_meta_link_active = "#069";
set c_meta_text_color = "#999";
set c_footer_background = "#7A97B2";
set c_footer_link = "#fff";
set c_footer_link_visited = "#fff";
set c_footer_link_hover = "#fff";
set c_footer_link_active = "#fff";
set c_footer_text_color = "#fff";
set c_comment_one_link = "#036";
set c_comment_one_link_visited = "#036";
set c_comment_one_link_hover = "#069";
set c_comment_one_link_active = "#069";
set c_comment_one_text_color = "#333";
set c_comment_one_title_color = "#999";
set c_comment_one_background = "#fff";
set c_comment_one_border = "#999";
set c_comment_two_link = "#036";
set c_comment_two_link_visited = "#036";
set c_comment_two_link_hover = "#069";
set c_comment_two_link_active = "#069";
set c_comment_two_text_color = "#333";
set c_comment_two_title_color = "#999";
set c_comment_two_background = "#f2f2f2";
set c_comment_two_border = "#999";
set c_comment_screened_link = "#036";
set c_comment_screened_link_visited = "#036";
set c_comment_screened_link_hover = "#069";
set c_comment_screened_link_active = "#069";
set c_comment_screened_text_color = "#333";
set c_comment_screened_title_color = "#999";
set c_comment_screened_background = "#ccc";
set c_comment_screened_border = "#999";
set f_page = "Tahoma, Verdana, Helvetica, sans-serif";
set f_page_title = "Tahoma, Verdana, Helvetica, sans-serif";
set f_page_link = "Tahoma, Verdana, Helvetica, sans-serif";
set f_menu_link = "Verdana, Helvetica, sans-serif";
set f_menu = "Tahoma, Verdana, Helvetica, sans-serif";
set f_menu_header = "Tahoma, Verdana, Helvetica, sans-serif";
set f_menu_current = "Verdana, Helvetica, sans-serif";
set f_entry = "Tahoma, Verdana, Helvetica, sans-serif";
set f_entry_link = "Tahoma, Verdana, Helvetica, sans-serif";
set f_entry_title = "Tahoma, Verdana, Helvetica, sans-serif";
set f_meta = "Verdana, Helvetica, sans-serif";
set f_meta_link = "Verdana, Helvetica, sans-serif";
set f_footer = "Tahoma, Verdana, Helvetica, sans-serif";
set f_footer_link = "Tahoma, Verdana, Helvetica, sans-serif";
set f_comment = "Tahoma, Verdana, Helvetica, sans-serif";
set f_comment_title = "Tahoma, Verdana, Helvetica, sans-serif";
set f_comment_link = "Tahoma, Verdana, Helvetica, sans-serif";
#NEWLAYER: tranquilityii/auto
layerinfo "redist_uniq" = "tranquilityii/auto";
layerinfo "type" = "theme";
layerinfo "name" = "Tranquility II - Auto Theme";
layerinfo "author_name" = "Matthew Vince";
set c_main_border = "#515151";
set c_header_background = "#515151";
set c_header_border = "#515151";
set c_page_title = "#fff";
set c_page_background = "#515151";
set c_page_text = "#333";
set c_page_link = "#00B4FF";
set c_page_link_visited = "#00B4FF";
set c_page_link_hover = "#006894";
set c_page_link_active = "#006894";
set c_menu_border = "#ccc";
set c_menu_background = "#eee";
set c_menu_link = "#000";
set c_menu_link_visited = "#999";
set c_menu_link_hover = "#000";
set c_menu_link_active = "#000";
set c_menu_text_color = "#333";
set c_menu_header_color = "#333";
set c_menu_current = "#000";
set f_menu_header_size = "140%";
set c_entry_background = "#fff";
set c_entry_link = "#00B4FF";
set c_entry_link_visited = "#00B4FF";
set c_entry_link_hover = "#006894";
set c_entry_link_active = "#006894";
set c_entry_text_color = "#333";
set c_entry_title_color = "#999";
set c_entry_border = "000";
set c_meta_background = "#fff";
set c_meta_link = "#036";
set c_meta_link_visited = "#036";
set c_meta_link_hover = "#069";
set c_meta_link_active = "#069";
set c_meta_text_color = "#999";
set c_footer_background = "#515151";
set c_footer_link = "#fff";
set c_footer_link_visited = "#fff";
set c_footer_link_hover = "#fff";
set c_footer_link_active = "#fff";
set c_footer_text_color = "#fff";
set c_comment_one_link = "#00B4FF";
set c_comment_one_link_visited = "#00B4FF";
set c_comment_one_link_hover = "#006894";
set c_comment_one_link_active = "#006894";
set c_comment_one_text_color = "#333";
set c_comment_one_title_color = "#999";
set c_comment_one_background = "#fff";
set c_comment_one_border = "#999";
set c_comment_two_link = "#00B4FF";
set c_comment_two_link_visited = "#00B4FF";
set c_comment_two_link_hover = "#006894";
set c_comment_two_link_active = "#006894";
set c_comment_two_text_color = "#333";
set c_comment_two_title_color = "#999";
set c_comment_two_background = "#f2f2f2";
set c_comment_two_border = "#999";
set c_comment_screened_link = "#00B4FF";
set c_comment_screened_link_visited = "#00B4FF";
set c_comment_screened_link_hover = "#006894";
set c_comment_screened_link_active = "#006894";
set c_comment_screened_text_color = "#333";
set c_comment_screened_title_color = "#999";
set c_comment_screened_background = "#ccc";
set c_comment_screened_border = "#999";

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,118 @@
#NEWLAYER: unearthed/rampant
layerinfo "type" = "theme";
layerinfo "name" = "Rampant Tenderfoot";
layerinfo redist_uniq = "unearthed/rampant";
set stronger_bgcolor = "#ff3300";
set strong_bgcolor = "#ff8000";
set neutral_bgcolor = "#ffb200";
set weak_bgcolor = "#ffb380";
set weaker_bgcolor = "#ffcc80";
#NEWLAYER: unearthed/acrid
layerinfo "type" = "theme";
layerinfo "name" = "Acrid Slide";
layerinfo redist_uniq = "unearthed/acrid";
set title_texture = "rough";
set stronger_bgcolor = "#33ff00";
set strong_bgcolor = "#0066b2";
set neutral_bgcolor = "#00B266";
set weak_bgcolor = "#99ff80";
set weaker_bgcolor = "#ccffbf";
#NEWLAYER: unearthed/leisure
layerinfo "type" = "theme";
layerinfo "name" = "Leisure Renewal";
layerinfo redist_uniq = "unearthed/leisure";
set title_texture = "camouflage";
set stronger_bgcolor = "#285577";
set strong_bgcolor = "#3c3773";
set neutral_bgcolor = "#287755";
set weak_bgcolor = "#c0c0ec";
set weaker_bgcolor = "#b1ecd3";
#NEWLAYER: unearthed/craftis
layerinfo "type" = "theme";
layerinfo "name" = "Craftis";
layerinfo redist_uniq = "unearthed/craftis";
set title_texture = "camouflage";
set stronger_bgcolor = "#dd0000";
set strong_bgcolor = "#aa4f39";
set neutral_bgcolor = "#d2d2d2";
set weak_bgcolor = "#fcffcf";
set weaker_bgcolor = "#eeeeee";
#NEWLAYER: unearthed/unveiled
layerinfo "type" = "theme";
layerinfo "name" = "Unveiled Metal";
layerinfo redist_uniq = "unearthed/unveiled";
set title_texture = "brushed_metal";
set stronger_bgcolor = "#666666";
set strong_bgcolor = "#999999";
set neutral_bgcolor = "#333333";
set weak_bgcolor = "#cccccc";
set weaker_bgcolor = "#eeeeee";
#NEWLAYER: unearthed/wait
layerinfo "type" = "theme";
layerinfo "name" = "Wait Screw";
layerinfo redist_uniq = "unearthed/wait";
set title_texture = "chalk";
set stronger_bgcolor = "#009999";
set strong_bgcolor = "#ff6600";
set neutral_bgcolor = "#66cccc";
set weak_bgcolor = "#ffb380";
set weaker_bgcolor = "#eeeeee";
#NEWLAYER: unearthed/drinkdna
layerinfo "type" = "theme";
layerinfo "name" = "Drinking DNA";
layerinfo redist_uniq = "unearthed/drinkdna";
set title_texture = "cork";
set stronger_bgcolor = "#4C9978";
set strong_bgcolor = "#468C8C";
set neutral_bgcolor = "#53A653";
set weak_bgcolor = "#ACE6E6";
set weaker_bgcolor = "#eeeeee";
#NEWLAYER: unearthed/gainful
layerinfo "type" = "theme";
layerinfo "name" = "Gainful Magic";
layerinfo redist_uniq = "unearthed/gainful";
set title_texture = "fibers";
set stronger_bgcolor = "#DFDFA7";
set strong_bgcolor = "#FFFF80";
set neutral_bgcolor = "#AAAA39";
set weak_bgcolor = "#eeeeee";
set weaker_bgcolor = "#FFFFBF";
#NEWLAYER: unearthed/inaccurate
layerinfo "type" = "theme";
layerinfo "name" = "Inaccurate Lingo";
layerinfo redist_uniq = "unearthed/inaccurate";
set title_texture = "stucco";
set stronger_bgcolor = "#FF8080";
set strong_bgcolor = "#FF9980";
set neutral_bgcolor = "#E572A5";
set weak_bgcolor = "#F2B6D0";
set weaker_bgcolor = "#eeeeee";
#NEWLAYER: unearthed/current
layerinfo "type" = "theme";
layerinfo "name" = "Current Protector";
layerinfo redist_uniq = "unearthed/current";
set title_texture = "type";
set stronger_bgcolor = "#B5D9D9";
set strong_bgcolor = "#285577";
set neutral_bgcolor = "#226666";
set weak_bgcolor = "#7DA0BB";
set weaker_bgcolor = "#B5D9D9";

View File

@@ -0,0 +1,25 @@
;; -*- coding: utf-8 -*-
/manage/siteopts.bml.btn.lang=Сменити язык
dystopia.hello_loggedin=Здорово буть
langname.en=Аглицкий
langname.ru=Руской
langname.sb=Сибирской
ljrlook.nav.editfriends=Тамыри
ljrlook.nav.friends=Тамыри
ljrlook.nav.hello=Здорово буть
lynx.nav.friends=Тамыри
poll.security.friends=Тамыри
xcolibur.nav.journal.friends=Тамыри
xcolibur.nav.manage.friends=Тамыри

View File

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
domain:100:faq
domain:101:journal/news
# EnglishLJ is child of English for general domain:
#lang:100:en_LJ:English (LJ):sim:en
#langdomain:en_LJ:general
# EnglishLJ is root of FAQ & news journal:
#langdomain:en_LJ:faq:1
#langdomain:en_LJ:journal/news:1
# Russian
lang:106:ru:Russian:diff:en
langdomain:ru:general
langdomain:ru:journal/news
langdomain:ru:faq
# Ukrainian
lang:131:uk:Ukrainian:diff:en
langdomain:uk:general
langdomain:uk:journal/news
langdomain:uk:faq
# Siberian
lang:206:sb:Siberian:diff:en
langdomain:sb:general
langdomain:sb:journal/news
langdomain:sb:faq

View File

@@ -0,0 +1,84 @@
#
# texttool.pl newitems override
# format:
# <code calculated by texttool.pl><space><actual code which should be used>
#
/modify.bml.colortheme.defaulttheme /modify_do.bml.colortheme.defaulttheme
/modify.bml.colortheme.color.head2 /modify_do.bml.colortheme.color.head2
/modify.bml.colortheme.customcolors /modify_do.bml.colortheme.customcolors
/modify.bml.overrides.warning /modify_do.bml.overrides.warning
/modify.bml.moodicons.head /modify_do.bml.moodicons.head
/modify.bml.availablestyles.userstyles /modify_do.bml.availablestyles.userstyles
/modify.bml.overrides.head /modify_do.bml.overrides.head
/modify.bml.moodicons.personal /modify_do.bml.moodicons.personal
/modify.bml.domainalias.example /modify_do.bml.domainalias.example
/modify.bml.friends.opt.usesharedpic.about /modify_do.bml.friends.opt.usesharedpic.about
/modify.bml.overrides.note /modify_do.bml.overrides.note
/modify.bml.colortheme.about /modify_do.bml.colortheme.about
/modify.bml.done.text /modify_do.bml.done.text
/modify.bml.success.head /modify_do.bml.success.head
/modify.bml.pagelayoutstyle.warning /modify_do.bml.pagelayoutstyle.warning
/modify.bml.friends.head /modify_do.bml.friends.head
/modify.bml.error.stylenotavailable /modify_do.bml.error.stylenotavailable
/modify.bml.colortheme.color.head1 /modify_do.bml.colortheme.color.head1
/modify.bml.friends.opt.usesharedpic.head /modify_do.bml.friends.opt.usesharedpic.head
/modify.bml.pagelayoutstyle.about /modify_do.bml.pagelayoutstyle.about
/modify.bml.domainalias.head /modify_do.bml.domainalias.head
/modify.bml.moodicons.opt.forcefriends.about /modify_do.bml.moodicons.opt.forcefriends.about
/modify.bml.colortheme.head /modify_do.bml.colortheme.head
/modify.bml.moodicons.preview /modify_do.bml.moodicons.preview
/modify.bml.pagelayoutstyle.head /modify_do.bml.pagelayoutstyle.head
/modify.bml.moodicons.about /modify_do.bml.moodicons.about
/modify.bml.friends.about /modify_do.bml.friends.about
/modify.bml.colortheme.area.head /modify_do.bml.colortheme.area.head
/modify.bml.availablestyles.head /modify_do.bml.availablestyles.head
/modify.bml.success.text /modify_do.bml.success.text
/modify.bml.domainalias.about /modify_do.bml.domainalias.about
/modify.bml.error.dupdomainalias /modify_do.bml.error.dupdomainalias
/modify.bml.journaloptions.about /modify_do.bml.journaloptions.about
/modify.bml.moodicons.select /modify_do.bml.moodicons.select
/modify.bml.domainalias.domainname /modify_do.bml.domainalias.domainname
/modify.bml.done.head /modify_do.bml.done.head
/modify.bml.overrides.about /modify_do.bml.overrides.about
/modify.bml.overrides.box.head /modify_do.bml.overrides.box.head
/modify.bml.journaloptions.head /modify_do.bml.journaloptions.head
/modify.bml.availablestyles.disabledstyles /modify_do.bml.availablestyles.disabledstyles
/modify.bml.domainalias.helptext /modify_do.bml.domainalias.helptext
/modify.bml.done.btn.savechanges /modify_do.bml.done.btn.savechanges
/friends/edit.bml.opt.delete /friends/edit_do.bml.opt.delete
/friends/edit.bml.name /friends/edit_do.bml.name
/friends/edit.bml.friend /friends/edit_do.bml.friend
/friends/edit.bml.needmore /friends/edit_do.bml.needmore
/friends/edit.bml.success.text /friends/edit_do.bml.success.text
/friends/edit.bml.btn.toggle /friends/edit_do.bml.btn.toggle
/friends/edit.bml.success.head /friends/edit_do.bml.success.head
/friends/edit.bml.error.updating /friends/edit_do.bml.error.updating
/friends/edit.bml.yourfriends.text /friends/edit_do.bml.yourfriends.text
/friends/edit.bml.user /friends/edit_do.bml.user
/friends/edit.bml.nofriends.head /friends/edit_do.bml.nofriends.head
/friends/edit.bml.fellowfriends.head /friends/edit_do.bml.fellowfriends.head
/friends/edit.bml.foreground /friends/edit_do.bml.foreground
/friends/edit.bml.done.text /friends/edit_do.bml.done.text
/friends/edit.bml.addfriends.text /friends/edit_do.bml.addfriends.text
/friends/edit.bml.addfriends.head /friends/edit_do.bml.addfriends.head
/friends/edit.bml.fellowfriends.text /friends/edit_do.bml.fellowfriends.text
/friends/edit.bml.btn.save /friends/edit_do.bml.btn.save
/friends/edit.bml.hover /friends/edit_do.bml.hover
/friends/edit.bml.opt.addtolist /friends/edit_do.bml.opt.addtolist
/friends/edit.bml.yourfriends.head /friends/edit_do.bml.yourfriends.head
/friends/edit.bml.background /friends/edit_do.bml.background
/friends/edit.bml.done.head /friends/edit_do.bml.done.head
/friends/edit.bml.nofriends.text /friends/edit_do.bml.nofriends.text
.opt.bannedfrom /talkpost.bml.opt.bannedfrom
.opt.loggedin /talkpost.bml.opt.loggedin
.label.picturetouse2 /talkpost.bml.label.picturetouse2
.noaccount /talkpost.bml.noaccount
/editjournal.bml.pickentry.head /editjournal_do.bml.pickentry.head
/editjournal.bml.error.modify /editjournal_do.bml.error.modify
/editjournal.bml.pickentry.text /editjournal_do.bml.pickentry.text
/editjournal.bml.error.nofind /editjournal_do.bml.error.nofind
/editjournal.bml.error.getting /editjournal_do.bml.error.getting

758
local/bin/upgrading/texttool.pl Executable file
View File

@@ -0,0 +1,758 @@
#!/usr/bin/perl
#
# This program deals with inserting/extracting text/language data
# from the database.
#
use strict;
use Getopt::Long;
my $opt_help = 0;
my $opt_local_lang;
my $opt_extra;
my $opt_only;
my $opt_override;
my $opt_verbose;
my $opt_do;
my @additems;
exit 1 unless
GetOptions(
"help" => \$opt_help,
"local-lang=s" => \$opt_local_lang,
"extra=s" => \$opt_extra,
"override|r" => \$opt_override,
"verbose" => \$opt_verbose,
"only=s" => \$opt_only,
"do" => \$opt_do,
"additems:s{,}" => \@additems,
);
my $mode = shift @ARGV;
help() if $opt_help or not defined $mode;
sub help
{
die "Usage: texttool.pl <command> [options]
Where 'command' is one of:
load Runs the following four commands in order:
popstruct Populate lang data from text[-local].dat into db
poptext Populate text from en.dat, etc into database.
--extra=<file> specifies an alternative input file
--override (-v) specifies existing values should be overwritten
for all languages. (for developer use only)
copyfaq If site is translating FAQ, copy FAQ data into trans area
loadcrumbs Load crumbs from ljcrumbs.pl and ljcrumbs-local.pl.
makeusable Setup internal indexes necessary after loading text
dumptext Dump lang text based on text[-local].dat information
check Check validity of text[-local].dat files
wipedb Remove all language/text data from database, including crumbs.
wipecrumbs Remove all crumbs from the database, leaving other text alone.
newitems Search files in htdocs, cgi-bin, & bin and insert
necessary text item codes in database
remove takes two extra arguments: domain name and code, and removes
that code and its text in all languages
Optional `options`:
--help The page you're looking at
--verbose More output
--local-lang=.. If given, works on local site files too
--do If given, lets newitems actually create items in database
--additems Takes multiple parameters. If given specifies
what exactly new items should be added.
";
}
## make sure $LJHOME is set so we can load & run everything
unless (-d $ENV{'LJHOME'}) {
die "LJHOME environment variable is not set, or is not a directory.\n".
"You must fix this before you can run this database update script.";
}
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
require "$ENV{'LJHOME'}/cgi-bin/ljlang.pl";
require "$ENV{'LJHOME'}/cgi-bin/weblib.pl";
my %dom_id; # number -> {}
my %dom_code; # name -> {}
my %lang_id; # number -> {}
my %lang_code; # name -> {}
my @lang_domains;
my $set = sub {
my ($hash, $key, $val, $errmsg) = @_;
die "$errmsg$key\n" if exists $hash->{$key};
$hash->{$key} = $val;
};
foreach my $scope ("general", "local")
{
my $file = $scope eq "general" ? "text.dat" : "text-local.dat";
my $ffile = "$ENV{'LJHOME'}/bin/upgrading/$file";
unless (-e $ffile) {
next if $scope eq "local";
die "$file file not found; odd: did you delete it?\n";
}
open (F, $ffile) or die "Can't open file: $file: $!\n";
while (<F>) {
s/\s+$//; s/^\#.+//;
next unless /\S/;
my @vals = split(/:/, $_);
my $what = shift @vals;
# language declaration
if ($what eq "lang") {
my $lang = {
'scope' => $scope,
'lnid' => $vals[0],
'lncode' => $vals[1],
'lnname' => $vals[2],
'parentlnid' => 0, # default. changed later.
'parenttype' => 'diff',
};
$lang->{'parenttype'} = $vals[3] if defined $vals[3];
if (defined $vals[4]) {
unless (exists $lang_code{$vals[4]}) {
die "Can't declare language $lang->{'lncode'} with missing parent language $vals[4].\n";
}
$lang->{'parentlnid'} = $lang_code{$vals[4]}->{'lnid'};
}
$set->(\%lang_id, $lang->{'lnid'}, $lang, "Language already defined with ID: ");
$set->(\%lang_code, $lang->{'lncode'}, $lang, "Language already defined with code: ");
}
# domain declaration
if ($what eq "domain") {
my $dcode = $vals[1];
my ($type, $args) = split(m!/!, $dcode);
my $dom = {
'scope' => $scope,
'dmid' => $vals[0],
'type' => $type,
'args' => $args || "",
};
$set->(\%dom_id, $dom->{'dmid'}, $dom, "Domain already defined with ID: ");
$set->(\%dom_code, $dcode, $dom, "Domain already defined with parameters: ");
}
# langdomain declaration
if ($what eq "langdomain") {
my $ld = {
'lnid' =>
(exists $lang_code{$vals[0]} ? $lang_code{$vals[0]}->{'lnid'} :
die "Undefined language: $vals[0]\n"),
'dmid' =>
(exists $dom_code{$vals[1]} ? $dom_code{$vals[1]}->{'dmid'} :
die "Undefined domain: $vals[1]\n"),
'dmmaster' => $vals[2] ? "1" : "0",
};
push @lang_domains, $ld;
}
}
close F;
}
if ($mode eq "check") {
print "all good.\n";
exit 0;
}
## make sure we can connect
my $dbh = LJ::get_dbh("master");
my $sth;
unless ($dbh) {
die "Can't connect to the database.\n";
}
# indenter
my $idlev = 0;
my $out = sub {
my @args = @_;
while (@args) {
my $a = shift @args;
if ($a eq "+") { $idlev++; }
elsif ($a eq "-") { $idlev--; }
elsif ($a eq "x") { $a = shift @args; die " "x$idlev . $a . "\n"; }
else { print " "x$idlev, $a, "\n"; }
}
};
my @good = qw(load popstruct poptext dumptext newitems wipedb makeusable copyfaq remove
wipecrumbs loadcrumbs);
popstruct() if $mode eq "popstruct" or $mode eq "load";
poptext(@ARGV) if $mode eq "poptext" or $mode eq "load";
copyfaq() if $mode eq "copyfaq" or $mode eq "load";
loadcrumbs() if $mode eq "loadcrumbs" or $mode eq "load";
makeusable() if $mode eq "makeusable" or $mode eq "load";
dumptext(@ARGV) if $mode eq "dumptext";
newitems() if $mode eq "newitems";
wipedb() if $mode eq "wipedb";
wipecrumbs() if $mode eq "wipecrumbs";
remove(@ARGV) if $mode eq "remove" and scalar(@ARGV) == 2;
help() unless grep { $mode eq $_ } @good;
exit 0;
sub makeusable
{
$out->("Making usable...", '+');
my $rec = sub {
my ($lang, $rec) = @_;
my $l = $lang_code{$lang};
$out->("x", "Bogus language: $lang") unless $l;
my @children = grep { $_->{'parentlnid'} == $l->{'lnid'} } values %lang_code;
foreach my $cl (@children) {
$out->("$l->{'lncode'} -- $cl->{'lncode'}");
my %need;
# push downwards everything that has some valid text in some language (< 4)
$sth = $dbh->prepare("SELECT dmid, itid, txtid FROM ml_latest WHERE lnid=$l->{'lnid'} AND staleness < 4");
$sth->execute;
while (my ($dmid, $itid, $txtid) = $sth->fetchrow_array) {
$need{"$dmid:$itid"} = $txtid;
}
$sth = $dbh->prepare("SELECT dmid, itid, txtid FROM ml_latest WHERE lnid=$cl->{'lnid'}");
$sth->execute;
while (my ($dmid, $itid, $txtid) = $sth->fetchrow_array) {
delete $need{"$dmid:$itid"};
}
while (my $k = each %need) {
my ($dmid, $itid) = split(/:/, $k);
my $txtid = $need{$k};
my $stale = $cl->{'parenttype'} eq "diff" ? 3 : 0;
$dbh->do("INSERT INTO ml_latest (lnid, dmid, itid, txtid, chgtime, staleness) VALUES ".
"($cl->{'lnid'}, $dmid, $itid, $txtid, NOW(), $stale)");
die $dbh->errstr if $dbh->err;
}
$rec->($cl->{'lncode'}, $rec);
}
};
$rec->("en", $rec);
$out->("-", "done.");
}
sub copyfaq
{
my $faqd = LJ::Lang::get_dom("faq");
my $ll = LJ::Lang::get_root_lang($faqd);
unless ($ll) { return; }
my $domid = $faqd->{'dmid'};
$out->("Copying FAQ...", '+');
my %existing;
$sth = $dbh->prepare("SELECT i.itcode FROM ml_items i, ml_latest l ".
"WHERE l.lnid=$ll->{'lnid'} AND l.dmid=$domid AND l.itid=i.itid AND i.dmid=$domid");
$sth->execute;
$existing{$_} = 1 while $_ = $sth->fetchrow_array;
# faq category
$sth = $dbh->prepare("SELECT faqcat, faqcatname FROM faqcat");
$sth->execute;
while (my ($cat, $name) = $sth->fetchrow_array) {
next if exists $existing{"cat.$cat"};
my $opts = { 'childrenlatest' => 1 };
LJ::Lang::set_text($dbh, $domid, $ll->{'lncode'}, "cat.$cat", $name, $opts);
}
# faq items
$sth = $dbh->prepare("SELECT faqid, question, answer FROM faq");
$sth->execute;
while (my ($faqid, $q, $a) = $sth->fetchrow_array) {
next if
exists $existing{"$faqid.1question"} and
exists $existing{"$faqid.2answer"};
my $opts = { 'childrenlatest' => 1 };
LJ::Lang::set_text($dbh, $domid, $ll->{'lncode'}, "$faqid.1question", $q, $opts);
LJ::Lang::set_text($dbh, $domid, $ll->{'lncode'}, "$faqid.2answer", $a, $opts);
}
$out->('-', "done.");
}
sub wipedb
{
$out->("Wiping DB...", '+');
foreach (qw(domains items langdomains langs latest text)) {
$out->("deleting from $_");
$dbh->do("DELETE FROM ml_$_");
}
$out->("-", "done.");
}
sub wipecrumbs
{
$out->('Wiping DB of all crumbs...', '+');
# step 1: get all items that are crumbs. [from ml_items]
my $genid = $dom_code{'general'}->{'dmid'};
my @crumbs;
my $sth = $dbh->prepare("SELECT itcode FROM ml_items
WHERE dmid = $genid AND itcode LIKE 'crumb.\%'");
$sth->execute;
while (my ($itcode) = $sth->fetchrow_array) {
# push onto list
push @crumbs, $itcode;
}
# step 2: remove the items that have these unique dmid/itids
foreach my $code (@crumbs) {
$out->("deleting $code");
remove("general", $code);
}
# done
$out->('-', 'done.');
}
sub loadcrumbs
{
$out->('Loading all crumbs into DB...', '+');
# get domain id of 'general' and language id of 'en'
my $genid = $dom_code{'general'}->{'dmid'};
my $loclang = $LJ::LANGS[0] || 'en';
# list of crumbs
my @crumbs;
foreach (keys %LJ::CRUMBS_LOCAL) { push @crumbs, $_; }
foreach (keys %LJ::CRUMBS) { push @crumbs, $_; }
# begin iterating, order doesn't matter...
foreach my $crumbkey (@crumbs) {
$out->("inserting crumb.$crumbkey");
my $crumb = LJ::get_crumb($crumbkey);
my $local = $LJ::CRUMBS_LOCAL{$crumbkey} ? 1 : 0;
# see if it exists
my $itid = $dbh->selectrow_array("SELECT itid FROM ml_items
WHERE dmid = $genid AND itcode = 'crumb.$crumbkey'")+0;
LJ::Lang::set_text($genid, $local ? $loclang : 'en', "crumb.$crumbkey", $crumb->[0])
unless $itid;
}
# done
$out->('-', 'done.');
}
sub popstruct
{
$out->("Populating structure...", '+');
foreach my $l (values %lang_id) {
$out->("Inserting language: $l->{'lnname'}");
$dbh->do("INSERT INTO ml_langs (lnid, lncode, lnname, parenttype, parentlnid) ".
"VALUES (" . join(",", map { $dbh->quote($l->{$_}) } qw(lnid lncode lnname parenttype parentlnid)) . ")");
}
foreach my $d (values %dom_id) {
$out->("Inserting domain: $d->{'type'}\[$d->{'args'}\]");
$dbh->do("INSERT INTO ml_domains (dmid, type, args) ".
"VALUES (" . join(",", map { $dbh->quote($d->{$_}) } qw(dmid type args)) . ")");
}
$out->("Inserting language domains ...");
foreach my $ld (@lang_domains) {
$dbh->do("INSERT IGNORE INTO ml_langdomains (lnid, dmid, dmmaster) VALUES ".
"(" . join(",", map { $dbh->quote($ld->{$_}) } qw(lnid dmid dmmaster)) . ")");
}
$out->("-", "done.");
}
sub poptext
{
my @langs = @_;
push @langs, (keys %lang_code) unless @langs;
$out->("Populating text...", '+');
my %source; # lang -> file, or "[extra]" when given by --extra= argument
if ($opt_extra) {
$source{'[extra]'} = $opt_extra;
} else {
foreach my $lang (@langs) {
my $file = "$ENV{'LJHOME'}/bin/upgrading/${lang}.dat";
next if $opt_only && $lang ne $opt_only;
next unless -e $file;
$source{$lang} = $file;
}
}
my %existing_item; # langid -> code -> 1
foreach my $source (keys %source)
{
$out->("$source", '+');
my $file = $source{$source};
open (D, $file)
or $out->('x', "Can't open $source data file");
# fixed language in *.dat files, but in extra files
# it switches as it goes.
my $l;
if ($source ne "[extra]") { $l = $lang_code{$source}; }
my $bml_prefix = "";
my $addcount = 0;
my $lnum = 0;
my ($code, $text);
my %metadata;
while (my $line = <D>) {
$lnum++;
my $del;
my $action_line;
if ($line =~ /^==(LANG|BML):\s*(\S+)/) {
$out->('x', "Bogus directives in non-extra file.")
if $source ne "[extra]";
my ($what, $val) = ($1, $2);
if ($what eq "LANG") {
$l = $lang_code{$val};
$out->('x', 'Bogus ==LANG switch to: $what') unless $l;
$bml_prefix = "";
} elsif ($what eq "BML") {
$out->('x', 'Bogus ==BML switch to: $what')
unless $val =~ m!^/.+\.bml$!;
$bml_prefix = $val;
}
} elsif ($line =~ /^(\S+?)=(.*)/) {
($code, $text) = ($1, $2);
$action_line = 1;
} elsif ($line =~ /^\!\s*(\S+)/) {
$del = $code;
$action_line = 1;
} elsif ($line =~ /^(\S+?)\<\<\s*$/) {
($code, $text) = ($1, "");
while (<D>) {
$lnum++;
last if $_ eq ".\n";
s/^\.//;
$text .= $_;
}
chomp $text; # remove file new-line (we added it)
$action_line = 1;
} elsif ($line =~ /^[\#\;]/) {
# comment line
next;
} elsif ($line =~ /\S/) {
$out->('x', "$source:$lnum: Bogus format.");
}
if ($code =~ m!^\.!) {
$out->('x', "Can't use code with leading dot: $code")
unless $bml_prefix;
$code = "$bml_prefix$code";
}
if ($code =~ /\|(.+)/) {
$metadata{$1} = $text;
next;
}
next unless $action_line;
$out->('x', 'No language defined!') unless $l;
# load existing items for target language
unless (exists $existing_item{$l->{'lnid'}}) {
$existing_item{$l->{'lnid'}} = {};
my $sth = $dbh->prepare(qq{
SELECT i.itcode
FROM ml_latest l, ml_items i
WHERE i.dmid=1 AND l.dmid=1 AND i.itid=l.itid AND l.lnid=$l->{'lnid'}
});
$sth->execute;
$existing_item{$l->{'lnid'}}->{$_} = 1
while $_ = $sth->fetchrow_array;
}
# do deletes
if (defined $del) {
remove("general", $del)
if delete $existing_item{$l->{'lnid'}}->{$del};
next;
}
# if override is set (development option) then delete
if ($opt_override && $existing_item{$l->{'lnid'}}->{$code}) {
remove("general", $code);
delete $existing_item{$l->{'lnid'}}->{$code};
}
unless ($existing_item{$l->{'lnid'}}->{$code}) {
$addcount++;
my $staleness = $metadata{'staleness'}+0;
my $res = LJ::Lang::set_text($dbh, 1, $l->{'lncode'}, $code, $text,
{ 'staleness' => $staleness,
'notes' => $metadata{'notes'}, });
$out->("set: $code") if $opt_verbose;
unless ($res) {
$out->('x', "ERROR: " . LJ::Lang::last_error());
}
}
%metadata = ();
}
close D;
$out->("added: $addcount", '-');
}
$out->("-", "done.");
# dead phrase removal
$out->("Removing dead phrases...", '+');
foreach my $file ("deadphrases.dat", "deadphrases-local.dat") {
my $ffile = "$ENV{'LJHOME'}/bin/upgrading/$file";
next unless -s $ffile;
$out->("File: $file");
open (DP, $ffile) or die;
while (my $li = <DP>) {
$li =~ s/\#.*//;
next unless $li =~ /\S/;
$li =~ s/\s+$//;
my ($dom, $it) = split(/\s+/, $li);
next unless exists $dom_code{$dom};
my $dmid = $dom_code{$dom}->{'dmid'};
my @items;
if ($it =~ s/\*$/\%/) {
my $sth = $dbh->prepare("SELECT itcode FROM ml_items WHERE dmid=? AND itcode LIKE ?");
$sth->execute($dmid, $it);
push @items, $_ while $_ = $sth->fetchrow_array;
} else {
@items = ($it);
}
foreach (@items) {
remove($dom, $_, 1);
}
}
close DP;
}
$out->('-', "Done.");
}
sub dumptext
{
my @langs = @_;
unless (@langs) { @langs = keys %lang_code; }
$out->('Dumping text...', '+');
foreach my $lang (@langs)
{
$out->("$lang");
my $l = $lang_code{$lang};
open (D, ">$ENV{'LJHOME'}/bin/upgrading/${lang}.dat")
or $out->('x', "Can't open $lang.dat");
print D ";; -*- coding: utf-8 -*-\n";
my $sth = $dbh->prepare("SELECT i.itcode, t.text, l.staleness, i.notes FROM ".
"ml_items i, ml_latest l, ml_text t ".
"WHERE l.lnid=$l->{'lnid'} AND l.dmid=1 ".
"AND i.dmid=1 AND l.itid=i.itid AND ".
"t.dmid=1 AND t.txtid=l.txtid AND ".
# only export mappings that aren't inherited:
"t.lnid=$l->{'lnid'} ".
"ORDER BY i.itcode");
$sth->execute;
die $dbh->errstr if $dbh->err;
my $writeline = sub {
my ($k, $v) = @_;
if ($v =~ /\n/) {
$v =~ s/\n\./\n\.\./g;
print D "$k<<\n$v\n.\n";
} else {
print D "$k=$v\n";
}
};
while (my ($itcode, $text, $staleness, $notes) = $sth->fetchrow_array) {
$writeline->("$itcode|staleness", $staleness)
if $staleness;
$writeline->("$itcode|notes", $notes)
if $notes =~ /\S/;
$writeline->($itcode, $text);
print D "\n";
}
close D;
}
$out->('-', 'done.');
}
sub newitems
{
$out->("Searching for referenced text codes...", '+');
my $top = $ENV{'LJHOME'};
my %overrides;
if (open (O, "$top/bin/upgrading/texttool-overrides")) {
while (<O>) {
my $l = $_;
if ($l !~ /^#/ && $l !~ /^[\s]*$/) {
$l =~ s/[\r\n]//;
my @a = split ,$l;
$overrides{$a[0]} = $a[1];
}
}
close O;
}
my @files;
push @files, qw(htdocs cgi-bin bin);
my %items; # $scope -> $key -> 1;
while (@files)
{
my $file = shift @files;
my $ffile = "$top/$file";
next unless -e $ffile;
if (-d $ffile) {
$out->("dir: $file") if $opt_verbose;
opendir (MD, $ffile) or die "Can't open $file";
while (my $f = readdir(MD)) {
next if $f eq "." || $f eq ".." ||
$f =~ /^\.\#/ || $f =~ /(\.png|\.gif|~|\#)$/;
unshift @files, "$file/$f";
}
closedir MD;
}
if (-f $ffile) {
my $scope = "general";
# $scope = "general" if -e "$top/cvs/livejournal/$file";
open (F, $ffile) or die "Can't open $file";
my $line = 0;
my $correct_code = sub {
my ($code, $file) = @_;
if ($code =~ /^\./ && $file =~ m!^htdocs/!) {
$code = "$file$code";
$code =~ s!^htdocs!!;
}
if ($overrides{$code}) {
$code = $overrides{$code};
}
return $code;
};
my $valid_code = sub {
my ($code, $file) = @_;
if ($code =~ /\$/ || $file eq "bin/upgrading/texttool.pl") {
print STDERR "SKIPPING: $file [$code]\n";
return 0;
}
return 1;
};
while (<F>) {
$line++;
if (/^#/) {
next;
}
while (/BML::ml\([\"\'](.+?)[\"\']/g) {
my $code = $1;
$code = $correct_code->($code, $file);
$out->("BML::ml: $file $code") if $opt_verbose;
$items{$scope}->{$code} = 1 if $valid_code->($code, $file);
}
while (/\(=_ML\s+(.+?)\s+_ML=\)/g) {
my $code = $1;
$code = $correct_code->($code, $file);
$out->("_ML: $code") if $opt_verbose;
$items{$scope}->{$code} = 1 if $valid_code->($code, $file);
}
while (/\$ML{'(.+?)'}/g) {
my $code = $1;
$code = $correct_code->($code, $file);
$out->("\$ML: $file $code") if $opt_verbose;
$items{$scope}->{$code} = 1 if $valid_code->($code, $file);
}
}
close F;
}
}
$out->(sprintf("%d general and %d local found.",
scalar keys %{$items{'general'}},
scalar keys %{$items{'local'}}));
# [ General ]
my %e_general; # code -> 1
$out->("Checking which general items already exist in database...");
my $sth = $dbh->prepare("SELECT i.itcode FROM ml_items i, ml_latest l WHERE ".
"l.dmid=1 AND l.lnid=1 AND i.dmid=1 AND i.itid=l.itid ");
$sth->execute;
while (my $it = $sth->fetchrow_array) { $e_general{$it} = 1; }
$out->(sprintf("%d found", scalar keys %e_general));
foreach my $it (keys %{$items{'general'}}) {
next if exists $e_general{$it};
if (@additems && grep(/^$it$/, @additems)) {
if ($opt_do) {
my $res = LJ::Lang::set_text($dbh, 1, "en", $it, undef, { 'staleness' => 4 });
$out->("Adding general: $it ... $res");
}
else {
$out->("Would add general: $it");
}
}
else {
$out->("Skipped: $it");
}
}
if ($opt_local_lang) {
my $ll = $lang_code{$opt_local_lang};
die "Bogus --local-lang argument\n" unless $ll;
die "Local-lang '$ll->{'lncode'}' parent isn't 'en'\n"
unless $ll->{'parentlnid'} == 1;
$out->("Checking which local items already exist in database...");
my %e_local;
$sth = $dbh->prepare("SELECT i.itcode FROM ml_items i, ml_latest l WHERE ".
"l.dmid=1 AND l.lnid=$ll->{'lnid'} AND i.dmid=1 AND i.itid=l.itid ");
$sth->execute;
while (my $it = $sth->fetchrow_array) { $e_local{$it} = 1; }
$out->(sprintf("%d found\n", scalar keys %e_local));
foreach my $it (keys %{$items{'local'}}) {
next if exists $e_general{$it};
next if exists $e_local{$it};
my $res = LJ::Lang::set_text($dbh, 1, $ll->{'lncode'}, $it, undef, { 'staleness' => 4 });
$out->("Adding local: $it ... $res");
}
}
$out->('-', 'done.');
}
sub remove {
my ($dmcode, $itcode, $no_error) = @_;
my $dmid;
if (exists $dom_code{$dmcode}) {
$dmid = $dom_code{$dmcode}->{'dmid'};
} else {
$out->("x", "Unknown domain code $dmcode.");
}
my $qcode = $dbh->quote($itcode);
my $itid = $dbh->selectrow_array("SELECT itid FROM ml_items WHERE dmid=$dmid AND itcode=$qcode");
return if $no_error && !$itid;
$out->("x", "Unknown item code $itcode.") unless $itid;
$out->("Removing item $itcode from domain $dmcode ($itid)...", "+");
# need to delete everything from: ml_items ml_latest ml_text
$dbh->do("DELETE FROM ml_items WHERE dmid=$dmid AND itid=$itid");
my $txtids = "";
my $sth = $dbh->prepare("SELECT txtid FROM ml_latest WHERE dmid=$dmid AND itid=$itid");
$sth->execute;
while (my $txtid = $sth->fetchrow_array) {
$txtids .= "," if $txtids;
$txtids .= $txtid;
}
$dbh->do("DELETE FROM ml_latest WHERE dmid=$dmid AND itid=$itid");
$dbh->do("DELETE FROM ml_text WHERE dmid=$dmid AND txtid IN ($txtids)");
$out->("-","done.");
}

15252
local/bin/upgrading/uk.dat Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff