init
7
livejournal/Inline/README.txt
Executable file
@@ -0,0 +1,7 @@
|
||||
This is a dummy file because we need to make this directory here.
|
||||
|
||||
This is where the optional LiveJournal Inline.pm C code compiles and
|
||||
installs.
|
||||
|
||||
To populate this directory, make sure you have a C compiler installed
|
||||
and then run $LJHOME/bin/lj-inline.pl
|
||||
1
livejournal/README.txt
Executable file
@@ -0,0 +1 @@
|
||||
Read this: http://www.livejournal.com/doc/server/
|
||||
93
livejournal/bin/api2html.pl
Executable file
@@ -0,0 +1,93 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
|
||||
use strict;
|
||||
|
||||
unless (-d $ENV{'LJHOME'}) {
|
||||
die "\$LJHOME not set.\n";
|
||||
}
|
||||
chdir $ENV{'LJHOME'} or die "Can't cd to $ENV{'LJOME'}\n";
|
||||
|
||||
### apidoc.pl does all the hard work.
|
||||
my $VAR1;
|
||||
eval `bin/apidoc.pl`;
|
||||
my $api = $VAR1;
|
||||
|
||||
print "<html>\n";
|
||||
print "<head><title>LiveJournal API Documentation</title></head>\n";
|
||||
print "<body>\n";
|
||||
print "<h1>LiveJournal API Documentation</h1>\n";
|
||||
|
||||
## print list
|
||||
print "<h2>Alphabetic List of Functions</h2>\n";
|
||||
print "<ul>\n";
|
||||
foreach my $func (sort keys %$api) {
|
||||
print "<li><a href=\"#$func\"><tt>$func</tt></a></li>\n";
|
||||
}
|
||||
print "</ul>\n";
|
||||
|
||||
## print each function
|
||||
print "<h2>Function Descriptions</h2>\n";
|
||||
foreach my $func (sort keys %$api) {
|
||||
my $f = $api->{$func};
|
||||
my $argstring;
|
||||
xlinkify(\$f->{'des'});
|
||||
|
||||
my $optcount;
|
||||
foreach my $arg (@{$f->{'args'}}) {
|
||||
my $comma = $argstring ? ", " : "";
|
||||
my $lbrack = "";
|
||||
if ($arg->{'optional'}) {
|
||||
$optcount++;
|
||||
$lbrack = "["
|
||||
}
|
||||
$argstring .= "$lbrack$comma$arg->{'name'}";
|
||||
if ($arg->{'list'}) {
|
||||
$argstring .= "*";
|
||||
}
|
||||
}
|
||||
$argstring .= "]"x$optcount;
|
||||
|
||||
print "<a name=\"$func\">\n";
|
||||
print "<h3><tt>$func</tt></h3>\n";
|
||||
print "<blockquote><table>\n";
|
||||
|
||||
print "<tr valign=\"top\"><td align=\"right\"><i>Description:</i></td>\n";
|
||||
print "<td>$f->{'des'}</td></tr>\n";
|
||||
|
||||
print "<tr valign=\"bottom\"><td align=\"right\"><i>Source:</i></td>\n";
|
||||
print "<td><tt>$f->{'source'}</tt></td></tr>\n";
|
||||
|
||||
if (@{$f->{'args'}}) {
|
||||
print "<tr valign=\"bottom\"><td align=\"right\"><i>Arguments:</i></td>\n";
|
||||
print "<td><tt><b>$argstring</b></tt></td></tr>\n";
|
||||
|
||||
print "<tr valign=\"bottom\"><td> </td>\n";
|
||||
print "<td><table cellpadding=\"2\" border=\"1\">\n";
|
||||
foreach my $arg (@{$f->{'args'}}) {
|
||||
print "<tr valign=\"top\"><td>$arg->{'name'}</td>";
|
||||
my $des = $arg->{'des'};
|
||||
xlinkify(\$des);
|
||||
print "<td>$des</td></tr>\n";
|
||||
}
|
||||
print "</table></td></tr>\n";
|
||||
}
|
||||
|
||||
if ($f->{'returns'}) {
|
||||
xlinkify(\$f->{'returns'});
|
||||
print "<tr valign=\"top\"><td align=\"right\"><i>Returns:</i></td>\n";
|
||||
print "<td>$f->{'returns'}</td></tr>\n";
|
||||
}
|
||||
|
||||
print "</table></blockquote>\n";
|
||||
print "</a><hr>\n";
|
||||
}
|
||||
|
||||
|
||||
print "</body>\n";
|
||||
print "</html>\n";
|
||||
|
||||
sub xlinkify {
|
||||
my $a = shift;
|
||||
$$a =~ s/\[func\[([^\]]*)]\]/<tt><a href=\"\#$1\">$1<\/a><\/tt>/g;
|
||||
}
|
||||
195
livejournal/bin/checkconfig.pl
Executable file
@@ -0,0 +1,195 @@
|
||||
#!/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",
|
||||
"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 "[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";
|
||||
|
||||
|
||||
15
livejournal/bin/cvsreport.pl
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# This is now just a wrapper around the non-LJ-specific multicvs.pl
|
||||
#
|
||||
|
||||
unless (-d $ENV{'LJHOME'}) {
|
||||
die "\$LJHOME not set.\n";
|
||||
}
|
||||
|
||||
# strip off paths beginning with LJHOME
|
||||
# (useful if you tab-complete filenames)
|
||||
$_ =~ s!\Q$ENV{'LJHOME'}\E/?!! foreach (@ARGV);
|
||||
|
||||
exit system("$ENV{'LJHOME'}/bin/multicvs.pl",
|
||||
"--conf=$ENV{'LJHOME'}/cvs/multicvs.conf", @ARGV);
|
||||
339
livejournal/bin/dbcheck.pl
Executable file
@@ -0,0 +1,339 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
|
||||
use strict;
|
||||
use DBI;
|
||||
use Getopt::Long;
|
||||
|
||||
my $help = 0;
|
||||
my $opt_fh = 0;
|
||||
my $opt_fix = 0;
|
||||
my $opt_start = 0;
|
||||
my $opt_stop = 0;
|
||||
my $opt_err = 0;
|
||||
my $opt_all = 0;
|
||||
my $opt_tablestatus;
|
||||
my $opt_checkreport = 0;
|
||||
my $opt_rates;
|
||||
my @opt_run;
|
||||
exit 1 unless GetOptions('help' => \$help,
|
||||
'flushhosts' => \$opt_fh,
|
||||
'start' => \$opt_start,
|
||||
'stop' => \$opt_stop,
|
||||
'checkreport' => \$opt_checkreport,
|
||||
'rates' => \$opt_rates,
|
||||
'fix' => \$opt_fix,
|
||||
'run=s' => \@opt_run,
|
||||
'onlyerrors' => \$opt_err,
|
||||
'all' => \$opt_all,
|
||||
'tablestatus' => \$opt_tablestatus,
|
||||
);
|
||||
|
||||
unless (-d $ENV{'LJHOME'}) {
|
||||
die "\$LJHOME not set.\n";
|
||||
}
|
||||
|
||||
if ($help) {
|
||||
die ("Usage: dbcheck.pl [opts] [[cmd] args...]\n" .
|
||||
" --all Check all hosts, even those with no weight assigned.\n" .
|
||||
" --help Get this help\n" .
|
||||
" --flushhosts Send 'FLUSH HOSTS' to each db as root.\n".
|
||||
" --fix Fix (once) common problems.\n".
|
||||
" --checkreport Show tables that haven't been checked in a while.\n".
|
||||
" --stop Stop replication.\n".
|
||||
" --start Start replication.\n".
|
||||
" --run <sql> Run arbitrary SQL.\n".
|
||||
" --onlyerrors Will be silent unless there are errors.\n".
|
||||
" --tablestatus Show warnings about full/sparse tables.\n".
|
||||
"\n".
|
||||
"Commands\n".
|
||||
" (none) Shows replication status.\n".
|
||||
" queries <host> Shows active queries on host, sorted by running time.\n"
|
||||
);
|
||||
}
|
||||
|
||||
require "$ENV{'LJHOME'}/cgi-bin/ljdb.pl";
|
||||
|
||||
my $dbh = LJ::DB::dbh_by_role("master");
|
||||
die "Can't get master db handle\n" unless $dbh;
|
||||
|
||||
my %dbinfo; # dbid -> hashref
|
||||
my %name2id; # name -> dbid
|
||||
my $sth;
|
||||
my $masterid = 0;
|
||||
|
||||
my %subclust; # id -> name of parent (pork-85 -> "pork")
|
||||
|
||||
$sth = $dbh->prepare("SELECT dbid, name, masterid, rootfdsn FROM dbinfo");
|
||||
$sth->execute;
|
||||
while ($_ = $sth->fetchrow_hashref) {
|
||||
if ($_->{name} =~ /(.+)\-\d\d$/) {
|
||||
$subclust{$_->{dbid}} = $1;
|
||||
next;
|
||||
}
|
||||
next unless $_->{'dbid'};
|
||||
$dbinfo{$_->{'dbid'}} = $_;
|
||||
$name2id{$_->{'name'}} = $_->{'dbid'};
|
||||
}
|
||||
|
||||
my %role; # rolename -> dbid -> [ norm, curr ]
|
||||
my %rolebyid; # dbid -> rolename -> [ norm, curr ]
|
||||
$sth = $dbh->prepare("SELECT dbid, role, norm, curr FROM dbweights");
|
||||
$sth->execute;
|
||||
while ($_ = $sth->fetchrow_hashref) {
|
||||
my $id = $_->{dbid};
|
||||
if ($subclust{$id}) {
|
||||
$id = $name2id{$subclust{$id}};
|
||||
}
|
||||
next unless defined $dbinfo{$id};
|
||||
$dbinfo{$id}->{'totalweight'} += $_->{'curr'};
|
||||
$role{$_->{role}}->{$id} = [ $_->{norm}, $_->{curr} ];
|
||||
$rolebyid{$id}->{$_->{role}} = [ $_->{norm}, $_->{curr} ];
|
||||
}
|
||||
|
||||
check_report() if $opt_checkreport;
|
||||
rate_report() if $opt_rates;
|
||||
|
||||
my @errors;
|
||||
my %master_status; # dbid -> [ $file, $pos ]
|
||||
|
||||
my $check_master_status = sub {
|
||||
my $dbid = shift;
|
||||
my $d = $dbinfo{$dbid};
|
||||
die "Bogus DB: $dbid" unless $d;
|
||||
my $db = LJ::DB::root_dbh_by_name($d->{name});
|
||||
next unless $db;
|
||||
|
||||
my ($masterfile, $masterpos) = $db->selectrow_array("SHOW MASTER STATUS");
|
||||
$master_status{$dbid} = [ $masterfile, $masterpos ];
|
||||
};
|
||||
|
||||
my $check = sub {
|
||||
my $dbid = shift;
|
||||
my $d = $dbinfo{$dbid};
|
||||
die "Bogus DB: $dbid" unless $d;
|
||||
|
||||
# calculate roles to show
|
||||
my $roles;
|
||||
{
|
||||
my %drole; # display role -> 1
|
||||
foreach my $role (grep { $role{$_}{$dbid}[1] } keys %{$rolebyid{$dbid}}) {
|
||||
my $drole = $role;
|
||||
$drole =~ s/cluster(\d+)\d/cluster${1}0/;
|
||||
$drole{$drole} = 1;
|
||||
}
|
||||
$roles = join(", ", sort keys %drole);
|
||||
}
|
||||
|
||||
my $db = LJ::DB::root_dbh_by_name($d->{name});
|
||||
unless ($db) {
|
||||
printf("%4d %-15s %4s %16s %14s ($roles)\n",
|
||||
$dbid,
|
||||
$d->{name},
|
||||
$d->{masterid} ? $d->{masterid} : "",
|
||||
) unless $opt_err;
|
||||
push @errors, "Can't connect to $d->{'name'}";
|
||||
return 0;
|
||||
}
|
||||
|
||||
my $tzone;
|
||||
(undef, $tzone) = $db->selectrow_array("show variables like 'timezone'");
|
||||
|
||||
$sth = $db->prepare("SHOW PROCESSLIST");
|
||||
$sth->execute;
|
||||
my $pcount_total = 0;
|
||||
my $pcount_busy = 0;
|
||||
while (my $r = $sth->fetchrow_hashref) {
|
||||
next if $r->{'State'} =~ /waiting for/i;
|
||||
next if $r->{'State'} eq "Reading master update";
|
||||
next if $r->{'State'} =~ /^(Has (sent|read) all)|(Sending binlog)/;
|
||||
$pcount_total++;
|
||||
$pcount_busy++ if $r->{'State'};
|
||||
}
|
||||
|
||||
my @master_logs;
|
||||
my $log_count = 0;
|
||||
if ($master_status{$dbid} && $master_status{$dbid}->[1]) {
|
||||
$sth = $db->prepare("SHOW MASTER LOGS");
|
||||
$sth->execute;
|
||||
while (my ($log) = $sth->fetchrow_array) {
|
||||
push @master_logs, $log;
|
||||
$log_count++;
|
||||
}
|
||||
}
|
||||
|
||||
my $ss = $db->selectrow_hashref("show slave status");
|
||||
if ($ss) {
|
||||
foreach my $k (sort keys %$ss) {
|
||||
$ss->{lc $k} = $ss->{$k};
|
||||
}
|
||||
}
|
||||
|
||||
my $diff;
|
||||
if ($ss) {
|
||||
if ($ss->{'slave_io_running'} eq "Yes" && $ss->{'slave_sql_running'} eq "Yes") {
|
||||
if ($ss->{'master_log_file'} eq $ss->{'relay_master_log_file'}) {
|
||||
$diff = $ss->{'read_master_log_pos'} - $ss->{'exec_master_log_pos'};
|
||||
} else {
|
||||
$diff = "XXXXXXX";
|
||||
push @errors, "Wrong log file: $d->{name}";
|
||||
}
|
||||
} else {
|
||||
$diff = "XXXXXXX";
|
||||
$ss->{last_error} =~ s/[^\n\r\t\x20-\x7e]//g;
|
||||
push @errors, "Slave not running: $d->{name}: $ss->{last_error}";
|
||||
}
|
||||
|
||||
my $ms = $master_status{$d->{masterid}} || [];
|
||||
#print " master: [@$ms], slave at: [$ss->{master_log_file}, $ss->{read_master_log_pos}]\n";
|
||||
if ($ss->{master_log_file} ne $ms->[0] || $ss->{read_master_log_pos} < $ms->[1] - 20_000) {
|
||||
push @errors, "$d->{name}: Relay log behind: master=[@$ms], $d->{name}=[$ss->{master_log_file}, $ss->{read_master_log_pos}]";
|
||||
}
|
||||
|
||||
} else {
|
||||
$diff = "-"; # not applicable
|
||||
}
|
||||
|
||||
#print "$dbid of $d->{masterid}: $d->{name} ($roles)\n";
|
||||
printf("%4d %-15s %4s repl:%7s %4s conn:%4d/%4d $tzone ($roles)\n",
|
||||
$dbid,
|
||||
$d->{name},
|
||||
$d->{masterid} ? $d->{masterid} : "",
|
||||
$diff,
|
||||
$log_count ? sprintf("<%2s>", $log_count) : "",
|
||||
$pcount_busy, $pcount_total) unless $opt_err;
|
||||
};
|
||||
|
||||
$check_master_status->($_) foreach (sorted_dbids());
|
||||
|
||||
$check->($_) foreach (sorted_dbids());
|
||||
|
||||
if (@errors) {
|
||||
if ($opt_err) {
|
||||
my %ignore;
|
||||
open(EX, "$ENV{'HOME'}/.dbcheck.ignore");
|
||||
while (<EX>) {
|
||||
s/\s+$//;
|
||||
$ignore{$_} = 1;
|
||||
}
|
||||
close EX;
|
||||
@errors = grep { ! $ignore{$_} } @errors;
|
||||
}
|
||||
print STDERR "\nERRORS:\n" if @errors;
|
||||
foreach (@errors) {
|
||||
print STDERR " * $_\n";
|
||||
}
|
||||
}
|
||||
|
||||
my $sorted_cache;
|
||||
sub sorted_dbids {
|
||||
return @$sorted_cache if $sorted_cache;
|
||||
$sorted_cache = [ _sorted_dbids() ];
|
||||
return @$sorted_cache;
|
||||
}
|
||||
|
||||
sub _sorted_dbids {
|
||||
my @ids;
|
||||
my %added; # dbid -> 1
|
||||
|
||||
my $add = sub {
|
||||
my $dbid = shift;
|
||||
$added{$dbid} = 1;
|
||||
push @ids, $dbid;
|
||||
};
|
||||
|
||||
my $masterid = (keys %{$role{'master'}})[0];
|
||||
$add->($masterid);
|
||||
|
||||
# then slaves
|
||||
foreach my $id (sort { $dbinfo{$a}->{name} cmp $dbinfo{$b}->{name} }
|
||||
grep { ! $added{$_} && $rolebyid{$_}->{slave} } keys %dbinfo) {
|
||||
$add->($id);
|
||||
}
|
||||
|
||||
# now, figure out which remaining are associated with cluster roles (user clusters)
|
||||
my %minclust; # dbid -> minimum cluster number associated
|
||||
my %is_master; # dbid -> bool (is cluster master)
|
||||
foreach my $dbid (grep { ! $added{$_} } keys %dbinfo) {
|
||||
foreach my $role (keys %{ $rolebyid{$dbid} || {} }) {
|
||||
next unless $role =~ /^cluster(\d+)(.*)/;
|
||||
$minclust{$dbid} = $1 if ! $minclust{$dbid} || $1 < $minclust{$dbid};
|
||||
$is_master{$dbid} ||= $2 eq "" || $2 eq "a" || $2 eq "b";
|
||||
}
|
||||
}
|
||||
|
||||
# then misc
|
||||
foreach my $id (sort { $dbinfo{$a}->{name} cmp $dbinfo{$b}->{name} }
|
||||
grep { ! $added{$_} && ! $minclust{$_} } keys %dbinfo) {
|
||||
$add->($id);
|
||||
}
|
||||
|
||||
|
||||
# then clusters, in order
|
||||
foreach my $id (sort { $minclust{$a} <=> $minclust{$b} ||
|
||||
$is_master{$b} <=> $is_master{$a} }
|
||||
grep { ! $added{$_} && $minclust{$_} } keys %dbinfo) {
|
||||
$add->($id);
|
||||
}
|
||||
return @ids;
|
||||
}
|
||||
|
||||
sub check_report {
|
||||
foreach my $dbid (sort { $dbinfo{$a}->{name} cmp $dbinfo{$b}->{name} }
|
||||
keys %dbinfo) {
|
||||
my $d = $dbinfo{$dbid};
|
||||
die "Bogus DB: $dbid" unless $d;
|
||||
my $db = LJ::DB::root_dbh_by_name($d->{name});
|
||||
|
||||
unless ($db) {
|
||||
print "$d->{name}\t?\t?\t?\n";
|
||||
next;
|
||||
}
|
||||
|
||||
my $dbs = $db->selectcol_arrayref("SHOW DATABASES");
|
||||
foreach my $dbname (@$dbs) {
|
||||
$db->do("USE $dbname");
|
||||
my $ts = $db->selectall_hashref("SHOW TABLE STATUS", "Name");
|
||||
foreach my $tn (sort keys %$ts) {
|
||||
my $v = $ts->{$tn};
|
||||
my $ut = $v->{Check_time} || "0000-00-00 00:00:00";
|
||||
$ut =~ s/ /,/;
|
||||
print "$d->{name}\t$dbname\t$tn\t$ut\t$v->{Type}-$v->{Row_format}\t$v->{Rows}\n";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
exit 0;
|
||||
}
|
||||
|
||||
use Time::HiRes ();
|
||||
|
||||
sub rate_report {
|
||||
my %prev; # dbid -> [ time, questions ]
|
||||
|
||||
while (1) {
|
||||
print "\n";
|
||||
my $sum = 0;
|
||||
foreach my $dbid (sorted_dbids()) {
|
||||
my $d = $dbinfo{$dbid};
|
||||
die "Bogus DB: $dbid" unless $d;
|
||||
my $db = LJ::DB::root_dbh_by_name($d->{name});
|
||||
|
||||
next unless $db;
|
||||
my (undef, $qs) = $db->selectrow_array("SHOW STATUS LIKE 'Questions'");
|
||||
my $now = Time::HiRes::time();
|
||||
my $cur = [ $now, $qs ];
|
||||
if (my $old = $prev{$dbid}) {
|
||||
my $dt = $now - $old->[0];
|
||||
my $qnew = $qs - $old->[1];
|
||||
my $rate = ($qnew / $dt);
|
||||
$sum += $rate;
|
||||
printf "%20s: %7.01f q/s\n", $d->{name}, $rate;
|
||||
}
|
||||
$prev{$dbid} ||= $cur;
|
||||
}
|
||||
printf "%20s: %7.01f q/s\n", "SUM", $sum;
|
||||
|
||||
sleep 1;
|
||||
}
|
||||
}
|
||||
392
livejournal/bin/dbselectd.pl
Executable file
@@ -0,0 +1,392 @@
|
||||
#!/usr/bin/perl -w
|
||||
#
|
||||
# DB selector daemon. Returns connect information on a preferred DB
|
||||
# to a requestor.
|
||||
#
|
||||
# <LJDEP>
|
||||
# lib: Getopt::Long, POSIX::, IO::Socket, IO::Select, Socket::, Fcntl::, DBI::
|
||||
# lib: cgi-bin/ljconfig.pl
|
||||
# </LJDEP>
|
||||
|
||||
use Getopt::Long;
|
||||
use POSIX;
|
||||
use IO::Socket;
|
||||
use IO::Select;
|
||||
use strict;
|
||||
use Socket;
|
||||
use Fcntl;
|
||||
use DBI;
|
||||
|
||||
my $PORT = 5151;
|
||||
my $PIDFILE = "$ENV{'LJHOME'}/var/dbselectd.pid";
|
||||
|
||||
my $SELECT_DELAY = 0.3;
|
||||
|
||||
# temporary:
|
||||
my $DBINFO_FILE = "$ENV{'LJHOME'}/cgi-bin/ljconfig.pl";
|
||||
my $opt_foreground = 0;
|
||||
GetOptions("foreground" => \$opt_foreground);
|
||||
|
||||
my $pid;
|
||||
|
||||
# statistics on known databases
|
||||
my %db_lastcheck;
|
||||
my %db_conncount;
|
||||
my $conf_modtime = 0;
|
||||
my $conf_stattime = 0;
|
||||
|
||||
# Buffers.
|
||||
my %inbuffer = ();
|
||||
my %outbuffer = ();
|
||||
my %cmd = ();
|
||||
my %clientinfo = ();
|
||||
|
||||
sub connect_to
|
||||
{
|
||||
my $svr = shift;
|
||||
my $dbh;
|
||||
|
||||
if (ref $LJ::DBCACHE{$svr})
|
||||
{
|
||||
$dbh = $LJ::DBCACHE{$svr};
|
||||
|
||||
# make sure connection is still good.
|
||||
my $sth = $dbh->prepare("SELECT CONNECTION_ID()"); # mysql specific
|
||||
$sth->execute;
|
||||
my ($id) = $sth->fetchrow_array;
|
||||
if ($id) { return $dbh; }
|
||||
undef $dbh;
|
||||
undef $LJ::DBCACHE{$svr};
|
||||
}
|
||||
|
||||
my $dbname = $LJ::DBINFO{$svr}->{'dbname'} || "livejournal";
|
||||
$dbh = DBI->connect("DBI:mysql:$dbname:$LJ::DBINFO{$svr}->{'host'}",
|
||||
$LJ::DBINFO{$svr}->{'user'},
|
||||
$LJ::DBINFO{$svr}->{'pass'},
|
||||
{
|
||||
PrintError => 0,
|
||||
});
|
||||
if ($dbh)
|
||||
{
|
||||
$LJ::DBCACHE{$svr} = $dbh;
|
||||
return $dbh;
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
sub db_can
|
||||
{
|
||||
my $svr = shift;
|
||||
my $cap = shift;
|
||||
return $LJ::DBINFO{$svr}->{'role'}->{$cap};
|
||||
}
|
||||
|
||||
sub check_server
|
||||
{
|
||||
my $svr = shift;
|
||||
delete $db_conncount{$svr};
|
||||
delete $db_lastcheck{$svr};
|
||||
|
||||
my $dbh = connect_to($svr);
|
||||
return unless (defined $dbh);
|
||||
|
||||
my $sth = $dbh->prepare("SHOW PROCESSLIST");
|
||||
$sth->execute;
|
||||
my $ct = 0;
|
||||
while (my $r = $sth->fetchrow_hashref)
|
||||
{
|
||||
# weight busy connections more than idle ones.
|
||||
if ($r->{'State'}) { $ct += 2; }
|
||||
else { $ct += 1; }
|
||||
}
|
||||
$db_conncount{$svr} = $ct;
|
||||
$db_lastcheck{$svr} = time();
|
||||
}
|
||||
|
||||
sub connection_load
|
||||
{
|
||||
my $svr = shift;
|
||||
my $time = time();
|
||||
if (! defined $db_lastcheck{$svr} ||
|
||||
$time - $db_lastcheck{$svr} > 10)
|
||||
{
|
||||
check_server($svr);
|
||||
}
|
||||
return $db_conncount{$svr};
|
||||
}
|
||||
|
||||
sub server_power
|
||||
{
|
||||
my $svr = shift;
|
||||
my $cap = shift;
|
||||
|
||||
my $weight = $LJ::DBINFO{$svr}->{'role'}->{$cap} || 1;
|
||||
my $connections = connection_load($svr);
|
||||
if (defined $connections) {
|
||||
$connections ||= 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return ($weight / $connections);
|
||||
}
|
||||
|
||||
sub use_what
|
||||
{
|
||||
my $c = shift;
|
||||
my $cap = shift;
|
||||
|
||||
## reload the DB info file if it's been more than 5 seconds since
|
||||
## its last stat time and if it's changed since what we remember.
|
||||
my $time = time();
|
||||
if ($conf_stattime + 5 < $time)
|
||||
{
|
||||
my $modtime = (stat($DBINFO_FILE))[9];
|
||||
if ($modtime > $conf_modtime) {
|
||||
delete $INC{$DBINFO_FILE};
|
||||
require $DBINFO_FILE;
|
||||
$conf_modtime = $modtime;
|
||||
$conf_stattime = $time;
|
||||
}
|
||||
}
|
||||
|
||||
my %cand = (); # candidates
|
||||
|
||||
# best candidate is one the client is already connected to
|
||||
foreach my $svr (keys %{$c->{'has'}}) {
|
||||
if (db_can($svr, $cap)) {
|
||||
$cand{$svr} = 1;
|
||||
}
|
||||
}
|
||||
|
||||
# if not connected to anything suitable, then:
|
||||
unless (%cand)
|
||||
{
|
||||
# every db with that capability is a good candidate
|
||||
foreach my $svr (keys %LJ::DBINFO) {
|
||||
if (db_can($svr, $cap)) {
|
||||
$cand{$svr} = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my @cands = keys %cand;
|
||||
|
||||
# sort valid candidates by server's connections
|
||||
my %power;
|
||||
foreach (@cands) {
|
||||
$power{$_} = server_power($_, $cap);
|
||||
}
|
||||
@cands = sort { $power{$b} <=> $power{$a} } @cands;
|
||||
|
||||
# use the one with the highest score:
|
||||
my $use = $cands[0];
|
||||
if ($use) {
|
||||
unless (defined $LJ::DBINFO{$use}->{'dbname'}) {
|
||||
$LJ::DBINFO{$use}->{'dbname'} = "livejournal";
|
||||
}
|
||||
return join(" ", $use, map { $LJ::DBINFO{$use}->{$_} } qw(host user pass dbname));
|
||||
} else {
|
||||
return "--";
|
||||
}
|
||||
}
|
||||
|
||||
sub handle
|
||||
{
|
||||
my $select = shift;
|
||||
my $client = shift;
|
||||
my $line = shift;
|
||||
my $c = ($clientinfo{$client} ||= {});
|
||||
my $out = \$outbuffer{$client};
|
||||
|
||||
$line =~ s/^(\S*)\s*//;
|
||||
my $cmd = $1;
|
||||
|
||||
if ($cmd eq "HAVE") {
|
||||
foreach (split(/,/, $line)) {
|
||||
next if ($_ eq "master");
|
||||
$c->{'has'}->{$_} = 1;
|
||||
}
|
||||
$$out = "OK\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if ($cmd eq "NEED") {
|
||||
my $cap = $line;
|
||||
my $use = use_what($c, $cap);
|
||||
$$out = "USE $use\n";
|
||||
return;
|
||||
}
|
||||
|
||||
if ($cmd eq "STATS") {
|
||||
my $svr = $line;
|
||||
$$out = "Stats follow:\n";
|
||||
foreach my $s (keys %LJ::DBINFO) {
|
||||
$$out .= "STATS $s = " . connection_load($s) . "\n";
|
||||
}
|
||||
$$out .= "End.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$$out = "unknown command.\n";
|
||||
}
|
||||
|
||||
# Server crap is below.
|
||||
|
||||
$SIG{'TERM'} = sub {
|
||||
unlink($PIDFILE);
|
||||
exit 1;
|
||||
};
|
||||
|
||||
if (-e $PIDFILE) {
|
||||
print "$PIDFILE exists, quitting.\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
sub write_pid
|
||||
{
|
||||
my $p = shift;
|
||||
open(PID, ">$PIDFILE") or die "Couldn't open $PIDFILE for writing: $!\n";
|
||||
print PID $p;
|
||||
close(PID);
|
||||
}
|
||||
|
||||
if ($opt_foreground) {
|
||||
print "Running in foreground...\n";
|
||||
$pid = $$;
|
||||
write_pid($pid);
|
||||
$SIG{'INT'} = sub {
|
||||
unlink($PIDFILE);
|
||||
exit 1;
|
||||
};
|
||||
} else {
|
||||
print "Forking off and initializing...\n";
|
||||
if ($pid = fork) {
|
||||
# Parent, log pid and exit.
|
||||
write_pid($pid);
|
||||
print "Closing ($pid) wrote to $PIDFILE\n";
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
sub killpid_die
|
||||
{
|
||||
my $msg = shift;
|
||||
unlink $PIDFILE;
|
||||
die $msg;
|
||||
}
|
||||
|
||||
# Connection stuff.
|
||||
my $server = IO::Socket::INET->new(
|
||||
"LocalPort" => $PORT,
|
||||
"Listen" => 10,
|
||||
"ReuseAddr" => 1,
|
||||
"Reuse" => 1,
|
||||
) or killpid_die "Can't make server socket: $@\n";
|
||||
|
||||
nonblock($server);
|
||||
$server->sockopt(SO_REUSEADDR, 1);
|
||||
my $select = IO::Select->new($server);
|
||||
|
||||
print "Looping.\n";
|
||||
|
||||
while(1)
|
||||
{
|
||||
my $client;
|
||||
my $rv;
|
||||
my $data;
|
||||
|
||||
# Got connection? Got data?
|
||||
foreach $client ($select->can_read($SELECT_DELAY)) {
|
||||
if ($client == $server) {
|
||||
# New connection, since there's stuff to read from the server sock.
|
||||
$client = $server->accept();
|
||||
$select->add($client);
|
||||
# If the nonblocking mess fails, uh, give up.
|
||||
unless (nonblock($client)) {
|
||||
$select->remove($client);
|
||||
}
|
||||
} else {
|
||||
# Read what data we have.
|
||||
$data = '';
|
||||
$rv = $client->recv($data, POSIX::BUFSIZ, 0);
|
||||
|
||||
unless (defined($rv) && length($data)) {
|
||||
# If a socket says you can read, but there's nothing there, it's
|
||||
# actually dead. Clean it up.
|
||||
cleanup($client);
|
||||
|
||||
$select->remove($client);
|
||||
close($client);
|
||||
next;
|
||||
}
|
||||
|
||||
$inbuffer{$client} .= $data;
|
||||
# Check to see if there's a newline at the end. If it is, the
|
||||
# command is finished. There's only one command line, so I won't
|
||||
# bother making %cmd a hash with array references to request
|
||||
# lines. Although this might be needed in the future.
|
||||
if ($inbuffer{$client} =~ s/^.*\n//) {
|
||||
$cmd{$client} = $&;
|
||||
delete $inbuffer{$client};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Deal with cmd stuff.
|
||||
foreach $client (keys %cmd) {
|
||||
my $cmd = $cmd{$client};
|
||||
$cmd =~ s/[\n\r]+$//;
|
||||
handle($select, $client, $cmd);
|
||||
}
|
||||
%cmd = ();
|
||||
|
||||
# Flush buffers
|
||||
foreach $client ($select->can_write($SELECT_DELAY)) {
|
||||
# Don't try if there's nothing there.
|
||||
next unless exists $outbuffer{$client};
|
||||
|
||||
$rv = $client->send($outbuffer{$client}, 0);
|
||||
unless (defined $rv) {
|
||||
# Something weird happened if we get here, I'll bitch if we ever
|
||||
# need logging on this thing.
|
||||
next;
|
||||
}
|
||||
if ($rv == length $outbuffer{$client} || $! == POSIX::EWOULDBLOCK) {
|
||||
substr($outbuffer{$client}, 0, $rv) = '';
|
||||
delete $outbuffer{$client} unless length $outbuffer{$client};
|
||||
} else {
|
||||
# Ahh, something broke. If it was going to block, the above would
|
||||
# catch it. Close up...
|
||||
cleanup($client);
|
||||
|
||||
$select->remove($client);
|
||||
close($client);
|
||||
next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Does the messy Socket based nonblock routine...
|
||||
sub nonblock {
|
||||
my $socket = shift;
|
||||
my $flags;
|
||||
|
||||
$flags = fcntl($socket, F_GETFL, 0) or return 0;
|
||||
fcntl($socket, F_SETFL, $flags | O_NONBLOCK) or return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub cleanup
|
||||
{
|
||||
my $client = shift;
|
||||
|
||||
delete $inbuffer{$client};
|
||||
delete $outbuffer{$client};
|
||||
delete $cmd{$client};
|
||||
delete $clientinfo{$client};
|
||||
}
|
||||
157
livejournal/bin/deleteusers.pl
Executable file
@@ -0,0 +1,157 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
|
||||
use strict;
|
||||
|
||||
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
|
||||
my $dbh = LJ::get_dbh("master");
|
||||
$dbh->{'RaiseError'} = 1;
|
||||
$dbh->{'PrintError'} = 1;
|
||||
my $sth;
|
||||
|
||||
$sth = $dbh->prepare("SELECT userid FROM user WHERE statusvis='D' AND statusvisdate < DATE_SUB(NOW(), INTERVAL 35 DAY) ORDER BY statusvisdate");
|
||||
$sth->execute;
|
||||
my @delusers;
|
||||
while (my $duid = $sth->fetchrow_array) {
|
||||
push @delusers, $duid;
|
||||
}
|
||||
print "Users to delete: ", scalar(@delusers), "\n";
|
||||
|
||||
# Get hashref mapping {userid => $u} for all users to be deleted
|
||||
my $user = LJ::load_userids(@delusers);
|
||||
|
||||
LJ::load_props($dbh, "talk");
|
||||
my $p_delposter = LJ::get_prop("talk", "deleted_poster");
|
||||
die "No 'deleted_poster' talkprop?" unless $p_delposter;
|
||||
my $ids;
|
||||
|
||||
my $lastbreak = time();
|
||||
my $pause = sub {
|
||||
if (time() - $lastbreak > 3) { print "pause.\n"; sleep(1); $lastbreak = time(); }
|
||||
};
|
||||
|
||||
# FIXME: This will soon need to be changed to use methods of the $u
|
||||
# object rather than global LJ:: functions, but this should work
|
||||
# for now.
|
||||
|
||||
my $runsql = sub {
|
||||
my $db = $dbh;
|
||||
if (ref $_[0]) { $db = shift; }
|
||||
my $user = shift;
|
||||
my $sql = shift;
|
||||
print " ($user) $sql\n";
|
||||
$db->do($sql);
|
||||
};
|
||||
|
||||
my $czero = 0;
|
||||
|
||||
foreach my $uid (@delusers)
|
||||
{
|
||||
my $du = $user->{$uid};
|
||||
my $user = $du->{'user'};
|
||||
print "$du->{'user'} ($du->{'userid'}) @ $du->{'statusvisdate'}";
|
||||
if ($du->{clusterid} == 0) {
|
||||
print " (on clusterid 0; skipping)\n";
|
||||
$czero++;
|
||||
next;
|
||||
}
|
||||
print " (cluster $du->{'clusterid'})...\n";
|
||||
$pause->();
|
||||
|
||||
# get a db handle for the cluster master.
|
||||
LJ::start_request(); # might've been awhile working with last handle, we don't want to be given an expired one.
|
||||
my $dbcm = LJ::get_cluster_master($du);
|
||||
$dbcm->{'RaiseError'} = 1;
|
||||
$dbcm->{'PrintError'} = 1;
|
||||
|
||||
# make all the user's comments posted now be owned by posterid 0 (anonymous)
|
||||
# but with meta-data saying who used to own it
|
||||
# ..... hm, with clusters this is a pain. let's not.
|
||||
|
||||
# delete memories
|
||||
print " memories\n";
|
||||
while (($ids = $dbh->selectcol_arrayref("SELECT memid FROM memorable WHERE userid=$uid LIMIT 100")) && @{$ids})
|
||||
{
|
||||
my $in = join(",", @$ids);
|
||||
print " id: $in\n";
|
||||
$runsql->($dbh, $user, "DELETE FROM memkeyword WHERE memid IN ($in)");
|
||||
$runsql->($dbh, $user, "DELETE FROM memorable WHERE memid IN ($in)");
|
||||
}
|
||||
|
||||
# delete todos
|
||||
print " todos\n";
|
||||
while (($ids = $dbh->selectcol_arrayref("SELECT todoid FROM todo WHERE journalid=$uid LIMIT 100")) && @{$ids})
|
||||
{
|
||||
my $in = join(",", @$ids);
|
||||
print " id: $in\n";
|
||||
$runsql->($dbh, $user, "DELETE FROM tododep WHERE todoid IN ($in)");
|
||||
$runsql->($dbh, $user, "DELETE FROM todokeyword WHERE todoid IN ($in)");
|
||||
$runsql->($dbh, $user, "DELETE FROM todo WHERE todoid IN ($in)");
|
||||
}
|
||||
|
||||
# delete userpics
|
||||
{
|
||||
print " userpics\n";
|
||||
if ($du->{'dversion'} > 6) {
|
||||
$ids = $dbcm->selectcol_arrayref("SELECT picid FROM userpic2 WHERE userid=$uid");
|
||||
} else {
|
||||
$ids = $dbh->selectcol_arrayref("SELECT picid FROM userpic WHERE userid=$uid");
|
||||
}
|
||||
my $in = join(",",@$ids);
|
||||
if ($in) {
|
||||
print " userpics: $in\n";
|
||||
$runsql->($dbcm, $user, "DELETE FROM userpicblob2 WHERE userid=$uid AND picid IN ($in)");
|
||||
if ($du->{'dversion'} > 6) {
|
||||
$runsql->($dbcm, $user, "DELETE FROM userpic2 WHERE userid=$uid");
|
||||
$runsql->($dbcm, $user, "DELETE FROM userpicmap2 WHERE userid=$uid");
|
||||
$runsql->($dbcm, $user, "DELETE FROM userkeywords WHERE userid=$uid");
|
||||
} else {
|
||||
$runsql->($dbh, $user, "DELETE FROM userpic WHERE userid=$uid");
|
||||
$runsql->($dbh, $user, "DELETE FROM userpicmap WHERE userid=$uid");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# delete posts
|
||||
print " posts\n";
|
||||
while (($ids = $dbcm->selectall_arrayref("SELECT jitemid, anum FROM log2 WHERE journalid=$uid LIMIT 100")) && @{$ids})
|
||||
{
|
||||
foreach my $idanum (@$ids) {
|
||||
my ($id, $anum) = ($idanum->[0], $idanum->[1]);
|
||||
print " deleting $id (a=$anum) ($uid; $du->{'user'})\n";
|
||||
LJ::delete_entry($du, $id, 0, $anum);
|
||||
$pause->();
|
||||
}
|
||||
}
|
||||
|
||||
# misc:
|
||||
$runsql->($user, "DELETE FROM userusage WHERE userid=$uid");
|
||||
$runsql->($user, "DELETE FROM friends WHERE userid=$uid");
|
||||
$runsql->($user, "DELETE FROM friends WHERE friendid=$uid");
|
||||
$runsql->($user, "DELETE FROM friendgroup WHERE userid=$uid");
|
||||
$runsql->($dbcm, $user, "DELETE FROM friendgroup2 WHERE userid=$uid");
|
||||
$runsql->($user, "DELETE FROM memorable WHERE userid=$uid");
|
||||
$runsql->($dbcm, $user, "DELETE FROM memorable2 WHERE userid=$uid");
|
||||
$runsql->($dbcm, $user, "DELETE FROM userkeywords WHERE userid=$uid");
|
||||
$runsql->($dbcm, $user, "DELETE FROM memkeyword2 WHERE userid=$uid");
|
||||
$runsql->($user, "DELETE FROM userbio WHERE userid=$uid");
|
||||
$runsql->($dbcm, $user, "DELETE FROM userbio WHERE userid=$uid");
|
||||
$runsql->($user, "DELETE FROM userinterests WHERE userid=$uid");
|
||||
$runsql->($user, "DELETE FROM userprop WHERE userid=$uid");
|
||||
$runsql->($user, "DELETE FROM userproplite WHERE userid=$uid");
|
||||
$runsql->($user, "DELETE FROM txtmsg WHERE userid=$uid");
|
||||
$runsql->($user, "DELETE FROM overrides WHERE user='$du->{'user'}'");
|
||||
$runsql->($user, "DELETE FROM priv_map WHERE userid=$uid");
|
||||
$runsql->($user, "DELETE FROM infohistory WHERE userid=$uid");
|
||||
$runsql->($user, "DELETE FROM reluser WHERE userid=$uid");
|
||||
$runsql->($user, "DELETE FROM reluser WHERE targetid=$uid");
|
||||
$runsql->($user, "DELETE FROM userlog WHERE userid=$uid");
|
||||
|
||||
$runsql->($user, "UPDATE user SET statusvis='X', statusvisdate=NOW(), password='' WHERE userid=$uid");
|
||||
|
||||
}
|
||||
|
||||
if ($czero) {
|
||||
print "\nWARNING: There are $czero users on cluster zero pending deletion.\n";
|
||||
print " These users must be upgraded before they can be expunged with this tool.\n";
|
||||
}
|
||||
167
livejournal/bin/dumpsql.pl
Executable file
@@ -0,0 +1,167 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# <LJDEP>
|
||||
# lib: cgi-bin/ljlib.pl
|
||||
# </LJDEP>
|
||||
|
||||
use strict;
|
||||
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
|
||||
require "$ENV{'LJHOME'}/cgi-bin/ljviews.pl";
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
sub header_text {
|
||||
return <<"HEADER";
|
||||
# This file is automatically generated from MySQL by \$LJHOME/bin/dumpsql.pl
|
||||
# Don't submit a diff against a hand-modified file - dump and diff instead.
|
||||
|
||||
HEADER
|
||||
}
|
||||
|
||||
# what tables don't we want to export the auto_increment columns from
|
||||
# because they already have their own unique string, which is what matters
|
||||
my %skip_auto = ("userproplist" => "name",
|
||||
"talkproplist" => "name",
|
||||
"logproplist" => "name",
|
||||
"priv_list" => "privcode",
|
||||
"supportcat" => "catkey",
|
||||
"ratelist" => "rlid",
|
||||
);
|
||||
|
||||
# get tables to export
|
||||
my %tables = ();
|
||||
my $sth = $dbh->prepare("SELECT tablename, redist_mode, redist_where ".
|
||||
"FROM schematables WHERE redist_mode NOT IN ('off')");
|
||||
$sth->execute;
|
||||
while (my ($table, $mode, $where) = $sth->fetchrow_array) {
|
||||
$tables{$table}->{'mode'} = $mode;
|
||||
$tables{$table}->{'where'} = $where;
|
||||
}
|
||||
|
||||
my %output; # {general|local} -> [ [ $alphasortkey, $SQL ]+ ]
|
||||
|
||||
# dump each table.
|
||||
foreach my $table (sort keys %tables)
|
||||
{
|
||||
my $where;
|
||||
if ($tables{$table}->{'where'}) {
|
||||
$where = "WHERE $tables{$table}->{'where'}";
|
||||
}
|
||||
|
||||
my $sth = $dbh->prepare("DESCRIBE $table");
|
||||
$sth->execute;
|
||||
my @cols = ();
|
||||
my $skip_auto = 0;
|
||||
while (my $c = $sth->fetchrow_hashref) {
|
||||
if ($c->{'Extra'} =~ /auto_increment/ && $skip_auto{$table}) {
|
||||
$skip_auto = 1;
|
||||
} else {
|
||||
push @cols, $c;
|
||||
}
|
||||
}
|
||||
|
||||
# DESCRIBE table can be different between developers
|
||||
@cols = sort { $a->{'Field'} cmp $b->{'Field'} } @cols;
|
||||
|
||||
my $cols = join(", ", map { $_->{'Field'} } @cols);
|
||||
my $sth = $dbh->prepare("SELECT $cols FROM $table $where");
|
||||
$sth->execute;
|
||||
my $sql;
|
||||
while (my @r = $sth->fetchrow_array)
|
||||
{
|
||||
my %vals;
|
||||
my $i = 0;
|
||||
foreach (map { $_->{'Field'} } @cols) {
|
||||
$vals{$_} = $r[$i++];
|
||||
}
|
||||
my $scope = "general";
|
||||
$scope = "local" if (defined $vals{'scope'} &&
|
||||
$vals{'scope'} eq "local");
|
||||
my $verb = "INSERT IGNORE";
|
||||
$verb = "REPLACE" if ($tables{$table}->{'mode'} eq "replace" &&
|
||||
! $skip_auto);
|
||||
$sql = "$verb INTO $table ";
|
||||
$sql .= "($cols) ";
|
||||
$sql .= "VALUES (" . join(", ", map { db_quote($_) } @r) . ");\n";
|
||||
|
||||
my $uniqc = $skip_auto{$table};
|
||||
my $skey = $uniqc ? $vals{$uniqc} : $sql;
|
||||
push @{$output{$scope}}, [ "$table.$skey.1", $sql ];
|
||||
|
||||
if ($skip_auto) {
|
||||
# for all the *proplist tables, there might be new descriptions
|
||||
# or columns, but we can't do a REPLACE, because that'd mess
|
||||
# with their auto_increment ids, so we do insert ignore + update
|
||||
my $where = "$uniqc=" . db_quote($vals{$uniqc});
|
||||
delete $vals{$uniqc};
|
||||
$sql = "UPDATE $table SET ";
|
||||
$sql .= join(",", map { "$_=" . db_quote($vals{$_}) } sort keys %vals);
|
||||
$sql .= " WHERE $where;\n";
|
||||
push @{$output{$scope}}, [ "$table.$skey.2", $sql ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# don't use $dbh->quote because it's changed between versions
|
||||
# and developers sending patches can't generate concise patches
|
||||
# it used to not quote " in a single quoted string, but later it does.
|
||||
# so we'll implement the new way here.
|
||||
sub db_quote {
|
||||
my $s = shift;
|
||||
return "NULL" unless defined $s;
|
||||
$s =~ s/\\/\\\\/g;
|
||||
$s =~ s/\"/\\\"/g;
|
||||
$s =~ s/\'/\\\'/g;
|
||||
$s =~ s/\n/\\n/g;
|
||||
$s =~ s/\r/\\r/g;
|
||||
return "'$s'";
|
||||
}
|
||||
|
||||
foreach my $k (keys %output) {
|
||||
my $file = $k eq "general" ? "base-data.sql" : "base-data-local.sql";
|
||||
print "Dumping $file\n";
|
||||
my $ffile = "$ENV{'LJHOME'}/bin/upgrading/$file";
|
||||
open (F, ">$ffile") or die "Can't write to $ffile\n";
|
||||
print F header_text();
|
||||
foreach (sort { $a->[0] cmp $b->[0] } @{$output{$k}}) {
|
||||
print F $_->[1];
|
||||
}
|
||||
close F;
|
||||
}
|
||||
|
||||
# and do S1 styles (ugly schema)
|
||||
print "Dumping s1styles.dat\n";
|
||||
require "$ENV{'LJHOME'}/bin/upgrading/s1style-rw.pl";
|
||||
my $ss = {};
|
||||
my $pubstyles = LJ::S1::get_public_styles({ 'formatdata' => 1});
|
||||
foreach my $s (values %$pubstyles) {
|
||||
my $uniq = "$s->{'type'}/$s->{'styledes'}";
|
||||
$ss->{$uniq}->{$_} = $s->{$_} foreach keys %$s;
|
||||
}
|
||||
s1styles_write($ss);
|
||||
|
||||
# and dump mood info
|
||||
print "Dumping moods.dat\n";
|
||||
open (F, ">$ENV{'LJHOME'}/bin/upgrading/moods.dat") or die;
|
||||
$sth = $dbh->prepare("SELECT moodid, mood, parentmood FROM moods ORDER BY moodid");
|
||||
$sth->execute;
|
||||
while (@_ = $sth->fetchrow_array) {
|
||||
print F "MOOD @_\n";
|
||||
}
|
||||
|
||||
$sth = $dbh->prepare("SELECT moodthemeid, name, des FROM moodthemes WHERE is_public='Y' ORDER BY name");
|
||||
$sth->execute;
|
||||
while (my ($id, $name, $des) = $sth->fetchrow_array) {
|
||||
$name =~ s/://;
|
||||
print F "MOODTHEME $name : $des\n";
|
||||
my $std = $dbh->prepare("SELECT moodid, picurl, width, height FROM moodthemedata ".
|
||||
"WHERE moodthemeid=$id ORDER BY moodid");
|
||||
$std->execute;
|
||||
while (@_ = $std->fetchrow_array) {
|
||||
print F "@_\n";
|
||||
}
|
||||
}
|
||||
close F;
|
||||
|
||||
|
||||
print "Done.\n";
|
||||
144
livejournal/bin/fingerd.pl
Executable file
@@ -0,0 +1,144 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# finger server.
|
||||
#
|
||||
# accepts two optional arguments, host and port.
|
||||
# doesn't daemonize.
|
||||
#
|
||||
#
|
||||
# <LJDEP>
|
||||
# lib: Socket::, Text::Wrap, cgi-bin/ljlib.pl
|
||||
# </LJDEP>
|
||||
|
||||
my $bindhost = shift @ARGV;
|
||||
my $port = shift @ARGV;
|
||||
|
||||
unless ($bindhost) {
|
||||
$bindhost = "0.0.0.0";
|
||||
}
|
||||
|
||||
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
|
||||
|
||||
use Socket;
|
||||
use Text::Wrap;
|
||||
|
||||
$SIG{'INT'} = sub {
|
||||
print "Interrupt caught!\n";
|
||||
close FH;
|
||||
close CL;
|
||||
exit;
|
||||
};
|
||||
|
||||
my $proto = getprotobyname('tcp');
|
||||
socket(FH, PF_INET, SOCK_STREAM, $proto) || die $!;
|
||||
|
||||
$port ||= 79;
|
||||
my $localaddr = inet_aton($bindhost);
|
||||
my $sin = sockaddr_in($port, $localaddr);
|
||||
setsockopt (FH,SOL_SOCKET,SO_REUSEADDR,1) or
|
||||
die "setsockopt() failed: $!\n";
|
||||
bind (FH, $sin) || die $!;
|
||||
|
||||
listen(FH, 10);
|
||||
|
||||
while (LJ::start_request())
|
||||
{
|
||||
accept(CL, FH) || die $!;
|
||||
|
||||
my $line = <CL>;
|
||||
chomp $line;
|
||||
$line =~ s/\0//g;
|
||||
$line =~ s/\s//g;
|
||||
|
||||
if ($line eq "") {
|
||||
print CL "Welcome to the $LJ::SITENAME finger server!
|
||||
|
||||
You can make queries in the following form:
|
||||
|
||||
\@$LJ::DOMAIN - this help message
|
||||
user\@$LJ::DOMAIN - their userinfo
|
||||
";
|
||||
close CL;
|
||||
next;
|
||||
}
|
||||
|
||||
my $dbr = LJ::get_dbh("slave", "master");
|
||||
|
||||
if ($line =~ /^(\w{1,15})$/) {
|
||||
# userinfo!
|
||||
my $user = $1;
|
||||
my $quser = $dbr->quote($user);
|
||||
my $sth = $dbr->prepare("SELECT user, has_bio, caps, userid, name, email, bdate, allow_infoshow FROM user WHERE user=$quser");
|
||||
$sth->execute;
|
||||
my $u = $sth->fetchrow_hashref;
|
||||
unless ($u) {
|
||||
print CL "\nUnknown user ($user)\n";
|
||||
close CL;
|
||||
next;
|
||||
}
|
||||
|
||||
my $bio;
|
||||
if ($u->{'has_bio'} eq "Y") {
|
||||
$sth = $dbr->prepare("SELECT bio FROM userbio WHERE userid=$u->{'userid'}");
|
||||
$sth->execute;
|
||||
($bio) = $sth->fetchrow_array;
|
||||
}
|
||||
delete $u->{'has_bio'};
|
||||
|
||||
$u->{'accttype'} = LJ::name_caps($u->{'caps'});
|
||||
|
||||
if ($u->{'allow_infoshow'} eq "Y") {
|
||||
LJ::load_user_props($dbr, $u, "opt_whatemailshow",
|
||||
"country", "state", "city", "zip",
|
||||
"aolim", "icq", "url", "urlname",
|
||||
"yahoo", "msn");
|
||||
} else {
|
||||
$u->{'opt_whatemailshow'} = "N";
|
||||
}
|
||||
delete $u->{'allow_infoshow'};
|
||||
|
||||
if ($u->{'opt_whatemailshow'} eq "L") {
|
||||
delete $u->{'email'};
|
||||
}
|
||||
if ($LJ::USER_EMAIL && LJ::get_cap($u, "useremail")) {
|
||||
if ($u->{'email'}) { $u->{'email'} .= ", "; }
|
||||
$u->{'email'} .= "$user\@$LJ::USER_DOMAIN";
|
||||
}
|
||||
|
||||
if ($u->{'opt_whatemailshow'} eq "N") {
|
||||
delete $u->{'email'};
|
||||
}
|
||||
delete $u->{'opt_whatemailshow'};
|
||||
|
||||
my $max = 1;
|
||||
foreach (keys %$u) {
|
||||
if (length($_) > $max) { $max = length($_); }
|
||||
}
|
||||
$max++;
|
||||
|
||||
delete $u->{'caps'};
|
||||
|
||||
print CL "\nUserinfo for $user...\n\n";
|
||||
foreach my $k (sort keys %$u) {
|
||||
printf CL "%${max}s : %s\n", $k, $u->{$k};
|
||||
}
|
||||
|
||||
if ($bio) {
|
||||
$bio =~ s/^\s+//;
|
||||
$bio =~ s/\s+$//;
|
||||
print CL "\nBio:\n\n";
|
||||
$Text::Wrap::columns = 77;
|
||||
print CL Text::Wrap::wrap(" ", " ", $bio);
|
||||
}
|
||||
print CL "\n\n";
|
||||
|
||||
close CL;
|
||||
next;
|
||||
|
||||
}
|
||||
|
||||
print CL "Unsupported/unimplemented query type: $line\n";
|
||||
print CL "length: ", length($line), "\n";
|
||||
close CL;
|
||||
next;
|
||||
}
|
||||
128
livejournal/bin/interdoc.pl
Executable file
@@ -0,0 +1,128 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# This script parses LJ dependency info from all the other files on
|
||||
# that make up the site. Usually that dependency data is at the end
|
||||
# of the files, but in this file it's here at the top for two reasons:
|
||||
# as an example, and because otherwise this script would parse itself
|
||||
# and start at the wrong place. So, here's this file's dependency
|
||||
# data:
|
||||
#
|
||||
# <LJDEP>
|
||||
# lib: Getopt::Long
|
||||
# </LJDEP>
|
||||
#
|
||||
# This file parses files for lines containing <LJDEP> then starts
|
||||
# looking for dependency declarations on subsequent lines until
|
||||
# </LJDEP> is found. Note that leading junk is ignored. The
|
||||
# dependencies are of the form:
|
||||
#
|
||||
# type: item, item, item
|
||||
#
|
||||
# Where type is one of:
|
||||
#
|
||||
# file -- data file
|
||||
# form -- form with method=GET
|
||||
# lib -- perl module or library (append :: if ! /::/)
|
||||
# link -- web link
|
||||
# mailto -- mailto link
|
||||
# post -- form with method=POST
|
||||
# prog -- program that's run
|
||||
# hook -- LJ hook name
|
||||
#
|
||||
|
||||
use strict;
|
||||
use Getopt::Long;
|
||||
|
||||
my $opt_warn = 0;
|
||||
my $opt_types = 0;
|
||||
GetOptions('warn' => \$opt_warn,
|
||||
'types' => \$opt_types);
|
||||
|
||||
unless (-d $ENV{'LJHOME'}) {
|
||||
die "\$LJHOME not set.\n";
|
||||
}
|
||||
chdir $ENV{'LJHOME'} or die "Can't cd to $ENV{'LJOME'}\n";
|
||||
|
||||
find(qw(bin cgi-bin htdocs));
|
||||
|
||||
exit;
|
||||
|
||||
sub find
|
||||
{
|
||||
my @dirs = @_;
|
||||
while (@dirs)
|
||||
{
|
||||
my $dir = shift @dirs;
|
||||
next if ($dir eq "htdocs/img");
|
||||
next if ($dir eq "htdocs/doc");
|
||||
|
||||
opendir (D, $dir);
|
||||
my @files = sort { $a cmp $b } readdir(D);
|
||||
close D;
|
||||
|
||||
foreach my $f (@files) {
|
||||
next if ($f eq "." || $f eq "..");
|
||||
my $full = "$dir/$f";
|
||||
if (-d $full) { find($full); }
|
||||
elsif (-f $full) { check_file($full); }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sub check_file
|
||||
{
|
||||
$_ = shift;
|
||||
next unless (-f);
|
||||
next if (/\.(gif|jpg|png|class|jar|zip|exe|gz|deb|rpm|ico)$/);
|
||||
next if (/~$/);
|
||||
|
||||
my $file = $_;
|
||||
my $indep = 0;
|
||||
my %deps;
|
||||
|
||||
open (F, $file);
|
||||
while (my $l = <F>)
|
||||
{
|
||||
if (! $indep) {
|
||||
if ($l =~ /<LJDEP>/) {
|
||||
$indep = 1;
|
||||
$deps{'_found'} = 1;
|
||||
}
|
||||
next;
|
||||
}
|
||||
|
||||
if ($l =~ /<\/LJDEP>/) {
|
||||
last;
|
||||
}
|
||||
|
||||
if ($l =~ /(\w+):(.+)/) {
|
||||
my $k = $1;
|
||||
my $v = $2;
|
||||
$v =~ s/^\s+//;
|
||||
$v =~ s/\s+$//;
|
||||
my @vs = split(/\s*\,\s*/, $v);
|
||||
foreach (@vs) {
|
||||
push @{$deps{$k}}, $_;
|
||||
}
|
||||
}
|
||||
}
|
||||
close (F);
|
||||
|
||||
if (delete $deps{'_found'}) {
|
||||
foreach my $t (keys %deps) {
|
||||
foreach my $v (@{$deps{$t}}) {
|
||||
if ($opt_types) {
|
||||
print "$t\n";
|
||||
} else {
|
||||
print join("\t", $file, $t, $v), "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($opt_warn) {
|
||||
print STDERR "No dep info: $file\n";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
3
livejournal/bin/jmk
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
java -jar $LJHOME/bin/jmk.jar $@
|
||||
43
livejournal/bin/lj-inline.pl
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
|
||||
use strict;
|
||||
use lib "$ENV{LJHOME}/cgi-bin";
|
||||
|
||||
BEGIN {
|
||||
$LJ::HAVE_INLINE = eval 'use Inline Config => DIRECTORY => ($ENV{LJ_INLINE_DIR} || "$ENV{LJHOME}/Inline"); use Inline "C"; 1;';
|
||||
|
||||
# to shutup Apache::SendStat's warning:
|
||||
$LJ::JUST_COMPILING = 1;
|
||||
}
|
||||
|
||||
print "This script will recompile ljcom's Inline.pm C code, if necessary. You need a C compiler installed.\n";
|
||||
|
||||
unless ($LJ::HAVE_INLINE) {
|
||||
print "\nBut you don't have Inline.pm installed, so quitting now.\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
print "Testing your Inline install...\n";
|
||||
unless (inline_test()) {
|
||||
print "Error. Sure you have a C compiler installed?\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
print "ljlib/ljlib-local.pl (if anything)...\n";
|
||||
require "ljlib.pl";
|
||||
|
||||
print "Apache::SendStats...\n";
|
||||
# wrapped in eval because ap_scoreboard_image isn't around
|
||||
# when not running inside apache
|
||||
eval "use Apache::SendStats;";
|
||||
|
||||
print "Done.\n";
|
||||
|
||||
__DATA__
|
||||
__C__
|
||||
|
||||
int inline_test () {
|
||||
printf("Your Inline install is good. Proceeding...\n");
|
||||
return 1;
|
||||
}
|
||||
631
livejournal/bin/ljblockwatcher.pl
Executable file
@@ -0,0 +1,631 @@
|
||||
#!/usr/bin/perl
|
||||
##############################################################################
|
||||
|
||||
=head1 NAME
|
||||
|
||||
dbreportd - Report database latencies at regular intervals.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
$ dbreportd OPTIONS
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over 4
|
||||
|
||||
=item -c, --clearscreen
|
||||
|
||||
Clear the screen and home the cursor before printing each report, like top. May
|
||||
not work on all terminals.
|
||||
|
||||
=item -d, --debug
|
||||
|
||||
Turn on debugging information. May be specified more than once for (potentially)
|
||||
increased levels of debugging.
|
||||
|
||||
=item -h, --help
|
||||
|
||||
Output a help message and exit.
|
||||
|
||||
=item -i, --interval=SECONDS
|
||||
|
||||
Set the number of seconds between reports to SECONDS. Defaults to 3 second
|
||||
intervals.
|
||||
|
||||
=item -p, --port=PORT
|
||||
|
||||
Set the port to listen on for reports. This is set in ljconfig.pl, but can be
|
||||
overridden here.
|
||||
|
||||
=item -V, --version
|
||||
|
||||
Output version information and exit.
|
||||
|
||||
=back
|
||||
|
||||
=head1 REQUIRES
|
||||
|
||||
I<Token requires line>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
None yet.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Michael Granger <ged@FaerieMUD.org>
|
||||
|
||||
Copyright (c) 2004 Danga Interactive. All rights reserved.
|
||||
|
||||
This program is Open Source software. You may use, modify, and/or redistribute
|
||||
this software under the terms of the Perl Artistic License. (See
|
||||
http://language.perl.com/misc/Artistic.html)
|
||||
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
=cut
|
||||
|
||||
# :TODO: Change param order in received msgs
|
||||
|
||||
##############################################################################
|
||||
package dbreportd;
|
||||
use strict;
|
||||
use warnings qw{all};
|
||||
|
||||
|
||||
###############################################################################
|
||||
### I N I T I A L I Z A T I O N
|
||||
###############################################################################
|
||||
BEGIN {
|
||||
|
||||
# Turn STDOUT buffering off
|
||||
$| = 1;
|
||||
|
||||
# Versioning stuff and custom includes
|
||||
use vars qw{$VERSION $RCSID};
|
||||
$VERSION = do { my @r = (q$Revision: 1.3 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r };
|
||||
$RCSID = q$Id: ljblockwatcher.pl,v 1.3 2004/03/09 22:25:05 deveiant Exp $;
|
||||
|
||||
# Define some constants
|
||||
use constant TRUE => 1;
|
||||
use constant FALSE => 0;
|
||||
|
||||
# How many time samples to keep around to determine average latency
|
||||
use constant SAMPLE_DEPTH => 10;
|
||||
|
||||
# How many samples to show in the "top <n> slow queries"
|
||||
use constant TOP_QUERY_SIZE => 5;
|
||||
|
||||
# ANSI vt100 escape codes for various things
|
||||
use constant VT100_CLEARSCREEN => "\e[2J";
|
||||
use constant VT100_HOME => "\e[0;0H";
|
||||
|
||||
# Modules
|
||||
use Getopt::Long qw{GetOptions};
|
||||
use Pod::Usage qw{pod2usage};
|
||||
|
||||
use IO::Socket::INET qw{};
|
||||
use IO::Select qw{};
|
||||
use Time::HiRes qw{usleep};
|
||||
use Data::Dumper qw{};
|
||||
|
||||
# Turn on option bundling (-vid)
|
||||
Getopt::Long::Configure( "bundling" );
|
||||
}
|
||||
|
||||
our $Debug = FALSE;
|
||||
|
||||
### Main body
|
||||
MAIN: {
|
||||
my (
|
||||
$helpFlag, # User requested help?
|
||||
$versionFlag, # User requested version info?
|
||||
|
||||
$interval, # Interval between generated reports
|
||||
$port, # Port number to listen on
|
||||
|
||||
$msg, # The message buffer for reports
|
||||
$sock, # UDP socket
|
||||
$selector, # IO::Select object
|
||||
$lastReport, # time() of last report output
|
||||
$host, # Message host
|
||||
$time, # Message time
|
||||
$notes, # Message notes
|
||||
$type, # Operation type (currently unused)
|
||||
%buffers, # SampleBuffers keyed by host
|
||||
$clearscreenFlag, # Clear the screen before every report?
|
||||
);
|
||||
|
||||
# Print the program header and read in command line options
|
||||
GetOptions(
|
||||
'd|debug+' => \$Debug,
|
||||
'h|help' => \$helpFlag,
|
||||
'i|interval=i' => \$interval,
|
||||
'V|version' => \$versionFlag,
|
||||
'p|port=i' => \$port,
|
||||
'c|clearscreen' => \$clearscreenFlag,
|
||||
) or abortWithUsage();
|
||||
|
||||
# If the -h flag or -V flag was given, just show the help or version,
|
||||
# respectively, and exit.
|
||||
helpMode() and exit if $helpFlag;
|
||||
versionMode() and exit if $versionFlag;
|
||||
|
||||
# Either get the port from the command line or a default
|
||||
$port ||= 4774;
|
||||
|
||||
# Set the interval to a default if it wasn't specified
|
||||
$interval = 3 if !defined $interval;
|
||||
|
||||
# Open a receiving UDP socket
|
||||
print VT100_CLEARSCREEN, VT100_HOME if $clearscreenFlag;
|
||||
print "Setting up listener on port $port\n";
|
||||
$sock = new IO::Socket::INET (
|
||||
Proto => 'udp',
|
||||
LocalPort => $port
|
||||
) or die "Failed to open receiving socket: $!";
|
||||
|
||||
$selector = new IO::Select;
|
||||
$selector->add( $sock );
|
||||
$lastReport = time();
|
||||
|
||||
%buffers = ();
|
||||
|
||||
# Print reports every couple of seconds
|
||||
while ( 1 ) {
|
||||
if ( $selector->can_read($interval) ) {
|
||||
|
||||
# Get the message and split it back into four parts
|
||||
my $addr = $sock->recv( $msg, 1024, 0 );
|
||||
print ">>> Message: $msg\n" if $Debug;
|
||||
( $host, $type, $time, $notes ) = split( /\x3/, $msg, 4 );
|
||||
|
||||
# Add the time and notes to the table of hosts
|
||||
$buffers{ $host } ||= new SampleBuffer ( $host, depth => SAMPLE_DEPTH );
|
||||
$buffers{ $host }->add( $type, $time, $notes );
|
||||
} else {
|
||||
sleep 0.5;
|
||||
}
|
||||
|
||||
} continue {
|
||||
if ( (time() - $lastReport) > $interval ) {
|
||||
print VT100_CLEARSCREEN, VT100_HOME if $clearscreenFlag;
|
||||
print_report( values %buffers );
|
||||
$lastReport = time();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
### FUNCTION: print_report( @buffers )
|
||||
### Given a list of SampleBuffer objects, print a table with the ones with the
|
||||
### highest average times.
|
||||
sub print_report {
|
||||
my @buffers = @_;
|
||||
|
||||
my (
|
||||
$row, # Row count for display
|
||||
@top, # Top 5 slowest average buffers
|
||||
%top, # ^-- Hash of same
|
||||
@sbuffers, # Buffer objects sorted by hostname
|
||||
@wbuffers, # Buffer objects sorted by worst op
|
||||
$fmt, # printf format for report rows
|
||||
$prefix, # Line prefixes
|
||||
);
|
||||
|
||||
if ( @buffers ) {
|
||||
# Pick the 5 slowest operations
|
||||
@top =
|
||||
map { $_->[0] }
|
||||
sort { $b->[1] <=> $a->[1] }
|
||||
map { [$_->host, $_->average_time] }
|
||||
@buffers;
|
||||
$row = 0;
|
||||
%top = ();
|
||||
foreach my $host ( @top[0 ... TOP_QUERY_SIZE] ) {
|
||||
last unless defined $host;
|
||||
$top{$host} = ++$row unless exists $top{$host};
|
||||
}
|
||||
#print Data::Dumper->Dumpxs( [\%top], ['top'] ), "\n";
|
||||
|
||||
# Make an array of sorted buffer objects by worst average time
|
||||
@sbuffers =
|
||||
map { $_->[0] }
|
||||
sort { $b->[1] <=> $a->[1] }
|
||||
map { [$_, $_->average_time] }
|
||||
@buffers;
|
||||
|
||||
# Make an array of sorted buffer objects by worst time
|
||||
@wbuffers =
|
||||
map { $_->[0] }
|
||||
sort { $b->[1] <=> $a->[1] }
|
||||
map { [$_, $_->worst_time] }
|
||||
@buffers;
|
||||
|
||||
# Output all hosts with the average worst operation times
|
||||
$fmt = "%-2s%25s %0.5fs";
|
||||
$row = 0;
|
||||
header( "Average longest blocking operations, by host" );
|
||||
foreach my $buf (@sbuffers) {
|
||||
$row++;
|
||||
|
||||
if ( exists $top{$buf->host} && $top{$buf->host} <= 3 ) {
|
||||
$prefix = '+';
|
||||
} else {
|
||||
$prefix = ' ';
|
||||
}
|
||||
|
||||
printf "$fmt\n", $prefix, $buf->host, $buf->average_time;
|
||||
}
|
||||
print "\n";
|
||||
|
||||
# Output the worst operations with their notes
|
||||
$row = 0;
|
||||
$fmt = "%0.5fs: '%s' [%s/%s]\n";
|
||||
header( "%d worst blockers", TOP_QUERY_SIZE );
|
||||
foreach my $buf (@wbuffers[0 ... TOP_QUERY_SIZE]) {
|
||||
last unless defined $buf;
|
||||
$row++;
|
||||
|
||||
my $sample = $buf->worst_sample;
|
||||
printf( $fmt,
|
||||
$sample->time,
|
||||
$sample->notes || "(none)",
|
||||
$sample->type,
|
||||
$buf->host );
|
||||
}
|
||||
print "\n";
|
||||
|
||||
# Print the raw buffer objects if debugging
|
||||
if ( $Debug ) {
|
||||
header( "Raw buffers" );
|
||||
foreach my $buf ( @buffers ) {
|
||||
local $Data::Dumper::Indent = 0;
|
||||
local $Data::Dumper::Terse = TRUE;
|
||||
print Data::Dumper->Dumpxs( [$buf], ['buf'] ), "\n";
|
||||
}
|
||||
}
|
||||
|
||||
print "\n";
|
||||
}
|
||||
|
||||
else {
|
||||
print "No hosts reporting.\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
### FUNCTION: header( $fmt, @args )
|
||||
### Printf the given message as a header.
|
||||
sub header {
|
||||
my ( $fmt, @args ) = @_;
|
||||
my $msg = sprintf( $fmt, @args );
|
||||
chomp( $msg );
|
||||
|
||||
print "$msg\n", '-' x 75, "\n";
|
||||
}
|
||||
|
||||
|
||||
### FUNCTION: helpMode()
|
||||
### Exit normally after printing the usage message
|
||||
sub helpMode {
|
||||
pod2usage( -verbose => 1, -exitval => 0 );
|
||||
}
|
||||
|
||||
|
||||
### FUNCTION: versionMode()
|
||||
### Exit normally after printing version information
|
||||
sub versionMode {
|
||||
print STDERR "dbreportd $VERSION\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
### FUNCTION: abortWithUsage()
|
||||
### Abort the program showing usage message.
|
||||
sub abortWithUsage {
|
||||
if ( @_ ) {
|
||||
pod2usage( -verbose => 1, -exitval => 1, -msg => join('', @_) );
|
||||
} else {
|
||||
pod2usage( -verbose => 1, -exitval => 1 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
### FUNCTION: abort( @messages )
|
||||
### Print the specified messages to the terminal and exit with a non-zero status.
|
||||
sub abort {
|
||||
my $msg = @_ ? join '', @_ : "unknown error";
|
||||
print STDERR $msg, "\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
### T I M E S A M P L E C L A S S
|
||||
#####################################################################
|
||||
package Sample;
|
||||
use strict;
|
||||
|
||||
BEGIN {
|
||||
use vars qw{$AUTOLOAD};
|
||||
use Carp qw{croak confess};
|
||||
use Data::Dumper ();
|
||||
$Data::Dumper::Terse = 1;
|
||||
$Data::Dumper::Indent = 1;
|
||||
}
|
||||
|
||||
### METHOD: new( $host )
|
||||
### Create a new sample buffer for the given host
|
||||
sub new {
|
||||
my $proto = shift;
|
||||
my $class = ref $proto || $proto;
|
||||
|
||||
my $self = bless {
|
||||
type => 'db',
|
||||
time => 0.0,
|
||||
notes => '',
|
||||
}, $class;
|
||||
|
||||
if ( @_ && (@_ % 2 == 0) ) {
|
||||
my %args = @_;
|
||||
foreach my $meth ( keys %args ) {
|
||||
$self->$meth( $args{$meth} );
|
||||
}
|
||||
}
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
|
||||
|
||||
### FUNCTION: blessed( $var )
|
||||
### Returns a true value if the given value is a blessed reference.
|
||||
sub blessed {
|
||||
my $arg = shift;
|
||||
return ref $arg && UNIVERSAL::isa( $arg, 'UNIVERSAL' );
|
||||
}
|
||||
|
||||
|
||||
### (PROXY) METHOD: AUTOLOAD( @args )
|
||||
### Proxy method to build (non-translucent) object accessors.
|
||||
sub AUTOLOAD {
|
||||
my $self = shift;
|
||||
confess "Cannot be called as a function" unless $self && blessed $self;
|
||||
|
||||
( my $name = $AUTOLOAD ) =~ s{.*::}{};
|
||||
|
||||
### Build an accessor for extant attributes
|
||||
if ( exists $self->{$name} ) {
|
||||
|
||||
### Define an accessor for this attribute
|
||||
my $method = sub {
|
||||
my $closureSelf = shift or confess "Cannot be called as a function";
|
||||
$closureSelf->{$name} = shift if @_;
|
||||
return $closureSelf->{$name};
|
||||
};
|
||||
|
||||
### Install the new method in the symbol table
|
||||
NO_STRICT_REFS: {
|
||||
no strict 'refs';
|
||||
*{$AUTOLOAD} = $method;
|
||||
}
|
||||
|
||||
### Now jump to the new method after sticking the self-ref back onto the
|
||||
### stack
|
||||
unshift @_, $self;
|
||||
goto &$AUTOLOAD;
|
||||
}
|
||||
|
||||
### Try to delegate to our parent's version of the method
|
||||
my $parentMethod = "SUPER::$name";
|
||||
return $self->$parentMethod( @_ );
|
||||
}
|
||||
|
||||
sub DESTROY {}
|
||||
sub END {}
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
### S A M P L E B U F F E R C L A S S
|
||||
#####################################################################
|
||||
|
||||
### Class for tracking latencies for a given host
|
||||
package SampleBuffer;
|
||||
use strict;
|
||||
|
||||
BEGIN {
|
||||
use Carp qw{croak confess};
|
||||
use vars qw{$AUTOLOAD};
|
||||
}
|
||||
|
||||
|
||||
### METHOD: new( $host )
|
||||
### Create a new sample buffer for the given host
|
||||
sub new {
|
||||
my $proto = shift;
|
||||
my $class = ref $proto || $proto;
|
||||
my $host = shift or die "No hostname given";
|
||||
|
||||
my $self = bless {
|
||||
host => $host,
|
||||
samples => {},
|
||||
depth => 10,
|
||||
}, $class;
|
||||
|
||||
if ( @_ && (@_ % 2 == 0) ) {
|
||||
my %args = @_;
|
||||
foreach my $meth ( keys %args ) {
|
||||
$self->$meth( $args{$meth} );
|
||||
}
|
||||
}
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
|
||||
### METHOD: add( $type, $time, $notes )
|
||||
### Add the specified I<time> to the sample buffer for the given I<type> with
|
||||
### the given I<notes>.
|
||||
sub add {
|
||||
my $self = shift or confess "Cannot be called as a function";
|
||||
my ( $type, $time, $notes ) = @_;
|
||||
|
||||
$self->{samples}{ $type } ||= [];
|
||||
my $slist = $self->{samples}{ $type };
|
||||
|
||||
my $sample = new Sample ( type => $type, time => $time, notes => $notes );
|
||||
unshift @$slist, $sample;
|
||||
pop @$slist if @$slist > $self->{depth};
|
||||
|
||||
return scalar @$slist;
|
||||
}
|
||||
|
||||
|
||||
### METHOD: samples( [$type] )
|
||||
### Fetch a list of the samples of the given I<type> in the buffer, or a list of
|
||||
### all samples if I<type> is not specified.
|
||||
sub samples {
|
||||
my $self = shift or confess "Cannot be used as a function";
|
||||
my $type = shift;
|
||||
|
||||
my @samples = ();
|
||||
|
||||
# Gather the samples that are going to be used to make the average, either
|
||||
# the specific kind requested, or all of 'em.
|
||||
if ( $type ) {
|
||||
# Regexp filter
|
||||
if ( ref $type eq 'Regexp' ) {
|
||||
foreach my $key ( keys %{$self->{samples}} ) {
|
||||
push @samples, @{$self->{samples}{ $key }}
|
||||
if $type =~ $key;
|
||||
}
|
||||
}
|
||||
|
||||
# Any other filter just gets string-equalled.
|
||||
else {
|
||||
@samples = @{$self->{samples}{ $type }};
|
||||
}
|
||||
} else {
|
||||
foreach my $type ( keys %{$self->{samples}} ) {
|
||||
push @samples, @{$self->{samples}{ $type }};
|
||||
}
|
||||
}
|
||||
|
||||
return @samples;
|
||||
}
|
||||
|
||||
|
||||
### METHOD: average_time( [$type] )
|
||||
### Return the average of all the times currently in the buffer for the given
|
||||
### I<type>. If I<type> isn't given, returns the overall average.
|
||||
sub average_time {
|
||||
my $self = shift or confess "Cannot be used as a function";
|
||||
my $type = shift;
|
||||
|
||||
my ( $time, $count ) = ( 0, 0 );
|
||||
|
||||
# Now add and count all the time from each target sample
|
||||
foreach my $sample ( $self->samples($type) ) {
|
||||
$time += $sample->time;
|
||||
$count++;
|
||||
}
|
||||
|
||||
return $time / $count;
|
||||
}
|
||||
|
||||
|
||||
### METHOD: worst_sample( [$type] )
|
||||
### Return the worst sample in the buffer for the given I<type>. If no type is
|
||||
### given, return the worst overall sample.
|
||||
sub worst_sample {
|
||||
my $self = shift or confess "Cannot be used as a function";
|
||||
my $type = shift;
|
||||
return () unless %{$self->{samples}};
|
||||
|
||||
my @samples =
|
||||
map { $_->[0] }
|
||||
sort { $a->[1] <=> $b->[1] }
|
||||
map { [$_, $_->time] } $self->samples( $type );
|
||||
|
||||
return $samples[-1];
|
||||
}
|
||||
|
||||
|
||||
### METHOD: worst_time( [$type] )
|
||||
### Return the worst time in the buffer for the given I<type>. If no I<type> is
|
||||
### given, returns the worst overall time.
|
||||
sub worst_time {
|
||||
my $self = shift or confess "Cannot be used as a function";
|
||||
my $type = shift;
|
||||
|
||||
my $samp = $self->worst_sample( $type ) or return ();
|
||||
return $samp->time;
|
||||
}
|
||||
|
||||
|
||||
### METHOD: worst_notes( [$type] )
|
||||
### Return the notes from the worst sample in the buffer for the given
|
||||
### I<type>. If I<type> is not specified, returns the notes for the worst
|
||||
### overall sample.
|
||||
sub worst_notes {
|
||||
my $self = shift or confess "Cannot be used as a function";
|
||||
my $type = shift;
|
||||
|
||||
my $samp = $self->worst_sample( $type ) or return ();
|
||||
return $samp->notes;
|
||||
}
|
||||
|
||||
|
||||
### FUNCTION: blessed( $var )
|
||||
### Returns a true value if the given value is a blessed reference.
|
||||
sub blessed {
|
||||
my $arg = shift;
|
||||
return ref $arg && UNIVERSAL::isa( $arg, 'UNIVERSAL' );
|
||||
}
|
||||
|
||||
|
||||
### (PROXY) METHOD: AUTOLOAD( @args )
|
||||
### Proxy method to build (non-translucent) object accessors.
|
||||
sub AUTOLOAD {
|
||||
my $self = shift;
|
||||
confess "Cannot be called as a function" unless $self && blessed $self;
|
||||
|
||||
( my $name = $AUTOLOAD ) =~ s{.*::}{};
|
||||
|
||||
### Build an accessor for extant attributes
|
||||
if ( exists $self->{$name} ) {
|
||||
|
||||
### Define an accessor for this attribute
|
||||
my $method = sub {
|
||||
my $closureSelf = shift or confess "Cannot be called as a function";
|
||||
$closureSelf->{$name} = shift if @_;
|
||||
return $closureSelf->{$name};
|
||||
};
|
||||
|
||||
### Install the new method in the symbol table
|
||||
NO_STRICT_REFS: {
|
||||
no strict 'refs';
|
||||
*{$AUTOLOAD} = $method;
|
||||
}
|
||||
|
||||
### Now jump to the new method after sticking the self-ref back onto the
|
||||
### stack
|
||||
unshift @_, $self;
|
||||
goto &$AUTOLOAD;
|
||||
}
|
||||
|
||||
### Try to delegate to our parent's version of the method
|
||||
my $parentMethod = "SUPER::$name";
|
||||
return $self->$parentMethod( @_ );
|
||||
}
|
||||
|
||||
sub DESTROY {}
|
||||
sub END {}
|
||||
|
||||
|
||||
139
livejournal/bin/ljmaint.pl
Executable file
@@ -0,0 +1,139 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# <LJDEP>
|
||||
# lib: Fcntl::, cgi-bin/ljlib.pl
|
||||
# file: bin/maint/taskinfo.txt, bin/maint/taskinfo-local.txt
|
||||
# </LJDEP>
|
||||
|
||||
use strict;
|
||||
use vars qw(%maint %maintinfo $VERBOSE);
|
||||
|
||||
unless (-d $ENV{'LJHOME'}) {
|
||||
die "\$LJHOME not set.\n";
|
||||
}
|
||||
|
||||
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
|
||||
|
||||
my $MAINT = "$LJ::HOME/bin/maint";
|
||||
|
||||
load_tasks();
|
||||
|
||||
$VERBOSE = 1; # 0=quiet, 1=normal, 2=verbose
|
||||
|
||||
if (@ARGV)
|
||||
{
|
||||
## check the correctness of the taskinfo files
|
||||
if ($ARGV[0] eq "--check") {
|
||||
foreach my $task (keys %maintinfo)
|
||||
{
|
||||
my %loaded;
|
||||
my $source = $maintinfo{$task}->{'source'};
|
||||
unless (-e "$MAINT/$source") {
|
||||
print "$task references missing file $source\n";
|
||||
next;
|
||||
}
|
||||
unless ($loaded{$source}++) {
|
||||
require "$MAINT/$source";
|
||||
}
|
||||
unless (ref $maint{$task} eq "CODE") {
|
||||
print "$task is missing code in $source\n";
|
||||
}
|
||||
}
|
||||
exit 0;
|
||||
}
|
||||
|
||||
if ($ARGV[0] =~ /^-v(.?)/) {
|
||||
if ($1 eq "") { $VERBOSE = 2; }
|
||||
else { $VERBOSE = $1; }
|
||||
shift @ARGV;
|
||||
}
|
||||
|
||||
my @targv;
|
||||
my $hit_colon = 0;
|
||||
foreach my $arg (@ARGV)
|
||||
{
|
||||
if ($arg eq ';') {
|
||||
$hit_colon = 1;
|
||||
run_task(@targv);
|
||||
@targv = ();
|
||||
next;
|
||||
}
|
||||
push @targv, $arg;
|
||||
}
|
||||
|
||||
if ($hit_colon) {
|
||||
# new behavior: task1 arg1 arg2 ; task2 arg arg2
|
||||
run_task(@targv);
|
||||
} else {
|
||||
# old behavior: task1 task2 task3 (no args, ever)
|
||||
foreach my $task (@targv) {
|
||||
run_task($task);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
print "Available tasks: \n";
|
||||
foreach (sort keys %maintinfo) {
|
||||
print " $_ - $maintinfo{$_}->{'des'}\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub run_task
|
||||
{
|
||||
my $task = shift;
|
||||
return unless ($task);
|
||||
my @args = @_;
|
||||
|
||||
print "Running task '$task':\n\n" if ($VERBOSE >= 1);
|
||||
unless ($maintinfo{$task}) {
|
||||
print "Unknown task '$task'\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$LJ::LJMAINT_VERBOSE = $VERBOSE;
|
||||
|
||||
require "$MAINT/$maintinfo{$task}->{'source'}";
|
||||
my $opts = $maintinfo{$task}{opts} || {};
|
||||
my $lock = undef;
|
||||
my $lockname = "mainttask-$task";
|
||||
if ($opts->{'locking'} eq "per_host") {
|
||||
$lockname .= "-$LJ::SERVER_NAME";
|
||||
}
|
||||
unless ($opts->{no_locking} ||
|
||||
($lock = LJ::locker()->trylock($lockname))
|
||||
) {
|
||||
print "Task '$task' already running ($DDLockClient::Error). Quitting.\n" if $VERBOSE >= 1;
|
||||
exit 0;
|
||||
}
|
||||
|
||||
eval {
|
||||
$maint{$task}->(@args);
|
||||
};
|
||||
if ( $@ ) {
|
||||
print STDERR "ERROR> task $task died: $@\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub load_tasks
|
||||
{
|
||||
foreach my $filename (qw(taskinfo.txt taskinfo-local.txt))
|
||||
{
|
||||
my $file = "$MAINT/$filename";
|
||||
open (F, $file) or next;
|
||||
my $source;
|
||||
while (my $l = <F>) {
|
||||
next if ($l =~ /^\#/);
|
||||
if ($l =~ /^(\S+):\s*/) {
|
||||
$source = $1;
|
||||
next;
|
||||
}
|
||||
if ($l =~ /^\s*(\w+)\s*-\s*(.+?)\s*$/) {
|
||||
$maintinfo{$1}->{'des'} = $2;
|
||||
$maintinfo{$1}->{'source'} = $source;
|
||||
}
|
||||
}
|
||||
close (F);
|
||||
}
|
||||
}
|
||||
|
||||
202
livejournal/bin/ljsysban.pl
Executable file
@@ -0,0 +1,202 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
|
||||
use strict;
|
||||
use Getopt::Long;
|
||||
|
||||
# parse input options
|
||||
my ($list, $add, $modify, $banid, $status, $bandate, $banuntil, $what, $value, $note);
|
||||
exit 1 unless GetOptions('list' => \$list,
|
||||
'add' => \$add,
|
||||
'modify' => \$modify,
|
||||
'banid=s' => \$banid,
|
||||
'status=s' => \$status,
|
||||
'bandate=s' => \$bandate,
|
||||
'banuntil=s' => \$banuntil,
|
||||
'what=s' => \$what,
|
||||
'value=s' => \$value,
|
||||
'note=s' => \$note,
|
||||
);
|
||||
|
||||
# did they give valid input?
|
||||
my $an_opt = ($what || $value || $status || $bandate || $banuntil || $note);
|
||||
unless (($list && (($banid && ! $an_opt) || (! $banid && $an_opt)) ||
|
||||
($add && $what && $value) ||
|
||||
($modify && $banid && $an_opt))) {
|
||||
|
||||
die "Usage: ljsysban.pl [opts]\n\n" .
|
||||
" --list { <--banid=?> | or one of:\n" .
|
||||
" [--what=? --status=? --bandate=datetime --banuntil=datetime\n" .
|
||||
" --value=? --note=?]\n" .
|
||||
" }\n\n" .
|
||||
" --add <--what=? --value=?\n" .
|
||||
" [--status=? --bandate=datetime --banuntil=datetime --note=?]>\n\n" .
|
||||
" --modify <--banid=?>\n" .
|
||||
" [--status=? --bandate=datetime --banuntil=datetime --value=? --note=?]\n\n";
|
||||
}
|
||||
|
||||
# now load in the beast
|
||||
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
# list bands
|
||||
if ($list) {
|
||||
my $where;
|
||||
if ($banid) {
|
||||
$where = "banid=" . $dbh->quote($banid);
|
||||
} else {
|
||||
my @where = ();
|
||||
push @where, ("what=" . $dbh->quote($what)) if $what;
|
||||
push @where, ("value=" . $dbh->quote($value)) if $value;
|
||||
push @where, ("status=" . $dbh->quote($status)) if $status;
|
||||
push @where, ("bandate=" . $dbh->quote($bandate)) if $bandate;
|
||||
push @where, ("banuntil=" . $dbh->quote($banuntil)) if $banuntil;
|
||||
push @where, ("note=" . $dbh->quote($note)) if $note;
|
||||
$where = join(" AND ", @where);
|
||||
}
|
||||
|
||||
my $sth = $dbh->prepare("SELECT * FROM sysban WHERE $where ORDER BY bandate ASC");
|
||||
$sth->execute;
|
||||
my $ct;
|
||||
while (my $ban = $sth->fetchrow_hashref) {
|
||||
print "> banid: $ban->{'banid'}, status: $ban->{'status'}, ";
|
||||
print "bandate: " . ($ban->{'bandate'} ? $ban->{'bandate'} : "BOT") . ", ";
|
||||
print "banuntil: " . ($ban->{'banuntil'} ? $ban->{'banuntil'} : "EOT") . "\n";
|
||||
print "> what: $ban->{'what'}, value: $ban->{'value'}\n";
|
||||
print "> note: $ban->{'note'}\n" if $ban->{'note'};
|
||||
print "\n";
|
||||
$ct++;
|
||||
}
|
||||
print "\n\tNO MATCHES\n\n" unless $ct;
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
# add new ban
|
||||
if ($add) {
|
||||
|
||||
$status = ($status eq 'expired' ? 'expired' : 'active');
|
||||
|
||||
$dbh->do("INSERT INTO sysban (status, what, value, note, bandate, banuntil)" .
|
||||
"VALUES (?, ?, ?, ?, " .
|
||||
($bandate ? $dbh->quote($bandate) : 'NOW()') . ", " .
|
||||
($banuntil ? $dbh->quote($banuntil) : 'NULL') . ")",
|
||||
undef, $status, $what, $value, $note);
|
||||
die $dbh->errstr if $dbh->err;
|
||||
my $insertid = $dbh->{'mysql_insertid'};
|
||||
|
||||
if ($what eq 'ip') {
|
||||
LJ::procnotify_add("ban_ip", { 'ip' => $value,
|
||||
'exptime' => LJ::mysqldate_to_time($banuntil) });
|
||||
LJ::MemCache::delete("sysban:ip");
|
||||
}
|
||||
if ($what eq 'uniq') {
|
||||
LJ::procnotify_add("ban_uniq", { 'uniq' => $value,
|
||||
'exptime' => LJ::mysqldate_to_time($banuntil) });
|
||||
LJ::MemCache::delete("sysban:uniq");
|
||||
}
|
||||
|
||||
# log in statushistory
|
||||
LJ::statushistory_add(0, 0, 'sysban_add',
|
||||
"banid=$insertid; status=$status; " .
|
||||
"bandate=" . ($bandate || LJ::mysql_time()) . "; " .
|
||||
"banuntil=" . ($banuntil || 'NULL') . "; " .
|
||||
"what=$what; value=$value; " .
|
||||
"note=$note;");
|
||||
|
||||
print "CREATED: banid=$insertid\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
# modify existing ban
|
||||
if ($modify) {
|
||||
|
||||
# load selected ban
|
||||
my $ban = $dbh->selectrow_hashref("SELECT * FROM sysban WHERE banid=?", undef, $banid);
|
||||
die $dbh->errstr if $dbh->err;
|
||||
|
||||
my @set = ();
|
||||
|
||||
# ip/uniq ban and we're going to change the value
|
||||
if (($value && $value ne $ban->{'value'}) ||
|
||||
$banuntil && $banuntil ne $ban->{'banuntil'} ||
|
||||
($status && $status ne $ban->{'status'} && $status eq 'expired')) {
|
||||
|
||||
if ($ban->{'what'} eq 'ip') {
|
||||
LJ::procnotify_add("unban_ip", { 'ip' => $value || $ban->{'value'}});
|
||||
LJ::MemCache::delete("sysban:ip");
|
||||
}
|
||||
|
||||
if ($ban->{'what'} eq 'uniq') {
|
||||
LJ::procnotify_add("unban_uniq", { 'uniq' => $value || $ban->{'value'} });
|
||||
LJ::MemCache::delete("sysban:uniq");
|
||||
}
|
||||
}
|
||||
|
||||
# what - must have a value
|
||||
if ($what && $what ne $ban->{'what'}) {
|
||||
$ban->{'what'} = $what;
|
||||
push @set, "what=" . $dbh->quote($ban->{'what'});
|
||||
}
|
||||
|
||||
# ip/uniq ban and we are going to change the value
|
||||
if (($value && $value ne $ban->{'value'}) ||
|
||||
$banuntil && $banuntil ne $ban->{'banuntil'} ||
|
||||
($status && $status ne $ban->{'status'} && $status eq 'active')) {
|
||||
|
||||
my $new_banuntil = $banuntil || $ban->{'banuntil'};
|
||||
|
||||
if ($ban->{'what'} eq 'ip') {
|
||||
LJ::procnotify_add("ban_ip", { 'ip' => $value || $ban->{'value'},
|
||||
'exptime' => LJ::mysqldate_to_time($new_banuntil) });
|
||||
LJ::MemCache::delete("sysban:ip");
|
||||
}
|
||||
|
||||
if ($ban->{'what'} eq 'uniq') {
|
||||
LJ::procnotify_add("ban_uniq", { 'uniq' => $value || $ban->{'value'},
|
||||
'exptime' => LJ::mysqldate_to_time($new_banuntil) });
|
||||
LJ::MemCache::delete("sysban:uniq");
|
||||
}
|
||||
}
|
||||
|
||||
# value - must have a value
|
||||
if ($value && $value ne $ban->{'value'}) {
|
||||
$ban->{'value'} = $value;
|
||||
push @set, "value=" . $dbh->quote($ban->{'value'});
|
||||
}
|
||||
|
||||
# status - must have a value
|
||||
if ($status && $status ne $ban->{'status'}) {
|
||||
$ban->{'status'} = ($status eq 'expired' ? 'expired' : 'active');
|
||||
push @set, "status=" . $dbh->quote($ban->{'status'});
|
||||
}
|
||||
|
||||
# banuntil
|
||||
if ($banuntil && $banuntil ne $ban->{'banuntil'}) {
|
||||
$ban->{'banuntil'} = ($banuntil && $banuntil ne 'NULL') ? $banuntil : 0;
|
||||
push @set, "banuntil=" . ($ban->{'banuntil'} ? $dbh->quote($ban->{'banuntil'}) : 'NULL');
|
||||
}
|
||||
|
||||
# bandate - must have a value
|
||||
if ($bandate && $bandate ne $ban->{'bandate'}) {
|
||||
$ban->{'bandate'} = $bandate;
|
||||
push @set, "bandate=" . $dbh->quote($ban->{'bandate'});
|
||||
}
|
||||
|
||||
# note - can be changed to blank
|
||||
if (defined $note && $note ne $ban->{'note'}) {
|
||||
$ban->{'note'} = $note;
|
||||
push @set, "note=" . $dbh->quote($ban->{'note'});
|
||||
}
|
||||
|
||||
# do update
|
||||
$dbh->do("UPDATE sysban SET " . join(", ", @set) . " WHERE banid=?", undef, $ban->{'banid'});
|
||||
|
||||
# log in statushistory
|
||||
my $msg; map { $msg .= " " if $msg;
|
||||
$msg .= "$_=$ban->{$_};" } qw(banid status bandate banuntil what value note);
|
||||
LJ::statushistory_add(0, 0, 'sysban_mod', $msg);
|
||||
|
||||
print "MODIFIED: banid=$banid\n";
|
||||
exit;
|
||||
}
|
||||
1149
livejournal/bin/ljubackup.pl
Executable file
1336
livejournal/bin/ljumover.pl
Executable file
110
livejournal/bin/logsummarize.pl
Executable file
@@ -0,0 +1,110 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
|
||||
use strict;
|
||||
|
||||
unless (-d $ENV{'LJHOME'}) {
|
||||
die "\$LJHOME not set.\n";
|
||||
}
|
||||
|
||||
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
|
||||
|
||||
my $db = LJ::get_dbh("logs");
|
||||
unless ($db) {
|
||||
die "No 'logs' db handle found.\n";
|
||||
}
|
||||
$db->{'InactiveDestroy'} = 1;
|
||||
my $sth;
|
||||
|
||||
my %table;
|
||||
$sth = $db->prepare("SHOW TABLES LIKE 'access%'");
|
||||
$sth->execute;
|
||||
while (my $t = $sth->fetchrow_array) {
|
||||
$table{$t} = 1;
|
||||
}
|
||||
|
||||
my @need_summary = sort grep { /^access\d{8,8}$/ } keys %table;
|
||||
pop @need_summary; # don't summarize the current day yet.
|
||||
|
||||
my $nsum_total = @need_summary;
|
||||
my $nsum_ct = 0;
|
||||
|
||||
use constant F_SERVER => 0;
|
||||
use constant F_LANG => 1;
|
||||
use constant F_METHOD => 2;
|
||||
use constant F_VHOST => 3;
|
||||
use constant F_URI => 4;
|
||||
use constant F_STATUS => 5;
|
||||
use constant F_CTYPE => 6;
|
||||
use constant F_BYTES => 7;
|
||||
use constant F_BROWSER => 8;
|
||||
use constant F_REF => 9;
|
||||
|
||||
foreach my $table (@need_summary)
|
||||
{
|
||||
$nsum_ct++;
|
||||
print "Summarizing $table ($nsum_ct/$nsum_total)\n";
|
||||
|
||||
my $row_total = $db->selectrow_array("SELECT COUNT(*) FROM $table");
|
||||
print " rows = $row_total\n";
|
||||
|
||||
my $sth = $db->prepare("SELECT server, langpref, method, vhost, uri, ".
|
||||
" status, ctype, bytes, browser, ref ".
|
||||
"FROM $table");
|
||||
$sth->{'mysql_use_result'} = 1;
|
||||
$sth->execute;
|
||||
my ($r, $row_ct);
|
||||
my %st;
|
||||
while ($r = $sth->fetchrow_arrayref) {
|
||||
$row_ct++;
|
||||
if ($row_ct % 10000 == 0) {
|
||||
printf " $row_ct/$row_total (%%%.02f)\n", 100*$row_ct/$row_total;
|
||||
}
|
||||
|
||||
next if ($r->[F_URI] =~ m!^/userpic!);
|
||||
|
||||
|
||||
$st{'count'}->{'total'}++;
|
||||
$st{'count'}->{'bytes'} += $r->[F_BYTES];
|
||||
$st{'http_meth'}->{$r->[F_METHOD]}++;
|
||||
$st{'http_status'}->{$r->[F_STATUS]}++;
|
||||
$st{'browser'}->{$r->[F_BROWSER]}++;
|
||||
$st{'host'}->{$r->[F_VHOST]}++;
|
||||
|
||||
if ($r->[F_URI] =~ s!^/(users/|~)\w+/?!/users/*/!) {
|
||||
$r->[F_URI] =~ s!day/\d\d\d\d/\d\d/\d\d!day!;
|
||||
$r->[F_URI] =~ s!calendar/\d\d\d\d!calendar!;
|
||||
}
|
||||
|
||||
if ($r->[F_VHOST] =~ /^(www\.)livejournal\.com$/) {
|
||||
$st{'uri'}->{$r->[F_URI]}++;
|
||||
} else {
|
||||
$r->[F_URI] =~ s!day/\d\d\d\d/\d\d/\d\d!day!;
|
||||
$r->[F_URI] =~ s!calendar/\d\d\d\d!calendar!;
|
||||
$st{'uri'}->{"user:" . $r->[F_URI]}++;
|
||||
}
|
||||
|
||||
my $ref = $r->[F_REF];
|
||||
if ($ref =~ m!^http://([^/]+)!) {
|
||||
$ref = $1;
|
||||
$st{'referer'}->{$ref}++ unless ($ref =~ /livejournal\.com$/);
|
||||
}
|
||||
}
|
||||
|
||||
my $tabledate = $table;
|
||||
$tabledate =~ s/^access//;
|
||||
|
||||
print " Writing stats file.\n";
|
||||
open (S, "| gzip -c > $ENV{'LJHOME'}/var/stats-$tabledate.gz") or die "Can't open stats file";
|
||||
foreach my $cat (sort keys %st) {
|
||||
print "Writing cat: $cat\n";
|
||||
foreach my $k (sort { $st{$cat}->{$b} <=> $st{$cat}->{$a} } keys %{$st{$cat}}) {
|
||||
print S "$cat\t$k\t$st{$cat}->{$k}\n"
|
||||
or die "Failed writing to stats-$tabledate.gz. Device full?\n";
|
||||
}
|
||||
}
|
||||
close S;
|
||||
|
||||
$db->do("DROP TABLE $table");
|
||||
}
|
||||
|
||||
536
livejournal/bin/mailgated.pl
Executable file
@@ -0,0 +1,536 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# <LJDEP>
|
||||
# lib: MIME::Parser, Mail::Address, cgi-bin/ljlib.pl, cgi-bin/supportlib.pl
|
||||
# </LJDEP>
|
||||
|
||||
use strict;
|
||||
use lib "$ENV{LJHOME}/cgi-bin";
|
||||
use Getopt::Long;
|
||||
use Sys::Hostname;
|
||||
use MIME::Parser;
|
||||
use Mail::Address;
|
||||
use Proc::ProcessTable;
|
||||
use Unicode::MapUTF8 ();
|
||||
use File::Temp ();
|
||||
use File::Path ();
|
||||
use Danga::Daemon;
|
||||
|
||||
require "$ENV{LJHOME}/cgi-bin/ljconfig.pl";
|
||||
|
||||
# worker globals
|
||||
use vars qw/ $mailspool $mailspool_new $workdir $maxloop
|
||||
$hostname $locktype $opt /;
|
||||
$opt = {};
|
||||
Getopt::Long::GetOptions $opt, qw/ workdir=s lock=s maxloop=s /;
|
||||
|
||||
# mailspool should match the MTA delivery location.
|
||||
$mailspool = $LJ::MAILSPOOL || "$ENV{'LJHOME'}/mail";
|
||||
$mailspool_new = "$mailspool/new";
|
||||
|
||||
# setup defaults
|
||||
$hostname = $1 if Sys::Hostname::hostname() =~ /^([\w-]+)/;
|
||||
$locktype = $opt->{'lock'} || $LJ::MAILLOCK;
|
||||
die "Invalid lock mechanism specified. Set \$LJ::MAILLOCK or use --lock.\n"
|
||||
unless $locktype =~ /hostname|none|ddlockd/i;
|
||||
$workdir = $opt->{'workdir'} || "$mailspool/tmp";
|
||||
$maxloop = $opt->{'maxloop'} || 100;
|
||||
|
||||
# sanity checks
|
||||
die "Invalid mailspool: $mailspool\n" unless -d $mailspool_new;
|
||||
die "Unable to read mailspool: $mailspool\n" unless -r $mailspool;
|
||||
|
||||
Danga::Daemon::daemonize(
|
||||
|
||||
\&worker,
|
||||
{
|
||||
interval => 10,
|
||||
shedprivs => 'lj',
|
||||
|
||||
listenport => 15000,
|
||||
listencode => \&cmd_interface,
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
# main event loop for mailgated.
|
||||
# examine mailspool, populate queues, and call
|
||||
# process() as needed.
|
||||
sub worker
|
||||
{
|
||||
require "$ENV{'LJHOME'}/cgi-bin/ljemailgateway.pl";
|
||||
require "$ENV{'LJHOME'}/cgi-bin/supportlib.pl";
|
||||
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
|
||||
require "$ENV{'LJHOME'}/cgi-bin/sysban.pl";
|
||||
$| = 1;
|
||||
|
||||
debug("Starting loop:");
|
||||
cleanup();
|
||||
LJ::start_request();
|
||||
|
||||
# Get list of files to process.
|
||||
# If a file simply exists in the mailspool, it needs attention.
|
||||
debug("\tprocess");
|
||||
opendir( MDIR, $mailspool_new )
|
||||
|| die "Unable to open mailspool $mailspool_new: $!\n";
|
||||
my @all_files = readdir(MDIR);
|
||||
closedir MDIR;
|
||||
|
||||
# Separate new messages from retries.
|
||||
# Hostname as part of the filename is Maildir specification -
|
||||
# use 'hostname' locking to be safe across NFS.
|
||||
my ( @new_messages, @retry_messages );
|
||||
foreach (@all_files) {
|
||||
next if /^\./;
|
||||
next if $locktype eq 'hostname' && !/\.$hostname\b/;
|
||||
if ( get_pcount($_) == 0 ) { # new message
|
||||
push @new_messages, $_;
|
||||
}
|
||||
else { # message retry
|
||||
push @retry_messages, $_;
|
||||
}
|
||||
}
|
||||
|
||||
# Make sure at least half of our processesing
|
||||
# queue is made up of new messages.
|
||||
# Randomize, so if we're running multiple mailgated
|
||||
# processess, they'll be more likely to be working on
|
||||
# different messages.
|
||||
rand_array( \@retry_messages, int( $maxloop / 2 ) ); # half queue max
|
||||
# fill the rest of the queue with new messages.
|
||||
rand_array( \@new_messages, $maxloop - ( scalar @retry_messages ) );
|
||||
|
||||
# do the work
|
||||
foreach my $file ( @new_messages, @retry_messages ) {
|
||||
my $lock;
|
||||
if ( get_pcount($file) % 20 == 0 ) { # only retry every 20th iteration
|
||||
if ( lc($locktype) eq 'ddlockd' ) {
|
||||
$lock = LJ::locker()->trylock("mailgated-$file");
|
||||
next unless $lock;
|
||||
}
|
||||
eval { process($file); };
|
||||
if ($@) {
|
||||
debug("\t\t$@");
|
||||
set_pcount($file);
|
||||
}
|
||||
}
|
||||
else {
|
||||
set_pcount($file);
|
||||
}
|
||||
}
|
||||
|
||||
debug("\tdone\n");
|
||||
LJ::end_request();
|
||||
}
|
||||
|
||||
# additional command line options
|
||||
sub cmd_interface
|
||||
{
|
||||
my ( $line, $s, $c, $codeloop, $codeopts ) = @_;
|
||||
|
||||
if ($line =~ /help/i) {
|
||||
foreach (sort qw/ ping pids reload stop queuesize status /) {
|
||||
print $c "\t$_\n";
|
||||
}
|
||||
print $c ".\nOK\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ($line =~ /queuesize/) {
|
||||
if (! opendir(MDIR, $mailspool_new)) {
|
||||
print $c "Unable to open mailspool $mailspool_new: $!\n";
|
||||
} else {
|
||||
my $count = 0;
|
||||
foreach (readdir(MDIR)) {
|
||||
next if /^\./;
|
||||
$count++;
|
||||
}
|
||||
closedir MDIR;
|
||||
print $c "$count\n";
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ($line =~ /status/) {
|
||||
my $pid = $Danga::Daemon::pid;
|
||||
my $t = new Proc::ProcessTable;
|
||||
my $state;
|
||||
|
||||
foreach my $p ( @{$t->table} ){
|
||||
$state = $p->state if $p->pid == $pid;
|
||||
}
|
||||
|
||||
print $c "mailgate ";
|
||||
print $c ($state ne 'defunct' && kill 0, $pid) ? "running" : "down";
|
||||
print $c "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
# Remove prior run workdirs.
|
||||
# File::Temp's CLEANUP only works upon program exit.
|
||||
sub cleanup
|
||||
{
|
||||
debug("\tcleanup");
|
||||
my $now = time();
|
||||
unless ( opendir( TMP, $workdir ) ) {
|
||||
debug("\t\tCan't open workdir $workdir: $!");
|
||||
return;
|
||||
}
|
||||
my $limit = 0;
|
||||
foreach ( readdir(TMP) ) {
|
||||
next unless /^ljmailgate_/;
|
||||
last if $limit >= 50;
|
||||
$limit++;
|
||||
my $modtime = ( stat("$workdir/$_") )[9];
|
||||
if ( $now - $modtime > 300 ) {
|
||||
File::Path::rmtree("$workdir/$_");
|
||||
debug("\t\t$workdir/$_");
|
||||
}
|
||||
}
|
||||
closedir TMP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
# takes an array ref - truncates to max size and shuffles it.
|
||||
sub rand_array
|
||||
{
|
||||
my ( $array, $max ) = @_;
|
||||
|
||||
my ( @tmp, $c );
|
||||
while (@$array) {
|
||||
push( @tmp, splice( @$array, rand(@$array), 1 ) );
|
||||
last if ++$c == $max;
|
||||
}
|
||||
@$array = @tmp;
|
||||
return;
|
||||
}
|
||||
|
||||
sub set_pcount
|
||||
{
|
||||
my ( $file, $resetattempt ) = @_;
|
||||
my $attempt = get_pcount($file);
|
||||
$attempt++;
|
||||
$attempt = 0 if $resetattempt;
|
||||
|
||||
my $name = $file;
|
||||
$name =~ s/:\d+$//;
|
||||
$name = $name . ":" . $attempt;
|
||||
rename "$mailspool_new/$file", "$mailspool_new/$name";
|
||||
return 0;
|
||||
}
|
||||
|
||||
# return the number of times we've seen this
|
||||
# message in the queue
|
||||
sub get_pcount
|
||||
{
|
||||
return 0 unless shift() =~ /:(\d+)$/;
|
||||
return $1;
|
||||
}
|
||||
|
||||
# Either an unrecoverable error, or a total success. ;)
|
||||
# Regardless, we're done with this message.
|
||||
# Remove it so it isn't processed again.
|
||||
our $last_file;
|
||||
our $last_tempdir;
|
||||
|
||||
sub dequeue
|
||||
{
|
||||
my $msg = shift;
|
||||
debug("\t\t dequeued: $msg") if $msg;
|
||||
unlink("$mailspool_new/$last_file")
|
||||
|| debug("\t\t Can't unlink $last_file!");
|
||||
File::Path::rmtree($last_tempdir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
# cleanup mime tempdirs, update attempt number,
|
||||
# but don't delete the message.
|
||||
sub retry
|
||||
{
|
||||
my $msg = shift;
|
||||
debug("\t\t retrying: $msg") if $msg;
|
||||
set_pcount($last_file);
|
||||
File::Path::rmtree($last_tempdir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
# examine message contents and decide what to do
|
||||
# with it.
|
||||
sub process
|
||||
{
|
||||
my $file = shift;
|
||||
debug("\t\t$file");
|
||||
my $tmpdir =
|
||||
File::Temp::tempdir( "ljmailgate_" . 'X' x 20, DIR => $workdir );
|
||||
my $parser = new MIME::Parser;
|
||||
|
||||
# for dequeue sub:
|
||||
$last_file = $file;
|
||||
$last_tempdir = $tmpdir;
|
||||
|
||||
$parser->output_dir($tmpdir);
|
||||
|
||||
# Close the message as quickly as possible, in case
|
||||
# we need to change status mid process.
|
||||
open( MESSAGE, "$mailspool_new/$file" )
|
||||
|| debug("\t\t Can't open file: $!") && return;
|
||||
my $entity;
|
||||
eval { $entity = $parser->parse( \*MESSAGE ) };
|
||||
close MESSAGE;
|
||||
return dequeue("Can't parse MIME") if $@;
|
||||
|
||||
my $head = $entity->head;
|
||||
$head->unfold;
|
||||
|
||||
my $subject = $head->get('Subject');
|
||||
chomp $subject;
|
||||
|
||||
# ignore spam/vacation/auto-reply messages
|
||||
if ( $subject =~ /auto.?(response|reply)/i
|
||||
|| $subject =~
|
||||
/^(Undelive|Mail System Error - |ScanMail Message: |\+\s*SPAM|Norton AntiVirus)/i
|
||||
|| $subject =~ /^(Mail Delivery Problem|Mail delivery failed)/i
|
||||
|| $subject =~ /^failure notice$/i
|
||||
|| $subject =~ /\[BOUNCED SPAM\]/i
|
||||
|| $subject =~ /^Symantec AVF /i
|
||||
|| $subject =~ /Attachment block message/i
|
||||
|| $subject =~ /Use this patch immediately/i
|
||||
|| $subject =~ /^YOUR PAYPAL\.COM ACCOUNT EXPIRES/i
|
||||
|| $subject =~ /^don\'t be late! ([\w\-]{1,15})$/i
|
||||
|| $subject =~ /^your account ([\w\-]{1,15})$/i )
|
||||
{
|
||||
return dequeue("Spam");
|
||||
}
|
||||
|
||||
# quick and dirty (and effective) scan for viruses
|
||||
return dequeue("Virus found") if virus_check($entity);
|
||||
|
||||
# see if it's a post-by-email
|
||||
my @to = Mail::Address->parse( $head->get('To') );
|
||||
if ( scalar @to > 0 ) {
|
||||
foreach my $dest ( @to ) {
|
||||
next unless $dest->address =~ /^(\S+?)\@\Q$LJ::EMAIL_POST_DOMAIN\E$/i;
|
||||
|
||||
my $user = $1;
|
||||
|
||||
# FIXME: verify auth (extra from $user/$subject/$body), require ljprotocol.pl, do post.
|
||||
# unresolved: where to temporarily store messages before they're approved?
|
||||
# perhaps the modblob table? perhaps a column it can be used to determine
|
||||
# whether it's a moderated community post vs. an un-acked phone post.
|
||||
my $post_rv;
|
||||
my $post_msg = LJ::Emailpost::process( $entity, $user, \$post_rv );
|
||||
|
||||
return $post_rv ? dequeue($post_msg) : retry($post_msg);
|
||||
}
|
||||
}
|
||||
|
||||
# stop more spam, based on body text checks
|
||||
my $tent = LJ::Emailpost::get_entity($entity);
|
||||
$tent = LJ::Emailpost::get_entity( $entity, 'html' ) unless $tent;
|
||||
return dequeue("Can't find text or html entity") unless $tent;
|
||||
my $body = $tent->bodyhandle->as_string;
|
||||
$body = LJ::trim($body);
|
||||
|
||||
### spam
|
||||
if ( $body =~ /I send you this file in order to have your advice/i
|
||||
|| $body =~ /^Content-Type: application\/octet-stream/i
|
||||
|| $body =~ /^(Please see|See) the attached file for details\.?$/i )
|
||||
{
|
||||
return dequeue("Spam");
|
||||
}
|
||||
|
||||
|
||||
# From this point on we know it's a support request of some type,
|
||||
my $email2cat = LJ::Support::load_email_to_cat_map();
|
||||
|
||||
my $to;
|
||||
my $toarg;
|
||||
my $ignore = 0;
|
||||
foreach my $a ( @to, Mail::Address->parse( $head->get('Cc') ) ) {
|
||||
my $address = $a->address;
|
||||
my $arg;
|
||||
if ( $address =~ /^(.+)\+(.*)\@(.+)$/ ) {
|
||||
( $address, $arg ) = ( "$1\@$3", $2 );
|
||||
}
|
||||
if ( defined $LJ::ALIAS_TO_SUPPORTCAT{$address} ) {
|
||||
$address = $LJ::ALIAS_TO_SUPPORTCAT{$address};
|
||||
}
|
||||
if ( defined $email2cat->{$address} ) {
|
||||
$to = $address;
|
||||
$toarg = $arg;
|
||||
}
|
||||
$ignore = 1 if $address eq $LJ::IGNORE_EMAIL;
|
||||
$ignore = 1 if $address eq $LJ::BOGUS_EMAIL;
|
||||
}
|
||||
|
||||
return dequeue("Not deliverable to support system (no match To:)")
|
||||
unless $to;
|
||||
|
||||
my $adf = ( Mail::Address->parse( $head->get('From') ) )[0];
|
||||
return dequeue("Bogus From: header") unless $adf;
|
||||
|
||||
my $name = $adf->name;
|
||||
my $from = $adf->address;
|
||||
$subject ||= "(No Subject)";
|
||||
|
||||
# is this a reply to another post?
|
||||
if ( $toarg =~ /^(\d+)z(.+)$/ ) {
|
||||
my $spid = $1;
|
||||
my $miniauth = $2;
|
||||
my $sp = LJ::Support::load_request($spid);
|
||||
|
||||
LJ::Support::mini_auth($sp) eq $miniauth
|
||||
or die "Invalid authentication?";
|
||||
|
||||
if ( LJ::sysban_check( 'support_email', $from ) ) {
|
||||
my $msg = "Support request blocked based on email.";
|
||||
LJ::sysban_block( 0, $msg, { 'email' => $from } );
|
||||
return dequeue($msg);
|
||||
}
|
||||
|
||||
# make sure it's not locked
|
||||
return dequeue("Request is locked, can't append comment.")
|
||||
if LJ::Support::is_locked($sp);
|
||||
|
||||
# valid. need to strip out stuff now with authcodes:
|
||||
$body =~ s!http://.+/support/act\.bml\S+![snipped]!g;
|
||||
$body =~ s!\+(\d)+z\w{1,10}\@!\@!g;
|
||||
$body =~ s!&auth=\S+!!g;
|
||||
|
||||
## try to get rid of reply stuff.
|
||||
# Outlook Express:
|
||||
$body =~ s!(\S+.*?)-{4,10} Original Message -{4,10}.+!$1!s;
|
||||
|
||||
# Pine/Netscape
|
||||
$body =~ s!(\S+.*?)\bOn [^\n]+ wrote:\n.+!$1!s;
|
||||
|
||||
# append the comment, re-open the request if necessary
|
||||
my $splid = LJ::Support::append_request(
|
||||
$sp,
|
||||
{
|
||||
'type' => 'comment',
|
||||
'body' => $body,
|
||||
}
|
||||
)
|
||||
or return dequeue("Error appending request?");
|
||||
|
||||
LJ::Support::touch_request($spid);
|
||||
|
||||
return dequeue("Support reply success");
|
||||
}
|
||||
|
||||
# Now see if we want to ignore this particular email and bounce it back with
|
||||
# the contents from a file. Check $LJ::DENY_REQUEST_FROM_EMAIL first. Note
|
||||
# that this will only bounce initial emails; if a user replies to an email
|
||||
# from a request that's open, it'll be accepted above.
|
||||
my ( $content_file, $content );
|
||||
if ( %LJ::DENY_REQUEST_FROM_EMAIL && $LJ::DENY_REQUEST_FROM_EMAIL{$to} ) {
|
||||
$content_file = $LJ::DENY_REQUEST_FROM_EMAIL{$to};
|
||||
$content = LJ::load_include($content_file);
|
||||
}
|
||||
if ( $content_file && $content ) {
|
||||
|
||||
# construct mail to send to user
|
||||
my $email = <<EMAIL_END;
|
||||
$content
|
||||
|
||||
Your original message:
|
||||
|
||||
$body
|
||||
EMAIL_END
|
||||
|
||||
# send the message
|
||||
LJ::send_mail(
|
||||
{
|
||||
'to' => $from,
|
||||
'from' => $LJ::BOGUS_EMAIL,
|
||||
'subject' => "Your Email to $to",
|
||||
'body' => $email,
|
||||
'wrap' => 1,
|
||||
}
|
||||
);
|
||||
|
||||
# all done
|
||||
return dequeue("Support request bounced to origin");
|
||||
}
|
||||
|
||||
# make a new post.
|
||||
my @errors;
|
||||
|
||||
# convert email body to utf-8
|
||||
my $content_type = $head->get('Content-type:');
|
||||
my $charset = $1
|
||||
if $content_type =~ /\bcharset=[\'\"]?(\S+?)[\'\"]?[\s\;]/i;
|
||||
if ( defined($charset)
|
||||
&& $charset !~ /^UTF-?8$/i
|
||||
&& Unicode::MapUTF8::utf8_supported_charset($charset) )
|
||||
{
|
||||
$body =
|
||||
Unicode::MapUTF8::to_utf8(
|
||||
{ -string => $body, -charset => $charset } );
|
||||
}
|
||||
|
||||
my $spid = LJ::Support::file_request(
|
||||
\@errors,
|
||||
{
|
||||
'spcatid' => $email2cat->{$to}->{'spcatid'},
|
||||
'subject' => $subject,
|
||||
'reqtype' => 'email',
|
||||
'reqname' => $name,
|
||||
'reqemail' => $from,
|
||||
'body' => $body,
|
||||
}
|
||||
);
|
||||
|
||||
if (@errors) {
|
||||
# FIXME: detect trasient vs. permanent errors (changes to
|
||||
# file_request above, probably) and either dequeue or try
|
||||
# later
|
||||
return dequeue("Support errors: @errors");
|
||||
}
|
||||
else {
|
||||
return dequeue("Support request success");
|
||||
}
|
||||
}
|
||||
|
||||
# returns true on found virus
|
||||
sub virus_check
|
||||
{
|
||||
my $entity = shift;
|
||||
return unless $entity;
|
||||
|
||||
my @exe = LJ::Emailpost::get_entity( $entity, 'all' );
|
||||
return unless scalar @exe;
|
||||
|
||||
# If an attachment's encoding begins with one of these strings,
|
||||
# we want to completely drop the message.
|
||||
# (Other 'clean' attachments are silently ignored, and the
|
||||
# message is allowed.)
|
||||
my @virus_sigs =
|
||||
qw(
|
||||
TVqQAAMAA TVpQAAIAA TVpAALQAc TVpyAXkAX TVrmAU4AA
|
||||
TVrhARwAk TVoFAQUAA TVoAAAQAA TVoIARMAA TVouARsAA
|
||||
TVrQAT8AA UEsDBBQAA UEsDBAoAAA
|
||||
R0lGODlhaAA7APcAAP///+rp6puSp6GZrDUjUUc6Zn53mFJMdbGvvVtXh2xre8bF1x8cU4yLprOy
|
||||
);
|
||||
|
||||
# get the length of the longest virus signature
|
||||
my $maxlength =
|
||||
length( ( sort { length $b <=> length $a } @virus_sigs )[0] );
|
||||
$maxlength = 1024 if $maxlength >= 1024; # capped at 1k
|
||||
|
||||
foreach my $part (@exe) {
|
||||
my $contents = $part->stringify_body;
|
||||
$contents = substr $contents, 0, $maxlength;
|
||||
|
||||
foreach (@virus_sigs) {
|
||||
return 1 if index( $contents, $_ ) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
86
livejournal/bin/maint/bday.pl
Executable file
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
|
||||
use strict;
|
||||
use vars qw(%maint);
|
||||
|
||||
$maint{'bdaymail'} = sub
|
||||
{
|
||||
my $dbr = LJ::get_db_reader();
|
||||
my $sth;
|
||||
|
||||
# get everybody whose birthday is today.
|
||||
$sth = $dbr->prepare("SELECT u.userid, u.user, u.name, u.email ".
|
||||
"FROM user u, userusage uu WHERE u.userid=uu.userid AND ".
|
||||
"u.bdate IS NOT NULL AND u.status='A' AND ".
|
||||
"u.statusvis='V' AND u.bdate <> '0000-00-00' AND ".
|
||||
"MONTH(NOW())=MONTH(u.bdate) AND DAYOFMONTH(NOW())=DAYOFMONTH(u.bdate) ".
|
||||
"AND uu.timeupdate > DATE_SUB(NOW(), INTERVAL 1 MONTH) AND ".
|
||||
"u.journaltype='P'");
|
||||
$sth->execute;
|
||||
my @bdays; push @bdays, $_ while ($_ = $sth->fetchrow_hashref);
|
||||
$sth->finish;
|
||||
|
||||
# go through each birthday person and tell them happy birthday.
|
||||
foreach my $bu (@bdays)
|
||||
{
|
||||
my ($user, $userid, $name, $email) = map { $bu->{$_} } qw(user userid name email);
|
||||
print "$user ($userid) .. $name .. $email\n";
|
||||
|
||||
LJ::send_mail({
|
||||
'to' => $email,
|
||||
'toname' => $name,
|
||||
'subject' => "Happy Birthday!",
|
||||
'from' => $LJ::ADMIN_EMAIL,
|
||||
'fromname' => $LJ::SITENAME,
|
||||
'body' => ("Happy Birthday $name!!\n\n".
|
||||
"According to our records, today is your birthday... everybody here ".
|
||||
"at $LJ::SITENAME would like to wish you a happy birthday!\n\n".
|
||||
"If you have any interesting birthday stories to share, do let us know! ".
|
||||
"Or better, email them to us and also update your LiveJournal with them. ".
|
||||
":) And if you have any questions/comments about the service in general, ".
|
||||
"let us know too... we're real people, not a huge corporation, so we read ".
|
||||
"and try to reply to all email.\n\n".
|
||||
"Anyway... the point of this email was originally just HAPPY BIRTHDAY!\n\n".
|
||||
"--\n$LJ::SITENAME\n$LJ::SITEROOT/\n"),
|
||||
});
|
||||
|
||||
# and now, tell people that list them as friends.
|
||||
$sth = $dbr->prepare("SELECT u.user, u.name, u.email ".
|
||||
"FROM user u, friends f, userprop up, userproplist upl, userusage uu ".
|
||||
"WHERE f.friendid=$userid AND f.userid=u.userid AND ".
|
||||
"up.userid=u.userid AND upl.upropid=up.upropid AND uu.userid=u.userid AND ".
|
||||
"upl.name='opt_bdaymail' AND up.value='1' AND ".
|
||||
"u.journaltype='P' AND u.status='A' AND u.statusvis='V' AND ".
|
||||
"uu.timeupdate>DATE_SUB(NOW(), INTERVAL 1 MONTH) AND ".
|
||||
"u.userid <> $userid");
|
||||
$sth->execute;
|
||||
if ($dbr->err) { die $dbr->errstr; }
|
||||
my @friendof; push @friendof, $_ while ($_ = $sth->fetchrow_hashref);
|
||||
|
||||
# possesive es
|
||||
my $s = ($name =~ /s$/i) ? "'" : "'s";
|
||||
|
||||
foreach my $fu (@friendof)
|
||||
{
|
||||
my ($fuser, $fname, $femail) = map { $fu->{$_} } qw(user name email);
|
||||
print " mail $fuser about $user...\n";
|
||||
|
||||
LJ::send_mail({
|
||||
'to' => $femail,
|
||||
'toname' => $fname,
|
||||
'subject' => "Birthday Reminder!",
|
||||
'from' => $LJ::ADMIN_EMAIL,
|
||||
'fromname' => $LJ::SITENAME,
|
||||
'body' => ("This is a reminder that today is $name$s birthday ".
|
||||
"(LiveJournal user: $user). You have $name listed as ".
|
||||
"a friend in your LiveJournal, so we thought this ".
|
||||
"reminder would be useful.".
|
||||
"\n\n--\n$LJ::SITENAME\n$LJ::SITEROOT/\n"),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
361
livejournal/bin/maint/captcha.pl
Executable file
@@ -0,0 +1,361 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use vars qw(%maint %maintinfo);
|
||||
|
||||
use LJ::Captcha qw{};
|
||||
use LJ::Blob qw{};
|
||||
use File::Temp qw{tempdir};
|
||||
use File::Path qw{rmtree};
|
||||
use File::Spec qw{};
|
||||
|
||||
our ( $FakeUserId, $ClusterId, $Digits, $DigitCount,
|
||||
$ExpireThresUser, $ExpireThresNoUser );
|
||||
|
||||
# Data for code-generation
|
||||
$Digits = "abcdefghkmnpqrstuvwzyz23456789";
|
||||
$DigitCount = length( $Digits );
|
||||
|
||||
# Maximum age of answered captchas. this is just
|
||||
# for double-click protection.
|
||||
$ExpireThresUser = 2 * 60; # two minutes
|
||||
|
||||
# 24 hours for captchas which were given out but not answered.
|
||||
# (they might leave their browser window open or something)
|
||||
$ExpireThresNoUser = 24 * 3600; # 1 day
|
||||
|
||||
|
||||
#####################################################################
|
||||
### F U N C T I O N S
|
||||
#####################################################################
|
||||
|
||||
### Read a file in as a scalar and return it
|
||||
sub readfile ($) {
|
||||
my ( $filename ) = @_;
|
||||
open my $fh, "<$filename" or die "open: $filename: $!";
|
||||
local $/ = undef;
|
||||
my $data = <$fh>;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
### Generate an n-character challenge code
|
||||
sub gencode ($) {
|
||||
my ( $digits ) = @_;
|
||||
my $code = '';
|
||||
for ( 1..$digits ) {
|
||||
$code .= substr( $Digits, int(rand($DigitCount)), 1 );
|
||||
}
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#####################################################################
|
||||
### M A I N T E N A N C E T A S K S
|
||||
#####################################################################
|
||||
$maintinfo{gen_audio_captchas}{opts}{locking} = "per_host";
|
||||
$maint{gen_audio_captchas} = sub {
|
||||
my (
|
||||
$u, # Fake user record for Blob::put
|
||||
$dbh, # Database handle (writer)
|
||||
$count, # Count of currently-extant audio challenges
|
||||
$need, # How many we need to still create
|
||||
$make, # how many we're actually going to create this round
|
||||
$tmpdir, # Temporary working directory
|
||||
$code, # The generated challenge code
|
||||
$wav, # Wav file
|
||||
$data, # Wav file data
|
||||
$err, # Error-message ref for Blob::put calls
|
||||
$capid, # Captcha row id
|
||||
$anum, # Deseries-ifier value
|
||||
);
|
||||
|
||||
print "-I- Generating new audio captchas...\n";
|
||||
|
||||
$dbh = LJ::get_dbh({raw=>1}, "master") or die "Failed to get_db_writer()";
|
||||
$dbh->do("SET wait_timeout=28800");
|
||||
|
||||
# Count how many challenges there are currently
|
||||
$count = $dbh->selectrow_array(q{
|
||||
SELECT COUNT(*)
|
||||
FROM captchas
|
||||
WHERE
|
||||
type = 'audio'
|
||||
AND issuetime = 0
|
||||
});
|
||||
|
||||
|
||||
my $MaxItems = $LJ::CAPTCHA_AUDIO_PREGEN || 500;
|
||||
|
||||
# If there are enough, don't generate any more
|
||||
print "Current count is $count of $MaxItems...";
|
||||
if ( $count >= $MaxItems ) {
|
||||
print "already have enough.\n";
|
||||
return;
|
||||
} else {
|
||||
$make = $need = $MaxItems - $count;
|
||||
$make = $LJ::CAPTCHA_AUDIO_MAKE
|
||||
if defined $LJ::CAPTCHA_AUDIO_MAKE && $make > $LJ::CAPTCHA_AUDIO_MAKE;
|
||||
print "generating $make new audio challenges.\n";
|
||||
}
|
||||
|
||||
# Clean up any old audio directories lying about from failed generations
|
||||
# before. In theory, File::Temp::tempdir() is supposed to clean them up
|
||||
# itself, but it doesn't appear to be doing so.
|
||||
foreach my $olddir ( glob "audio_captchas_*" ) {
|
||||
|
||||
# If it's been more than an hour since it's been changed from the
|
||||
# starting time of the script, kill it
|
||||
if ( (-M $olddir) * 24 > 1 ) {
|
||||
print "cleaning up old working temp directory ($olddir).\n";
|
||||
rmtree( $olddir ) or die "rmtree: $olddir: $!";
|
||||
}
|
||||
}
|
||||
|
||||
# Load the system user for Blob::put() and create an auto-cleaning temp
|
||||
# directory for audio generation
|
||||
$u = LJ::load_user( "system" )
|
||||
or die "Couldn't load the system user.";
|
||||
$tmpdir = tempdir( "audio_captchas_XXXXXX", CLEANUP => 0 );
|
||||
|
||||
# target location
|
||||
my $location = $LJ::CAPTCHA_MOGILEFS ? 'mogile' : 'blob';
|
||||
|
||||
# Generate the challenges
|
||||
for ( my $i = 0; $i < $make; $i++ ) {
|
||||
print "Generating audio $i...";
|
||||
( $wav, $code ) = LJ::Captcha::generate_audio( $tmpdir );
|
||||
$data = readfile( $wav );
|
||||
unlink $wav or die "unlink: $wav: $!";
|
||||
|
||||
# Generate the capid + anum
|
||||
print "generating new capid/anum...";
|
||||
$capid = LJ::alloc_global_counter( 'C' );
|
||||
die "Couldn't allocate capid" unless $capid;
|
||||
$anum = int( rand 65_535 );
|
||||
|
||||
# Insert the blob
|
||||
print "uploading (capid = $capid, anum = $anum)...";
|
||||
if ($location eq 'mogile') {
|
||||
my $mogfs = LJ::mogclient(); # force load
|
||||
die "Requested to store captchas on MogileFS, but it's not loaded.\n"
|
||||
unless $mogfs;
|
||||
my $fh = $mogfs->new_file("captcha:$capid", 'captcha')
|
||||
or die "Unable to contact MogileFS server for storage.\n";
|
||||
$fh->print($data);
|
||||
$fh->close
|
||||
or die "Unable to save captcha to MogileFS server: $@\n";
|
||||
} else {
|
||||
LJ::Blob::put( $u, 'captcha_audio', 'wav', $capid, $data, \$err )
|
||||
or die "Error uploading to media server: $err";
|
||||
}
|
||||
|
||||
# Insert the captcha into the DB. If it fails for some reason, delete
|
||||
# the just-uploaded file from the media storage system too.
|
||||
print "inserting (code = $code)...";
|
||||
my $rval = eval {
|
||||
$dbh->do(q{
|
||||
INSERT INTO captchas( capid, type, location, answer, anum )
|
||||
VALUES ( ?, 'audio', ?, ?, ? )
|
||||
}, undef, $capid, $location, $code, $anum);
|
||||
};
|
||||
if ( !$rval || $@ ) {
|
||||
my $err = $@ || $dbh->errstr;
|
||||
if ( $location eq 'mogile' ) {
|
||||
LJ::mogclient()->delete( "captcha:$capid" );
|
||||
} else {
|
||||
LJ::Blob::delete( $u, 'captcha_audio', 'wav', $capid );
|
||||
}
|
||||
die "audio captcha insert error on ($capid, $location, $code, $anum): $err";
|
||||
}
|
||||
|
||||
print "done.\n";
|
||||
}
|
||||
|
||||
print "cleaning up working temporary directory ($tmpdir).\n";
|
||||
rmtree( $tmpdir ) or die "Failed directory cleanup: $!";
|
||||
|
||||
print "done. Created $make new audio captchas.\n";
|
||||
return 1;
|
||||
};
|
||||
|
||||
$maintinfo{gen_image_captchas}{opts}{locking} = "per_host";
|
||||
$maint{gen_image_captchas} = sub {
|
||||
my (
|
||||
$u, # Fake user record for Blob::put
|
||||
$dbh, # Database handle (writer)
|
||||
$count, # Count of currently-extant audio challenges
|
||||
$need, # How many we need to still create
|
||||
$code, # The generated challenge code
|
||||
$png, # PNG data
|
||||
$err, # Error-message ref for Blob::put calls
|
||||
$capid, # Captcha row id
|
||||
$anum, # Deseries-ifier value
|
||||
);
|
||||
|
||||
print "-I- Generating new image captchas...\n";
|
||||
|
||||
$dbh = LJ::get_dbh({raw=>1}, "master") or die "Failed to get_db_writer()";
|
||||
$dbh->do("SET wait_timeout=28800");
|
||||
|
||||
# Count how many challenges there are currently
|
||||
$count = $dbh->selectrow_array(q{
|
||||
SELECT COUNT(*)
|
||||
FROM captchas
|
||||
WHERE
|
||||
type = 'image'
|
||||
AND issuetime = 0
|
||||
});
|
||||
|
||||
my $MaxItems = $LJ::CAPTCHA_IMAGE_PREGEN || 1000;
|
||||
|
||||
# If there are enough, don't generate any more
|
||||
print "Current count is $count of $MaxItems...";
|
||||
if ( $count >= $MaxItems ) {
|
||||
print "already have enough.\n";
|
||||
return;
|
||||
} else {
|
||||
$need = $MaxItems - $count;
|
||||
print "generating $need new image challenges.\n";
|
||||
}
|
||||
|
||||
# Load system user for Blob::put()
|
||||
$u = LJ::load_user( "system" )
|
||||
or die "Couldn't load the system user.";
|
||||
|
||||
$dbh = LJ::get_db_writer() or die "Failed to get_db_writer()";
|
||||
|
||||
# target location
|
||||
my $location = $LJ::CAPTCHA_MOGILEFS ? 'mogile' : 'blob';
|
||||
|
||||
# Generate the challenges
|
||||
for ( my $i = 0; $i < $need; $i++ ) {
|
||||
print "Generating image $i...";
|
||||
$code = gencode( 7 );
|
||||
( $png ) = LJ::Captcha::generate_visual( $code );
|
||||
|
||||
# Generate the capid + anum
|
||||
print "generating new capid/anum...";
|
||||
$capid = LJ::alloc_global_counter( 'C' );
|
||||
die "Couldn't allocate capid" unless $capid;
|
||||
$anum = int( rand 65_535 );
|
||||
|
||||
# Insert the blob
|
||||
print "uploading (capid = $capid, anum = $anum)...";
|
||||
if ($location eq 'mogile') {
|
||||
my $mogfs = LJ::mogclient(); # force load
|
||||
die "Requested to store captchas on MogileFS, but it's not loaded.\n"
|
||||
unless $mogfs;
|
||||
my $fh = $mogfs->new_file("captcha:$capid", 'captcha')
|
||||
or die "Unable to contact MogileFS server for storage.\n";
|
||||
$fh->print($png);
|
||||
$fh->close
|
||||
or die "Unable to save captcha to MogileFS server: $@\n";
|
||||
} else {
|
||||
LJ::Blob::put( $u, 'captcha_image', 'png', $capid, $png, \$err )
|
||||
or die "Error uploading to media server: $err";
|
||||
}
|
||||
|
||||
# Insert the captcha into the DB. If it fails for some reason, delete
|
||||
# the just-uploaded file from the media storage system too.
|
||||
print "inserting (code = $code)...";
|
||||
my $rval = eval {
|
||||
$dbh->do(q{
|
||||
INSERT INTO captchas( capid, type, location, answer, anum )
|
||||
VALUES ( ?, 'image', ?, ?, ? )
|
||||
}, undef, $capid, $location, $code, $anum);
|
||||
};
|
||||
if ( !$rval || $@ ) {
|
||||
my $err = $@ || $dbh->errstr;
|
||||
if ( $location eq 'mogile' ) {
|
||||
LJ::mogclient()->delete( "captcha:$capid" );
|
||||
} else {
|
||||
LJ::Blob::delete( $u, 'captcha_image', 'png', $capid );
|
||||
}
|
||||
die "image captcha insert error on ($capid, $location, $code, $anum): $err";
|
||||
}
|
||||
|
||||
print "done.\n";
|
||||
}
|
||||
|
||||
print "done. Created $need new image captchas.\n";
|
||||
return 1;
|
||||
};
|
||||
|
||||
$maint{clean_captchas} = sub {
|
||||
my (
|
||||
$u, # System user
|
||||
$expired, # arrayref of arrayrefs of expired captchas
|
||||
$dbh, # Database handle (writer)
|
||||
$sql, # SQL statement
|
||||
$sth, # Statement handle
|
||||
$count, # Deletion count
|
||||
$err, # Error message reference for Blob::delete calls
|
||||
);
|
||||
|
||||
print "-I- Cleaning captchas.\n";
|
||||
|
||||
# Find captchas to delete
|
||||
$sql = q{
|
||||
SELECT
|
||||
capid, type, location
|
||||
FROM captchas
|
||||
WHERE
|
||||
( issuetime <> 0 AND issuetime < ? )
|
||||
OR
|
||||
( userid > 0
|
||||
AND ( issuetime <> 0 AND issuetime < ? )
|
||||
)
|
||||
LIMIT 2500
|
||||
};
|
||||
$dbh = LJ::get_db_writer()
|
||||
or die "No master DB handle";
|
||||
$expired = $dbh->selectall_arrayref( $sql, undef,
|
||||
time() - $ExpireThresNoUser,
|
||||
time() - $ExpireThresUser );
|
||||
die "selectall_arrayref: $sql: ", $dbh->errstr if $dbh->err;
|
||||
|
||||
if ( @$expired ) {
|
||||
print "found ", scalar @$expired, " captchas to delete...\n";
|
||||
} else {
|
||||
print "Done: No captchas to delete.\n";
|
||||
return;
|
||||
}
|
||||
|
||||
# Prepare deletion statement
|
||||
$sql = q{ DELETE FROM captchas WHERE capid = ? };
|
||||
$sth = $dbh->prepare( $sql );
|
||||
|
||||
# Fetch system user
|
||||
$u = LJ::load_user( "system" )
|
||||
or die "Couldn't load the system user.";
|
||||
|
||||
# Now delete each one from the DB and the media server
|
||||
foreach my $captcha ( @$expired ) {
|
||||
my ( $capid, $type, $location ) = @$captcha;
|
||||
$location ||= 'blob';
|
||||
print "Deleting captcha $capid ($type, $location)\n";
|
||||
my $ext = $type eq 'audio' ? 'wav' : 'png';
|
||||
|
||||
if ($location eq 'mogile') {
|
||||
my $mogfs = LJ::mogclient(); # force load
|
||||
die "Requested to delete captchas from MogileFS, but it's not loaded.\n"
|
||||
unless $mogfs;
|
||||
$mogfs->delete("captcha:$capid")
|
||||
or die "Unable to delete captcha from MogileFS server for capid = $capid.\n";
|
||||
} else {
|
||||
LJ::Blob::delete( $u, "captcha_$type", $ext, $capid, \$err )
|
||||
or die "Failed to delete $type file from media server for ".
|
||||
"capid = $capid: $err";
|
||||
}
|
||||
$sth->execute( $capid )
|
||||
or die "execute: $sql ($capid): ", $sth->errstr;
|
||||
$count++;
|
||||
}
|
||||
|
||||
print "Done: deleted $count expired captchas.\n";
|
||||
return 1;
|
||||
};
|
||||
|
||||
207
livejournal/bin/maint/clean_caches.pl
Executable file
@@ -0,0 +1,207 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
|
||||
$maint{'clean_caches'} = sub
|
||||
{
|
||||
my $dbh = LJ::get_db_writer();
|
||||
my $sth;
|
||||
|
||||
my $verbose = $LJ::LJMAINT_VERBOSE;
|
||||
|
||||
print "-I- Cleaning authactions.\n";
|
||||
$dbh->do("DELETE FROM authactions WHERE datecreate < DATE_SUB(NOW(), INTERVAL 30 DAY)");
|
||||
|
||||
print "-I- Cleaning faquses.\n";
|
||||
$dbh->do("DELETE FROM faquses WHERE dateview < DATE_SUB(NOW(), INTERVAL 7 DAY)");
|
||||
|
||||
print "-I- Cleaning duplock.\n";
|
||||
$dbh->do("DELETE FROM duplock WHERE instime < DATE_SUB(NOW(), INTERVAL 1 HOUR)");
|
||||
|
||||
print "-I- Cleaning commenturl.\n";
|
||||
$dbh->do("DELETE FROM commenturls WHERE timecreate < UNIX_TIMESTAMP() - 86400*30 LIMIT 50000");
|
||||
|
||||
print "-I- Cleaning captcha sessions.\n";
|
||||
foreach my $c (@LJ::CLUSTERS) {
|
||||
my $dbcm = LJ::get_cluster_master($c);
|
||||
next unless $dbcm;
|
||||
$dbcm->do("DELETE FROM captcha_session WHERE sesstime < UNIX_TIMESTAMP()-86400");
|
||||
}
|
||||
|
||||
print "-I- Cleaning old anonymous comment IP logs.\n";
|
||||
my $count;
|
||||
foreach my $c (@LJ::CLUSTERS) {
|
||||
my $dbcm = LJ::get_cluster_master($c);
|
||||
next unless $dbcm;
|
||||
# 432,000 seconds is 5 days
|
||||
$count += $dbcm->do('DELETE FROM tempanonips WHERE reporttime < (UNIX_TIMESTAMP() - 432000)');
|
||||
}
|
||||
print " deleted $count\n";
|
||||
|
||||
print "-I- Cleaning diresearchres.\n";
|
||||
# need insert before delete so master logs delete and slaves actually do it
|
||||
$dbh->do("INSERT INTO dirsearchres2 VALUES (MD5(NOW()), DATE_SUB(NOW(), INTERVAL 31 MINUTE), '')");
|
||||
$dbh->do("DELETE FROM dirsearchres2 WHERE dateins < DATE_SUB(NOW(), INTERVAL 30 MINUTE)");
|
||||
|
||||
print "-I- Cleaning meme.\n";
|
||||
do {
|
||||
$sth = $dbh->prepare("DELETE FROM meme WHERE ts < DATE_SUB(NOW(), INTERVAL 7 DAY) LIMIT 250");
|
||||
$sth->execute;
|
||||
if ($dbh->err) { print $dbh->errstr; }
|
||||
print " deleted ", $sth->rows, "\n";
|
||||
} while ($sth->rows && ! $sth->err);
|
||||
|
||||
print "-I- Cleaning old pending comments.\n";
|
||||
$count = 0;
|
||||
foreach my $c (@LJ::CLUSTERS) {
|
||||
my $dbcm = LJ::get_cluster_master($c);
|
||||
next unless $dbcm;
|
||||
# 3600 seconds is one hour
|
||||
my $time = time() - 3600;
|
||||
$count += $dbcm->do('DELETE FROM pendcomments WHERE datesubmit < ? LIMIT 2000', undef, $time);
|
||||
}
|
||||
print " deleted $count\n";
|
||||
|
||||
# move rows from talkleft_xfp to talkleft
|
||||
print "-I- Moving talkleft_xfp.\n";
|
||||
|
||||
my $xfp_count = $dbh->selectrow_array("SELECT COUNT(*) FROM talkleft_xfp");
|
||||
print " rows found: $xfp_count\n";
|
||||
|
||||
if ($xfp_count) {
|
||||
|
||||
my @xfp_cols = qw(userid posttime journalid nodetype nodeid jtalkid publicitem);
|
||||
my $xfp_cols = join(",", @xfp_cols);
|
||||
my $xfp_cols_join = join(",", map { "t.$_" } @xfp_cols);
|
||||
|
||||
my %insert_vals;
|
||||
my %delete_vals;
|
||||
|
||||
# select out 1000 rows from random clusters
|
||||
$sth = $dbh->prepare("SELECT u.clusterid,u.user,$xfp_cols_join " .
|
||||
"FROM talkleft_xfp t, user u " .
|
||||
"WHERE t.userid=u.userid LIMIT 1000");
|
||||
$sth->execute();
|
||||
my $row_ct = 0;
|
||||
while (my $row = $sth->fetchrow_hashref) {
|
||||
|
||||
my %qrow = map { $_, $dbh->quote($row->{$_}) } @xfp_cols;
|
||||
|
||||
push @{$insert_vals{$row->{'clusterid'}}},
|
||||
("(" . join(",", map { $qrow{$_} } @xfp_cols) . ")");
|
||||
push @{$delete_vals{$row->{'clusterid'}}},
|
||||
("(userid=$qrow{'userid'} AND " .
|
||||
"journalid=$qrow{'journalid'} AND " .
|
||||
"nodetype=$qrow{'nodetype'} AND " .
|
||||
"nodeid=$qrow{'nodeid'} AND " .
|
||||
"posttime=$qrow{'posttime'} AND " .
|
||||
"jtalkid=$qrow{'jtalkid'})");
|
||||
|
||||
$row_ct++;
|
||||
}
|
||||
|
||||
foreach my $clusterid (sort keys %insert_vals) {
|
||||
my $dbcm = LJ::get_cluster_master($clusterid);
|
||||
unless ($dbcm) {
|
||||
print " cluster down: $clusterid\n";
|
||||
next;
|
||||
}
|
||||
|
||||
print " cluster $clusterid: " . scalar(@{$insert_vals{$clusterid}}) .
|
||||
" rows\n" if $verbose;
|
||||
$dbcm->do("INSERT INTO talkleft ($xfp_cols) VALUES " .
|
||||
join(",", @{$insert_vals{$clusterid}})) . "\n";
|
||||
if ($dbcm->err) {
|
||||
print " db error (insert): " . $dbcm->errstr . "\n";
|
||||
next;
|
||||
}
|
||||
|
||||
# no error, delete from _xfp
|
||||
$dbh->do("DELETE FROM talkleft_xfp WHERE " .
|
||||
join(" OR ", @{$delete_vals{$clusterid}})) . "\n";
|
||||
if ($dbh->err) {
|
||||
print " db error (delete): " . $dbh->errstr . "\n";
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
print " rows remaining: " . ($xfp_count - $row_ct) . "\n";
|
||||
}
|
||||
|
||||
# move clustered recentaction summaries from their respective clusters
|
||||
# to the global actionhistory table
|
||||
print "-I- Migrating recentactions.\n";
|
||||
|
||||
foreach my $cid (@LJ::CLUSTERS) {
|
||||
next unless $cid;
|
||||
|
||||
my $dbcm = LJ::get_cluster_master($cid);
|
||||
unless ($dbcm) {
|
||||
print " cluster down: $clusterid\n";
|
||||
next;
|
||||
}
|
||||
|
||||
unless ($dbcm->do("LOCK TABLES recentactions WRITE")) {
|
||||
print " db error (lock): " . $dbcm->errstr . "\n";
|
||||
next;
|
||||
}
|
||||
|
||||
my $sth = $dbcm->prepare
|
||||
("SELECT what, COUNT(*) FROM recentactions GROUP BY 1");
|
||||
$sth->execute;
|
||||
if ($dbcm->err) {
|
||||
print " db error (select): " . $dbcm->errstr . "\n";
|
||||
next;
|
||||
}
|
||||
|
||||
my %counts = ();
|
||||
my $total_ct = 0;
|
||||
while (my ($what, $ct) = $sth->fetchrow_array) {
|
||||
$counts{$what} += $ct;
|
||||
$total_ct += $ct;
|
||||
}
|
||||
|
||||
print " cluster $cid: $total_ct rows\n" if $verbose;
|
||||
|
||||
# Note: We can experience failures on both sides of this
|
||||
# transaction. Either our delete can succeed then
|
||||
# insert fail or vice versa. Luckily this data is
|
||||
# for statistical purposes so we can just live with
|
||||
# the possibility of a small skew.
|
||||
|
||||
unless ($dbcm->do("DELETE FROM recentactions")) {
|
||||
print " db error (delete): " . $dbcm->errstr . "\n";
|
||||
next;
|
||||
}
|
||||
|
||||
# at this point if there is an error we will ignore it and try
|
||||
# to insert the count data above anyway
|
||||
$dbcm->do("UNLOCK TABLES")
|
||||
or print " db error (unlock): " . $dbcm->errstr . "\n";
|
||||
|
||||
# nothing to insert, why bother?
|
||||
next unless %counts;
|
||||
|
||||
# insert summary into global actionhistory table
|
||||
my @bind = ();
|
||||
my @vals = ();
|
||||
while (my ($what, $ct) = each %counts) {
|
||||
push @bind, "(UNIX_TIMESTAMP(),?,?,?)";
|
||||
push @vals, $cid, $what, $ct;
|
||||
}
|
||||
my $bind = join(",", @bind);
|
||||
|
||||
$dbh->do("INSERT INTO actionhistory (time, clusterid, what, count) " .
|
||||
"VALUES $bind", undef, @vals);
|
||||
if ($dbh->err) {
|
||||
print " db error (insert): " . $dbh->errstr . "\n";
|
||||
|
||||
# something's badly b0rked, don't try any other clusters for now
|
||||
last;
|
||||
}
|
||||
|
||||
# next cluster
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
76
livejournal/bin/maint/generic.pl
Executable file
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
|
||||
$maint{joinmail} = sub {
|
||||
# this needs to be resumeable, so that it can run once every 10 or 15 minutes to digest things
|
||||
# that are a day old but haven't been sent. also, the first query down there needs to include
|
||||
# the right authaction type in the WHERE clause, and NOT do a GROUP BY.
|
||||
print "Returning without running... I'm disabled right now.\n";
|
||||
return 1;
|
||||
|
||||
my $dbr = LJ::get_db_reader();
|
||||
|
||||
# get all information
|
||||
my $pending = $dbr->selectall_arrayref("SELECT userid, COUNT(arg1) FROM authactions " .
|
||||
"WHERE used = 'N' AND datecreate > DATE_SUB(NOW(), INTERVAL 1 DAY)" .
|
||||
"GROUP BY userid") || [];
|
||||
|
||||
# get userids of communities
|
||||
my @commids;
|
||||
push @commids, $_->[0]+0 foreach @$pending;
|
||||
my $cus = LJ::load_userids(@commids);
|
||||
|
||||
# now let's get the maintainers of these
|
||||
my $in = join ',', @commids;
|
||||
my $maintrows = $dbr->selectall_arrayref("SELECT userid, targetid FROM reluser WHERE userid IN ($in) AND type = 'A'") || [];
|
||||
my @maintids;
|
||||
my %maints;
|
||||
foreach (@$maintrows) {
|
||||
push @{$maints{$_->[0]}}, $_->[1];
|
||||
push @maintids, $_->[1];
|
||||
}
|
||||
my $mus = LJ::load_userids(@maintids);
|
||||
|
||||
# tell the maintainers that they got new people.
|
||||
foreach my $row (@$pending) {
|
||||
my $cuser = $cus->{$row->[0]}{user};
|
||||
print "$cuser: $row->[1] invites: ";
|
||||
my %email; # see who we emailed on this comm
|
||||
foreach my $mid (@{$maints{$row->[0]}}) {
|
||||
print "$mid ";
|
||||
next if $email{$mus->{$mid}{email}}++;
|
||||
LJ::load_user_props($mus->{$mid}, 'opt_communityjoinemail');
|
||||
next unless $mus->{$mid}{opt_communityjoinemail} eq 'D'; # Daily or Digest
|
||||
|
||||
my $body = "Dear $mus->{$mid}{user},\n\n" .
|
||||
"Over the past day or so, $row->[1] request(s) to join the \"$cuser\" community have " .
|
||||
"been received. To look at the currently pending membership requests, please visit the pending " .
|
||||
"membership page:\n\n" .
|
||||
"\t$LJ::SITEROOT/community/pending.bml?comm=$cuser\n\n" .
|
||||
"You may also ignore this email. Outstanding requests to join will expire after a period of 30 days.\n\n" .
|
||||
"If you wish to no longer receive these emails, visit the community management page and " .
|
||||
"set the relevant options:\n\n\t$LJ::SITEROOT/community/manage.bml\n\n" .
|
||||
"Regards,\n$LJ::SITENAME Team\n";
|
||||
|
||||
LJ::send_mail({
|
||||
to => $mus->{$mid}{email},
|
||||
from => $LJ::COMMUNITY_EMAIL,
|
||||
fromname => $LJ::SITENAME,
|
||||
charset => 'utf-8',
|
||||
subject => "$cuser Membership Requests",
|
||||
body => $body,
|
||||
wrap => 76,
|
||||
});
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
};
|
||||
|
||||
$maint{clean_spamreports} = sub {
|
||||
my $dbh = LJ::get_db_writer();
|
||||
my $len = 86400 * 90; # 90 days
|
||||
my $ct = $dbh->do("DELETE FROM spamreports WHERE reporttime < UNIX_TIMESTAMP() - $len")+0;
|
||||
print "Deleted $ct reports.\n";
|
||||
};
|
||||
|
||||
1;
|
||||
530
livejournal/bin/maint/stats.pl
Executable file
@@ -0,0 +1,530 @@
|
||||
#!/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 $usertotal = $db->selectrow_array("SELECT MAX(userid) FROM user");
|
||||
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 $usertotal = $db->selectrow_array("SELECT MAX(userid) FROM user");
|
||||
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 $usertotal = $db->selectrow_array("SELECT MAX(userid) FROM userproplite2");
|
||||
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 $usertotal = $db->selectrow_array("SELECT MAX(userid) FROM userproplite2");
|
||||
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 $usertotal = $db->selectrow_array("SELECT MAX(userid) FROM userproplite2");
|
||||
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;
|
||||
|
||||
# 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("SELECT MAX(userid) FROM user");
|
||||
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;
|
||||
122
livejournal/bin/maint/statspics.pl
Executable file
@@ -0,0 +1,122 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
|
||||
use GD::Graph::bars;
|
||||
|
||||
$maint{'genstatspics'} = sub
|
||||
{
|
||||
my $dbh = LJ::get_db_writer();
|
||||
my $sth;
|
||||
|
||||
### get posts by day data from summary table
|
||||
print "-I- new accounts by day.\n";
|
||||
$sth = $dbh->prepare("SELECT DATE_FORMAT(statkey, '%m-%d') AS 'day', statval AS 'new' FROM stats WHERE statcat='newbyday' ORDER BY statkey DESC LIMIT 60");
|
||||
$sth->execute;
|
||||
if ($dbh->err) { die $dbh->errstr; }
|
||||
|
||||
my @data;
|
||||
my $i;
|
||||
my $max;
|
||||
while ($_ = $sth->fetchrow_hashref)
|
||||
{
|
||||
my $val = $_->{'new'};
|
||||
unshift @{$data[0]}, ($i++ % 5 == 0 ? $_->{'day'} : "");
|
||||
unshift @{$data[1]}, $val;
|
||||
if ($val > $max) { $max = $val; }
|
||||
}
|
||||
|
||||
# posts by day graph
|
||||
my $g = GD::Graph::bars->new(520, 350);
|
||||
$g->set(
|
||||
x_label => 'Day',
|
||||
y_label => 'Accounts',
|
||||
title => 'New accounts per day',
|
||||
tranparent => 0,
|
||||
y_max_value => $max,
|
||||
);
|
||||
|
||||
my $gd = $g->plot(\@data);
|
||||
open(IMG, ">$LJ::HTDOCS/stats/newbyday.png") or die $!;
|
||||
binmode IMG;
|
||||
print IMG $gd->png;
|
||||
close IMG;
|
||||
|
||||
unless ($LJ::DISABLED{'stats-postsbyday'}) {
|
||||
print "-I- posts in last 60 days.\n";
|
||||
|
||||
### suck the data in
|
||||
$sth = $dbh->prepare("SELECT DATE_FORMAT(statkey, '%m-%d') AS 'day', statval AS 'posts' FROM stats WHERE statcat='postsbyday' ORDER BY statkey DESC LIMIT 60");
|
||||
$sth->execute;
|
||||
if ($dbh->err) { die $dbh->errstr; }
|
||||
|
||||
### analyze the last 60 days data
|
||||
|
||||
my @data;
|
||||
my $i;
|
||||
my $max;
|
||||
while ($_ = $sth->fetchrow_hashref)
|
||||
{
|
||||
my $val = $_->{'posts'};
|
||||
unshift @{$data[0]}, ($i++ % 5 == 0 ? $_->{'day'} : "");
|
||||
unshift @{$data[1]}, $val;
|
||||
if ($val > $max) { $max = $val; }
|
||||
}
|
||||
|
||||
# posts by day graph
|
||||
my $g = GD::Graph::bars->new(520, 350);
|
||||
$g->set(
|
||||
x_label => 'Day',
|
||||
y_label => 'Posts',
|
||||
title => 'Posts per day',
|
||||
tranparent => 0,
|
||||
y_max_value => $max,
|
||||
);
|
||||
|
||||
my $gd = $g->plot(\@data);
|
||||
open(IMG, ">$LJ::HTDOCS/stats/postsbyday.png") or die $!;
|
||||
binmode IMG;
|
||||
print IMG $gd->png;
|
||||
close IMG;
|
||||
|
||||
print "-I- posts by week.\n";
|
||||
|
||||
### suck the data in
|
||||
$sth = $dbh->prepare("SELECT DATE_FORMAT(statkey, '%X-%V') AS 'week', SUM(statval) AS 'posts' FROM stats WHERE statcat='postsbyday' AND DATE_FORMAT(statkey, '%X-%V') <> DATE_FORMAT(NOW(), '%X-%V') AND statkey>'1999-06-01' GROUP BY 1 ORDER BY statkey DESC");
|
||||
$sth->execute;
|
||||
if ($dbh->err) { die $dbh->errstr; }
|
||||
|
||||
### analyze the last 60 days data
|
||||
|
||||
my @data;
|
||||
my $i;
|
||||
my $max;
|
||||
while ($_ = $sth->fetchrow_hashref)
|
||||
{
|
||||
my $val = $_->{'posts'};
|
||||
unshift @{$data[0]}, ($i++ % 10 == 0 ? $_->{'week'} : "");
|
||||
unshift @{$data[1]}, $val;
|
||||
if ($val > $max) { $max = $val; }
|
||||
}
|
||||
|
||||
# posts by week graph
|
||||
my $g = GD::Graph::bars->new(520, 350);
|
||||
$g->set(
|
||||
x_label => 'Week',
|
||||
y_label => 'Posts',
|
||||
title => 'Posts per week',
|
||||
tranparent => 0,
|
||||
y_max_value => $max,
|
||||
);
|
||||
|
||||
my $gd = $g->plot(\@data);
|
||||
open(IMG, ">$LJ::HTDOCS/stats/postsbyweek.png") or die $!;
|
||||
binmode IMG;
|
||||
print IMG $gd->png;
|
||||
close IMG;
|
||||
}
|
||||
|
||||
print "-I- done.\n";
|
||||
|
||||
};
|
||||
|
||||
1;
|
||||
513
livejournal/bin/maint/synsuck.pl
Executable file
@@ -0,0 +1,513 @@
|
||||
#!/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;
|
||||
require "ljprotocol.pl";
|
||||
require "parsefeed.pl";
|
||||
require "cleanhtml.pl";
|
||||
|
||||
$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, $readers) =
|
||||
map { $urow->{$_} } qw(user userid synurl lastmod etag 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" => 10);
|
||||
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: $user ($synurl)\n" if $verbose;
|
||||
|
||||
my $req = HTTP::Request->new("GET", $synurl);
|
||||
$req->header('If-Modified-Since', LJ::time_to_http($lastmod))
|
||||
if $lastmod;
|
||||
$req->header('If-None-Match', $etag)
|
||||
if $etag;
|
||||
|
||||
my ($content, $too_big);
|
||||
my $res = $ua->request($req, sub {
|
||||
if (length($content) > 1024*150) { $too_big = 1; return; }
|
||||
$content .= $_[0];
|
||||
}, 4096);
|
||||
if ($too_big) { $delay->(60, "toobig"); return; }
|
||||
|
||||
if ($res->is_error()) {
|
||||
# http error
|
||||
print "HTTP error!\n" if $verbose;
|
||||
|
||||
# overload parseerror here because it's already there -- we'll
|
||||
# never have both an http error and a parse error on the
|
||||
# same request
|
||||
$delay->(3*60, "parseerror");
|
||||
|
||||
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 ? 60 : 24*60, "notmodified");
|
||||
return;
|
||||
}
|
||||
|
||||
# WARNING: blatant XML spec violation ahead...
|
||||
#
|
||||
# Blogger doesn't produce valid XML, since they don't handle encodings
|
||||
# correctly. So if we see they have no encoding (which is UTF-8 implictly)
|
||||
# but it's not valid UTF-8, say it's Windows-1252, which won't
|
||||
# cause XML::Parser to barf... but there will probably be some bogus characters.
|
||||
# better than nothing I guess. (personally, I'd prefer to leave it broken
|
||||
# and have people bitch at Blogger, but jwz wouldn't stop bugging me)
|
||||
# XML::Parser doesn't include Windows-1252, but we put it in cgi-bin/XML/* for it
|
||||
# to find.
|
||||
my $encoding;
|
||||
if ($content =~ /<\?xml.+?>/ && $& =~ /encoding=([\"\'])(.+?)\1/) {
|
||||
$encoding = lc($2);
|
||||
}
|
||||
if (! $encoding && ! LJ::is_utf8($content)) {
|
||||
$content =~ s/\?>/ encoding='windows-1252' \?>/;
|
||||
}
|
||||
|
||||
# WARNING: another hack...
|
||||
# People produce what they think is iso-8859-1, but they include
|
||||
# Windows-style smart quotes. Check for invalid iso-8859-1 and correct.
|
||||
if ($encoding =~ /^iso-8859-1$/i && $content =~ /[\x80-\x9F]/) {
|
||||
# They claimed they were iso-8859-1, but they are lying.
|
||||
# Assume it was Windows-1252.
|
||||
print "Invalid ISO-8859-1; assuming Windows-1252...\n" if $verbose;
|
||||
$content =~ s/encoding=([\"\'])(.+?)\1/encoding='windows-1252'/;
|
||||
}
|
||||
|
||||
# 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);
|
||||
return;
|
||||
}
|
||||
|
||||
# another sanity check
|
||||
unless (ref $feed->{'items'} eq "ARRAY") {
|
||||
$delay->(3*60, "noitems");
|
||||
return;
|
||||
}
|
||||
|
||||
my @items = reverse @{$feed->{'items'}};
|
||||
|
||||
# take most recent 20
|
||||
splice(@items, 0, @items-20) if @items > 20;
|
||||
|
||||
# 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;
|
||||
}
|
||||
}
|
||||
|
||||
# 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=? LIMIT 1000");
|
||||
$sth->execute($su->{'userid'}, $p->{'id'});
|
||||
while (my ($itemid, $id) = $sth->fetchrow_array) {
|
||||
$existing_item{$id} = $itemid;
|
||||
}
|
||||
}
|
||||
|
||||
# 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;
|
||||
};
|
||||
|
||||
foreach my $it (@items) {
|
||||
|
||||
# remove the SvUTF8 flag. it's still UTF-8, but
|
||||
# we don't want perl knowing that and fucking stuff up
|
||||
# for us behind our back in random places all over
|
||||
# http://zilla.livejournal.org/show_bug.cgi?id=1037
|
||||
foreach my $attr (qw(subject text link)) {
|
||||
$it->{$attr} = pack('C*', unpack('C*', $it->{$attr}));
|
||||
}
|
||||
|
||||
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+$//;
|
||||
|
||||
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' => "$htmllink$it->{'text'}",
|
||||
'year' => $year,
|
||||
'mon' => $mon,
|
||||
'day' => $day,
|
||||
'hour' => $hour,
|
||||
'min' => $min,
|
||||
'props' => {
|
||||
'syn_link' => $it->{'link'},
|
||||
},
|
||||
};
|
||||
$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 });
|
||||
LJ::set_userprop($su, "urlname", $title);
|
||||
}
|
||||
|
||||
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'}"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $r_lastmod = LJ::http_to_time($res->header('Last-Modified'));
|
||||
my $r_etag = $res->header('ETag');
|
||||
|
||||
# decide when to poll next (in minutes).
|
||||
# FIXME: this is super lame. (use hints in RSS file!)
|
||||
my $int = $newcount ? 30 : 60;
|
||||
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 unless $readers;
|
||||
|
||||
$dbh->do("UPDATE syndicated SET checknext=DATE_ADD(NOW(), INTERVAL $int MINUTE), ".
|
||||
"lastcheck=NOW(), lastmod=?, etag=?, laststatus=?, numreaders=? $updatenew ".
|
||||
"WHERE userid=$userid", undef, $r_lastmod, $r_etag, $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.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:
|
||||
27
livejournal/bin/maint/taskinfo.txt
Executable file
@@ -0,0 +1,27 @@
|
||||
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.
|
||||
1000
livejournal/bin/moveucluster.pl
Executable file
2750
livejournal/bin/moveuclusterd.pl
Executable file
253
livejournal/bin/qbufferd.pl
Executable file
@@ -0,0 +1,253 @@
|
||||
#!/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";
|
||||
|
||||
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;
|
||||
};
|
||||
207
livejournal/bin/statserv.pl
Executable file
@@ -0,0 +1,207 @@
|
||||
#!/usr/bin/perl -w
|
||||
# LiveJournal statistics server. Sits on a UDP port and journals
|
||||
# information on the incoming hit rate, manages site bans, etc.
|
||||
# Loosely based on the ljrpcd code to save typing ;)
|
||||
# <LJDEP>
|
||||
# lib: IO::Socket Proc::ProcessTable IO::Handle DBI
|
||||
#
|
||||
# </LJDEP>
|
||||
|
||||
use strict;
|
||||
use IO::Socket;
|
||||
use IO::Handle;
|
||||
use Proc::ProcessTable;
|
||||
use DBI;
|
||||
|
||||
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
|
||||
|
||||
# Max message length and port to bind.
|
||||
my $MAXLEN = 512;
|
||||
my $PORTNO = 6200;
|
||||
my $PIDFILE = '/home/lj/var/statserv.pid';
|
||||
my $LOGDIR = '/home/lj/logs/';
|
||||
|
||||
# Maximum amount of hits they can use in five minutes.
|
||||
my %maxes = ( 'ip' => 15, 'guest' => 20, 'user' => 25 );
|
||||
|
||||
# Pid and pidfile.
|
||||
my $pid;
|
||||
my $is_parent = 1;
|
||||
# Socket. Needs to be here for the HUP stuff.
|
||||
my $sock;
|
||||
# Cache hash.
|
||||
my %caches = ();
|
||||
# Cache array.
|
||||
my @events = ();
|
||||
|
||||
# Exceptions hash (IP range or username as keys)
|
||||
# If you want some host (such as a big stupid random proxy) to
|
||||
# be more lenient with the number of hits it can make in five minutes,
|
||||
# put the value in here. If value is -1, then there is no limit.
|
||||
my %except = ();
|
||||
|
||||
# In case we're shot, unlink the pidfile.
|
||||
$SIG{TERM} = sub {
|
||||
unlink($PIDFILE);
|
||||
exit 1;
|
||||
};
|
||||
|
||||
# Local network bind to.
|
||||
my $MYNET = '10.0';
|
||||
|
||||
if (-e $PIDFILE) {
|
||||
open (PID, $PIDFILE);
|
||||
my $tpid;
|
||||
chomp ($tpid = <PID>);
|
||||
close PID;
|
||||
my $processes = Proc::ProcessTable->new()->table;
|
||||
if (grep { $_->cmndline =~ /statserv/ } @$processes) {
|
||||
print "Process exists already, quitting.\n";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
|
||||
print "LiveJournal Statistics Daemon starting up into the background...\n";
|
||||
|
||||
if ($pid = fork) {
|
||||
# Parent, log pid and exit.
|
||||
open(PID, ">$PIDFILE") or die "Couldn't open $PIDFILE for writing: $!\n";
|
||||
print PID $pid;
|
||||
close(PID);
|
||||
print "Closing ($pid) wrote to $PIDFILE\n";
|
||||
$is_parent = 1;
|
||||
exit;
|
||||
} else {
|
||||
# This is the child.
|
||||
my($cmdmsg, $remaddr, $remhost);
|
||||
|
||||
# HUP signal handler.
|
||||
$SIG{HUP} = \&restart_request;
|
||||
# SIGUSR handler.
|
||||
$SIG{USR1} = sub { open_logfile(); };
|
||||
|
||||
open_logfile();
|
||||
|
||||
$sock = IO::Socket::INET->new(LocalPort => "$PORTNO", Proto => 'udp') or die "socket: $@";
|
||||
|
||||
# Main loop.
|
||||
while ($sock->recv($cmdmsg, $MAXLEN)) {
|
||||
my ($port, $ipaddr) = sockaddr_in($sock->peername);
|
||||
my $ip_addr = inet_ntoa($ipaddr);
|
||||
|
||||
# Make sure it's from around here.
|
||||
if ($ip_addr !~ m/^$MYNET/) {
|
||||
print "Got message from an invalid host.\n";
|
||||
next;
|
||||
}
|
||||
|
||||
# Quick command parsing, since there isn't much to it.
|
||||
if ($cmdmsg =~ s/^cmd:\s//) {
|
||||
handle_request($cmdmsg);
|
||||
next;
|
||||
}
|
||||
}
|
||||
die "recv: $!\n";
|
||||
}
|
||||
|
||||
# Sub to restart the daemon.
|
||||
sub restart_request {
|
||||
$sock->close;
|
||||
unlink($PIDFILE);
|
||||
exec($0);
|
||||
}
|
||||
|
||||
|
||||
# Handle the request. This updates the appropriate caches,
|
||||
# and may set a ban.
|
||||
# Requests look like:
|
||||
# cmd: cachename : ip_addr : type : url
|
||||
# type can be: ip, guest, or user
|
||||
# If type is "ip" then cachename can be anything. I suggest
|
||||
# it be set to "ip" as well. If just to save space.
|
||||
sub handle_request {
|
||||
my $cmd = shift;
|
||||
my $now = time();
|
||||
|
||||
# Clear expired events.
|
||||
clean_events($now);
|
||||
# As of now, we don't care about the URL, really.
|
||||
if ($cmd =~ m/^(\w+)\s:\s([\d\.]+)\s:\s(\w+)/) {
|
||||
my $user = $1;
|
||||
my $ip_addr = $2;
|
||||
my $type = $3;
|
||||
# If there was no cookie of any kind, the type
|
||||
# name is set to "ip" - in this case we up the
|
||||
# cache number for the IP range.
|
||||
if ($type eq "ip") {
|
||||
# This regex is dumb, but the data we have is trustable.
|
||||
$user = $ip_addr;
|
||||
$user =~ s/(\d+)\.(\d+)\.(\d+)\.(\d+)/$1\.$2\.$3\./;
|
||||
}
|
||||
unless (exists $caches{$user}) {
|
||||
$caches{$user} = { 'numhit' => 0, 'type' => $type };
|
||||
}
|
||||
push @events, [ $user, $now ];
|
||||
$caches{$user}->{'numhit'}++;
|
||||
|
||||
# Now we check to see if they have hit too fast, and ban if so.
|
||||
if (should_ban($user)) {
|
||||
# FIXME: For final operation, this should be replaced with
|
||||
# a call to set_ban(). This is also going to spam a ton,
|
||||
# but with the "spiffy" algorithm I can't easily nuke a user.
|
||||
print "Would have banned user $user. Hits: " . $caches{$user}->{'numhit'} . "\n";
|
||||
}
|
||||
# After this, "add_stat($user, $type, $url)" should run.
|
||||
} else {
|
||||
print "Got a mal-formed request: $cmd\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Returns 1 if the passed "user" should be banned, 0 if not.
|
||||
sub should_ban {
|
||||
my $user = shift;
|
||||
|
||||
my $max = $except{$user} || $maxes{$caches{$user}->{'type'}} || 0;
|
||||
# If it doesn't have a defined class, do we really want it around?
|
||||
return 1 unless ($max);
|
||||
return 1 if ($caches{$user}->{'numhit'} > $max);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Removes old events, and decrements caches.
|
||||
sub clean_events {
|
||||
my $now = shift;
|
||||
while (@events && $events[0]->[1] < $now - 360) {
|
||||
my $deadevt = shift @events;
|
||||
if (--$caches{$deadevt->[0]}->{'numhits'} < 1) {
|
||||
delete $caches{$deadevt->[0]};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Placeholder. Sets a ban in the database.
|
||||
sub set_ban {
|
||||
|
||||
}
|
||||
|
||||
# Placeholder. Runs various stats collections.
|
||||
sub add_stat {
|
||||
|
||||
}
|
||||
|
||||
# Opens a new tagged logfile. Also sets it to the default
|
||||
# filehandle, sets autoflush, and returns the new handle.
|
||||
sub open_logfile {
|
||||
my $now = time();
|
||||
my $logname = $LOGDIR . "statserv-" . $now . "\.log\n";
|
||||
my $logfh = new IO::Handle;
|
||||
open($logfh, ">> $logname") or die "Couldn't open $logname: $!\n";
|
||||
my $oldfh = select($logfh);
|
||||
# Make sure the old one is closed.
|
||||
close($oldfh);
|
||||
# Set autoflush and return.
|
||||
$| = 1;
|
||||
return $logfh;
|
||||
}
|
||||
33
livejournal/bin/truncate-cluster.pl
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
|
||||
use strict;
|
||||
require "$ENV{LJHOME}/cgi-bin/ljlib.pl";
|
||||
|
||||
my $cid = shift;
|
||||
die "Usage: truncate-cluster.pl <clusterid>\n" unless $cid =~ /^\d+$/;
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
my $ct = $dbh->selectrow_array("SELECT COUNT(*) FROM user WHERE clusterid=?", undef, $cid);
|
||||
die $dbh->errstr if $dbh->err;
|
||||
|
||||
if ($ct > 0) {
|
||||
die "Can't truncate a cluster with users. Cluster \#$cid has $ct users.\n";
|
||||
}
|
||||
|
||||
my $cm = LJ::get_cluster_master({raw=>1}, $cid);
|
||||
die "Can't get handle to cluster \#$cid\n" unless $cm;
|
||||
|
||||
my $size;
|
||||
foreach my $table (sort (@LJ::USER_TABLES, @LJ::USER_TABLES_LOCAL)) {
|
||||
my $ts = $cm->selectrow_hashref("SHOW TABLE STATUS like '$table'");
|
||||
die "Can't get table status for $table\n" unless $ts;
|
||||
print "Size of $table = $ts->{'Data_length'}\n";
|
||||
next unless $ts->{'Data_length'};
|
||||
$cm->do("TRUNCATE TABLE $table");
|
||||
die $cm->errstr if $cm->err;
|
||||
|
||||
$size += $ts->{'Data_length'};
|
||||
|
||||
}
|
||||
print "Total size truncated (excluding indexes): $size\n";
|
||||
1071
livejournal/bin/upgrading/base-data.sql
Executable file
72
livejournal/bin/upgrading/blobify_userpics.pl
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use Getopt::Long;
|
||||
|
||||
# load libraries now
|
||||
use lib "$ENV{'LJHOME'}/cgi-bin";
|
||||
use LJ::Blob;
|
||||
use Image::Size ();
|
||||
require "ljlib.pl";
|
||||
|
||||
my $opt_fast;
|
||||
exit 1 unless
|
||||
GetOptions("fast" => \$opt_fast,
|
||||
);
|
||||
|
||||
my $clusterid = shift;
|
||||
die "Usage: blobify_userpics.pl <clusterid>\n"
|
||||
unless $clusterid;
|
||||
|
||||
my $db = LJ::get_cluster_master($clusterid);
|
||||
die "Invalid/down cluster: $clusterid\n" unless $db;
|
||||
|
||||
print "Getting count.\n";
|
||||
my $total = $db->selectrow_array("SELECT COUNT(*) FROM userpicblob2");
|
||||
my $done = 0;
|
||||
|
||||
my $loop = 1;
|
||||
while ($loop) {
|
||||
$loop = 0;
|
||||
LJ::start_request(); # shrink caches
|
||||
print "Getting 200.\n";
|
||||
my $sth = $db->prepare("SELECT userid, picid, imagedata FROM userpicblob2 LIMIT 200");
|
||||
$sth->execute;
|
||||
while (my ($uid, $picid, $image) = $sth->fetchrow_array) {
|
||||
$loop = 1;
|
||||
my $u = LJ::load_userid($uid);
|
||||
die "Can't find userid: $uid" unless $u;
|
||||
|
||||
# sometimes expunges don't expunge all the way.
|
||||
if ($u->{'statusvis'} eq "X") {
|
||||
$db->do("DELETE FROM userpicblob2 WHERE userid=$uid AND picid=$picid");
|
||||
next;
|
||||
}
|
||||
|
||||
my ($sx, $sy, $fmt) = Image::Size::imgsize(\$image);
|
||||
die "Unknown format" unless $fmt eq "GIF" || $fmt eq "JPG" || $fmt eq "PNG";
|
||||
$fmt = lc($fmt);
|
||||
|
||||
my $err;
|
||||
my $rv = LJ::Blob::put($u, "userpic", $fmt, $picid, $image, \$err);
|
||||
die "Error putting file: $u->{'user'}/$picid\n" unless $rv;
|
||||
|
||||
unless ($opt_fast) {
|
||||
# extra paranoid!
|
||||
my $get = LJ::Blob::get($u, "userpic", $fmt, $picid);
|
||||
die "Re-fetch didn't match" unless $get eq $image;
|
||||
}
|
||||
|
||||
$db->do("DELETE FROM userpicblob2 WHERE userid=$uid AND picid=$picid");
|
||||
|
||||
$done++;
|
||||
printf " Moved $uid/$picid.$fmt ($done/$total = %.2f%%)\n", ($done / $total * 100);
|
||||
}
|
||||
}
|
||||
|
||||
my $end_ct = $db->selectrow_array("SELECT COUNT(*) FROM userpicblob2");
|
||||
if ($end_ct == 0) {
|
||||
$db->do("TRUNCATE TABLE userpicblob2");
|
||||
}
|
||||
print "Done.\n";
|
||||
|
||||
77
livejournal/bin/upgrading/compress_cluster.pl
Executable file
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
|
||||
my $clusterid = shift;
|
||||
die "Usage: compress_cluster <clusterid>\n"
|
||||
unless $clusterid;
|
||||
|
||||
# load libraries now
|
||||
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
|
||||
|
||||
# force this option on, since that's the point of the tool
|
||||
$LJ::COMPRESS_TEXT = 1;
|
||||
|
||||
my $db = LJ::get_cluster_master($clusterid);
|
||||
die "Invalid/down cluster: $clusterid\n" unless $db;
|
||||
|
||||
# table, column, [ prikey1, prikey2 ]
|
||||
foreach my $t (['logtext2', 'event', ['journalid', 'jitemid']],
|
||||
['talktext2', 'body', ['journalid', 'jtalkid']]) {
|
||||
|
||||
my ($table, $col, $key) = @$t;
|
||||
my ($pk1, $pk2) = @$key; # 2 sections of primary key
|
||||
|
||||
my $total = $db->selectrow_array("SELECT COUNT(*) FROM $table");
|
||||
|
||||
print "Processing table: $table [$total total rows]\n";
|
||||
|
||||
$db->do("HANDLER $table OPEN");
|
||||
my $ct = 0;
|
||||
my $modct = 0;
|
||||
|
||||
my $bytes_pre;
|
||||
my $bytes_post;
|
||||
|
||||
my $stats = sub {
|
||||
printf("%6.2f%% done (mod=%.2f%%, size=%.2f%%),\n",
|
||||
($ct / $total) * 100,
|
||||
($modct / $ct) * 100,
|
||||
($bytes_post / $bytes_pre) * 100);
|
||||
};
|
||||
|
||||
my $loop = 1;
|
||||
while ($loop) {
|
||||
my $sth = $db->prepare("HANDLER $table READ `PRIMARY` NEXT LIMIT 100");
|
||||
$sth->execute;
|
||||
$loop = 0;
|
||||
|
||||
while (my $row = $sth->fetchrow_hashref) {
|
||||
|
||||
$loop = 1;
|
||||
# print status
|
||||
$stats->() if (++$ct % 1000 == 0);
|
||||
|
||||
# try to compress the text
|
||||
my $orig_len = length($row->{$col});
|
||||
$bytes_pre += $orig_len;
|
||||
my $new_text = LJ::text_compress($row->{$col});
|
||||
my $new_len = length($new_text);
|
||||
$bytes_post += $new_len;
|
||||
|
||||
# do nothing if the "compressed" and uncompressed sizes are the same
|
||||
next if $new_text eq $row->{$col};
|
||||
|
||||
# update this row since it compressed
|
||||
$db->do("UPDATE $table SET $col=? WHERE $pk1=? AND $pk2=? AND $col=?",
|
||||
undef, $new_text, $row->{$pk1}, $row->{$pk2}, $row->{$col});
|
||||
|
||||
$modct++;
|
||||
}
|
||||
}
|
||||
$stats->();
|
||||
|
||||
$db->do("HANDLER $table CLOSE");
|
||||
|
||||
print "$ct rows processed, $modct modified\n\n";
|
||||
}
|
||||
41
livejournal/bin/upgrading/d1d2-single.pl
Executable file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
|
||||
use strict;
|
||||
|
||||
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
|
||||
my $dbh = LJ::get_dbh("master");
|
||||
|
||||
my $user = shift @ARGV;
|
||||
my $where = "dversion=1 LIMIT 1";
|
||||
if ($user) {
|
||||
$where = "user=" . $dbh->quote($user);
|
||||
}
|
||||
|
||||
my $u = $dbh->selectrow_hashref("SELECT * FROM user WHERE $where");
|
||||
unless ($u) {
|
||||
die "No users with dversion==1 to convert. Done.\n" unless $user;
|
||||
die "User not found.\n";
|
||||
}
|
||||
|
||||
die "User not dversion 1\n" unless $u->{'dversion'} == 1;
|
||||
|
||||
my $dbch = LJ::get_cluster_master($u);
|
||||
die "Can't connect to cluster master.\n" unless $dbch;
|
||||
|
||||
print "$u->{'user'}:\n";
|
||||
my @pics = @{$dbh->selectcol_arrayref("SELECT picid FROM userpic WHERE ".
|
||||
"userid=$u->{'userid'}")};
|
||||
foreach my $picid (@pics) {
|
||||
print " $picid...\n";
|
||||
my $imagedata = $dbh->selectrow_array("SELECT imagedata FROM userpicblob ".
|
||||
"WHERE picid=$picid");
|
||||
$imagedata = $dbh->quote($imagedata);
|
||||
$dbch->do("REPLACE INTO userpicblob2 (userid, picid, imagedata) VALUES ".
|
||||
"($u->{'userid'}, $picid, $imagedata)");
|
||||
}
|
||||
|
||||
$dbh->do("UPDATE user SET dversion=2 WHERE userid=$u->{'userid'}");
|
||||
print "Done.\n";
|
||||
|
||||
|
||||
320
livejournal/bin/upgrading/d4d5-global.pl
Executable file
@@ -0,0 +1,320 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
|
||||
use strict;
|
||||
$| = 1;
|
||||
|
||||
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
|
||||
|
||||
my $BLOCK_MOVE = 5000; # user rows to get at a time before moving
|
||||
my $BLOCK_INSERT = 25; # rows to insert at a time when moving users
|
||||
my $BLOCK_UPDATE = 1000; # users to update at a time if they had no data to move
|
||||
|
||||
# used for keeping stats notes
|
||||
my %stats = (); # { 'action' => { 'pass' => { 'stat' => 'value' } } }
|
||||
|
||||
# rows come order by user, keep last username so we can avoid dups
|
||||
my $lastuser;
|
||||
|
||||
# what pass are we on?
|
||||
my $pass;
|
||||
|
||||
my $get_db_writer = sub {
|
||||
return LJ::get_dbh({raw=>1}, "master");
|
||||
};
|
||||
|
||||
my $get_db_slow = sub {
|
||||
return LJ::get_dbh({raw=>1}, "slow", "master");
|
||||
};
|
||||
|
||||
my $get_cluster_master = sub {
|
||||
my $cid = shift;
|
||||
return LJ::get_dbh({raw=>1}, "cluster$cid");
|
||||
};
|
||||
|
||||
# percentage complete
|
||||
my $status = sub {
|
||||
my ($ct, $tot, $units, $pass, $user) = @_;
|
||||
my $len = length($tot);
|
||||
|
||||
my $passtxt = $pass ? "[Pass: $pass] " : '';
|
||||
my $usertxt = $user ? " Moving user: $user" : '';
|
||||
return sprintf(" $passtxt\[%6.2f%%: %${len}d/%${len}d $units]$usertxt\n",
|
||||
($ct / $tot) * 100, $ct, $tot);
|
||||
};
|
||||
|
||||
my $header = sub {
|
||||
my $size = 50;
|
||||
return "\n" .
|
||||
("#" x $size) . "\n" .
|
||||
"# $_[0] " . (" " x ($size - length($_[0]) - 4)) . "#\n" .
|
||||
("#" x $size) . "\n\n";
|
||||
};
|
||||
|
||||
# mover function
|
||||
my $move_user = sub {
|
||||
my $user = shift;
|
||||
|
||||
# if the current user is the same as the last,
|
||||
# we have a duplicate so skip it
|
||||
return 0 if $user eq $lastuser;
|
||||
$lastuser = $user;
|
||||
|
||||
my $u = LJ::load_user($user);
|
||||
return 0 unless $u->{'dversion'} == 4;
|
||||
|
||||
# update user count for this pass
|
||||
$stats{'move'}->{$pass}->{'user_ct'}++;
|
||||
|
||||
# print status
|
||||
print $status->($stats{'move'}->{$pass}->{'ct'},
|
||||
$stats{'move'}->{$pass}->{'total'}, "rows", $pass, $user);
|
||||
|
||||
# ignore expunged users
|
||||
if ($u->{'statusvis'} eq "X") {
|
||||
LJ::update_user($u, { 'dversion' => 5 })
|
||||
or die "error updating dversion";
|
||||
$u->{'dversion'} = 5; # update local copy in memory
|
||||
return 1;
|
||||
}
|
||||
|
||||
# get a handle for every user to revalidate our connection?
|
||||
my $dbh = $get_db_writer->()
|
||||
or die "Can't connect to global master";
|
||||
my $dbslo = $get_db_slow->()
|
||||
or die "Can't connect to global slow master";
|
||||
my $dbcm = $get_cluster_master->($u->{'clusterid'})
|
||||
or die "Can't connect to cluster master ($u->{'clusterid'})";
|
||||
|
||||
# be careful, we're moving data
|
||||
foreach my $db ($dbh, $dbslo, $dbcm) {
|
||||
$db->do("SET wait_timeout=28800");
|
||||
$db->{'RaiseError'} = 1;
|
||||
}
|
||||
|
||||
my @map = (['style' => 's1style',
|
||||
qw(styleid userid styledes type formatdata is_public
|
||||
is_embedded is_colorfree opt_cache has_ads lastupdate) ],
|
||||
['overrides' => 's1overrides',
|
||||
qw(userid override) ]
|
||||
);
|
||||
|
||||
# in moving, s1stylecache gets special cased because its
|
||||
# name hasn't changed, only location. so if there is only
|
||||
# one cluster, then there's no point in physically moving it
|
||||
|
||||
if (@LJ::CLUSTERS > 1) {
|
||||
push @map, ['s1stylecache' => 's1stylecache',
|
||||
qw(styleid cleandate type opt_cache vars_stor vars_cleanver) ];
|
||||
}
|
||||
|
||||
# user 'system' is a special case. if we encounter this user we'll swap $dbcm
|
||||
# to secretly be a $dbh. because the 'system' user uses the clustered tables
|
||||
# on the global dbs, the queries will still work, we just need to misdirect them
|
||||
$dbcm = $dbh if $u->{'user'} eq 'system';
|
||||
|
||||
# styleids to delete since s1stylemap isn't keyed on user
|
||||
my @delete_styleids = ();
|
||||
|
||||
# update tables
|
||||
foreach my $tableinf (@map) {
|
||||
|
||||
# find src and dest table names
|
||||
my $src_table = shift @$tableinf;
|
||||
my $dest_table = shift @$tableinf;
|
||||
|
||||
# if this is the style table, replace into stylemap here,
|
||||
# so that if this process is killed, style and stylemap
|
||||
# won't get too out of sync
|
||||
my $do_stylemap = $src_table eq 'style' && $dest_table eq 's1style';
|
||||
|
||||
# find what columns this table has
|
||||
my @cols = @$tableinf;
|
||||
my $cols = join(",", @cols);
|
||||
my $bind_row = "(" . join(",", map { "?" } @cols) . ")";
|
||||
|
||||
my (@bind, @vals);
|
||||
my (@map_bind, @map_vals);
|
||||
|
||||
# flush rows to destination table
|
||||
my $flush = sub {
|
||||
return unless @bind;
|
||||
|
||||
# insert data
|
||||
my $bind = join(",", @bind);
|
||||
$dbcm->do("REPLACE INTO $dest_table ($cols) VALUES $bind", undef, @vals);
|
||||
|
||||
# insert new styles into s1stylemap
|
||||
if ($do_stylemap) {
|
||||
my $map_bind = join(",", @map_bind);
|
||||
$dbh->do("REPLACE INTO s1stylemap (styleid, userid) VALUES $map_bind",
|
||||
undef, @map_vals);
|
||||
}
|
||||
|
||||
# reset values
|
||||
@bind = ();
|
||||
@vals = ();
|
||||
};
|
||||
|
||||
# s1stylecache is the only table keyed on styleid, not user
|
||||
my $where = "user=" . $dbh->quote($u->{'user'});
|
||||
if ($src_table eq "s1stylecache") {
|
||||
my $ids = $dbh->selectcol_arrayref("SELECT styleid FROM style WHERE user=?",
|
||||
undef, $u->{'user'});
|
||||
my $ids_in = join(",", map { $dbh->quote($_) } @$ids) || "0";
|
||||
$where = "styleid IN ($ids_in)";
|
||||
}
|
||||
|
||||
# select from source table and build data for insert
|
||||
my $sth = $dbh->prepare("SELECT * FROM $src_table WHERE $where");
|
||||
$sth->execute();
|
||||
while (my $row = $sth->fetchrow_hashref) {
|
||||
|
||||
# so that when we look for userid later, it'll be there
|
||||
$row->{'userid'} = $u->{'userid'};
|
||||
|
||||
# build data for insert
|
||||
push @bind, $bind_row;
|
||||
push @vals, $row->{$_} foreach @cols;
|
||||
|
||||
# special case: insert new s1styles into s1stylemap
|
||||
if ($do_stylemap) {
|
||||
push @map_bind, "(?,?)";
|
||||
push @map_vals, ($row->{'styleid'}, $u->{'userid'});
|
||||
push @delete_styleids, $row->{'styleid'};
|
||||
}
|
||||
|
||||
# increment the count for this pass, style or overrides
|
||||
$stats{'move'}->{$pass}->{'ct'}++
|
||||
unless $src_table eq 's1stylecache';
|
||||
|
||||
# flush if we've reached our insert limit
|
||||
$flush->() if @bind > $BLOCK_INSERT;
|
||||
}
|
||||
|
||||
$flush->();
|
||||
}
|
||||
|
||||
# haven't died yet? everything is still going okay
|
||||
|
||||
# update dversion
|
||||
LJ::update_user($u, { 'dversion' => 5 })
|
||||
or die "error updating dversion";
|
||||
$u->{'dversion'} = 5; # update local copy in memory
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
my $dbh = $get_db_writer->();
|
||||
die "Could not connect to global master" unless $dbh;
|
||||
$dbh->{'RaiseError'} = 1;
|
||||
my $dbslo = $get_db_slow->();
|
||||
die "Could not connect to global slow master" unless $dbslo;
|
||||
$dbslo->{'RaiseError'} = 1;
|
||||
|
||||
my $ts = $dbslo->selectrow_hashref("SHOW TABLE STATUS LIKE 'overrides'");
|
||||
if ($ts->{'Type'} eq 'ISAM') {
|
||||
die "This script isn't efficient with ISAM tables. Please convert to MyISAM with:\n" .
|
||||
" mysql> ALTER TABLE overrides TYPE=MyISAM;\n\n" .
|
||||
"Then re-run this script.\n";
|
||||
}
|
||||
|
||||
print $header->("Moving user data");
|
||||
|
||||
# first pass should get everything, second pass will
|
||||
# get changes made during the first
|
||||
foreach my $p (1..2) {
|
||||
|
||||
# this is strange. perl bug?
|
||||
$pass = $p;
|
||||
|
||||
# get totals from overrides and style so we can do a percentage bar
|
||||
# there will be overlaps in this when users have both styles and
|
||||
# overrides, but we'll fix those up as we go
|
||||
foreach (qw(style overrides)) {
|
||||
$stats{'move'}->{$pass}->{'total'} += $dbslo->selectrow_array("SELECT COUNT(*) FROM $_");
|
||||
}
|
||||
|
||||
print "Processing $stats{'move'}->{$p}->{'total'} total rows\n";
|
||||
|
||||
# 2 passes, so we catch people with styles & overrides,
|
||||
# styles w/o overrides, and overrides w/o styles
|
||||
foreach my $table (qw(style overrides)) {
|
||||
|
||||
$lastuser = '';
|
||||
|
||||
# loop until we have no more users to convert
|
||||
my $ct;
|
||||
do {
|
||||
|
||||
# get blocks of $BLOCK_MOVE users at a time
|
||||
my $sth = $dbslo->prepare("SELECT user FROM $table WHERE user>? " .
|
||||
"ORDER BY user LIMIT $BLOCK_MOVE");
|
||||
$sth->execute($lastuser);
|
||||
$ct = 0;
|
||||
while (my $user = $sth->fetchrow_array) {
|
||||
$move_user->($user);
|
||||
$ct++;
|
||||
}
|
||||
|
||||
} while $ct;
|
||||
}
|
||||
|
||||
print $stats{'move'}->{$p}->{'user_ct'}+0 . " users moved\n\n";
|
||||
}
|
||||
|
||||
# now we're confident that all users have had their data moved if
|
||||
# necessary, so we can just unconditionally change dversions.
|
||||
|
||||
print $header->("Updating remaining users");
|
||||
|
||||
$stats{'update'}->{'total'} = $dbslo->selectrow_array("SELECT COUNT(*) FROM user WHERE dversion=4");
|
||||
print "Converting $stats{'update'}->{'total'} users\n";
|
||||
|
||||
# now update dversions for users who had no data to move
|
||||
if ($stats{'update'}->{'total'}) {
|
||||
|
||||
my $get_users = sub {
|
||||
my $sth = $dbslo->prepare("SELECT userid, user FROM user " .
|
||||
"WHERE dversion=4 LIMIT $BLOCK_UPDATE");
|
||||
$sth->execute();
|
||||
my @rows; # [ userid, user ]
|
||||
while ( my ($userid, $user) = $sth->fetchrow_array) {
|
||||
push @rows, [ $userid, $user ];
|
||||
}
|
||||
return @rows;
|
||||
};
|
||||
|
||||
while (my @rows = $get_users->()) {
|
||||
|
||||
# update database
|
||||
my $bind = join(",", map { "?" } @rows);
|
||||
my @vals = map { $_->[0] } @rows;
|
||||
$dbh->do("UPDATE user SET dversion=5 WHERE userid IN ($bind)",
|
||||
undef, @vals);
|
||||
|
||||
# update memcache
|
||||
foreach (@rows) {
|
||||
LJ::MemCache::delete([$_->[0], "userid:" . $_->[0]]);
|
||||
LJ::MemCache::delete([$_->[1], "user:" . $_->[1]]);
|
||||
}
|
||||
$stats{'update'}->{'ct'} += @rows;
|
||||
|
||||
print $status->($stats{'update'}->{'ct'}, $stats{'update'}->{'total'}, "users");
|
||||
}
|
||||
}
|
||||
|
||||
my $zeropad = sub {
|
||||
return sprintf("%d", $_[0]);
|
||||
};
|
||||
|
||||
# calculate total move stats
|
||||
foreach (1..2) {
|
||||
$stats{'move'}->{'total_ct'} += $stats{'move'}->{$_}->{'ct'};
|
||||
$stats{'move'}->{'total_user_ct'} += $stats{'move'}->{$_}->{'user_ct'};
|
||||
}
|
||||
|
||||
print $header->("Dversion 4->5 conversion completed");
|
||||
print " Rows moved: " . $zeropad->($stats{'move'}->{'total_ct'}) . "\n";
|
||||
print " Users moved: " . $zeropad->($stats{'move'}->{'total_user_ct'}) . "\n";
|
||||
print "Users updated: " . $zeropad->($stats{'update'}->{'ct'}) . "\n\n";
|
||||
349
livejournal/bin/upgrading/d5d6-mkf.pl
Executable file
@@ -0,0 +1,349 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
|
||||
use strict;
|
||||
use Getopt::Long;
|
||||
$| = 1;
|
||||
|
||||
use lib ("$ENV{LJHOME}/cgi-bin");
|
||||
require "ljlib.pl";
|
||||
use LJ::User;
|
||||
|
||||
use constant DEBUG => 0; # turn on for debugging (mostly db handle crap)
|
||||
|
||||
my $BLOCK_MOVE = 5000; # user rows to get at a time before moving
|
||||
my $BLOCK_INSERT = 25; # rows to insert at a time when moving users
|
||||
my $BLOCK_UPDATE = 1000; # users to update at a time if they had no data to move
|
||||
|
||||
# get options
|
||||
my %opts;
|
||||
exit 1 unless
|
||||
GetOptions("lock=s" => \$opts{locktype},);
|
||||
|
||||
# if no locking, notify them about it
|
||||
die "ERROR: Lock must be of types 'ddlockd' or 'none'\n"
|
||||
if $opts{locktype} && $opts{locktype} !~ m/^(?:ddlockd|none)$/;
|
||||
|
||||
# used for keeping stats notes
|
||||
my %stats = (); # { 'stat' => 'value' }
|
||||
|
||||
my %handle;
|
||||
|
||||
# database handle retrieval sub
|
||||
my $get_db_handles = sub {
|
||||
# figure out what cluster to load
|
||||
my $cid = shift(@_) + 0;
|
||||
|
||||
my $dbh = $handle{0};
|
||||
unless ($dbh) {
|
||||
$dbh = $handle{0} = LJ::get_dbh({ raw => 1 }, "master");
|
||||
print "Connecting to master ($dbh)...\n";
|
||||
eval {
|
||||
$dbh->do("SET wait_timeout=28800");
|
||||
};
|
||||
$dbh->{'RaiseError'} = 1;
|
||||
}
|
||||
|
||||
my $dbcm;
|
||||
$dbcm = $handle{$cid} if $cid;
|
||||
if ($cid && ! $dbcm) {
|
||||
$dbcm = $handle{$cid} = LJ::get_cluster_master({ raw => 1 }, $cid);
|
||||
print "Connecting to cluster $cid ($dbcm)...\n";
|
||||
return undef unless $dbcm;
|
||||
eval {
|
||||
$dbcm->do("SET wait_timeout=28800");
|
||||
};
|
||||
$dbcm->{'RaiseError'} = 1;
|
||||
}
|
||||
|
||||
# return one or both, depending on what they wanted
|
||||
return $cid ? ($dbh, $dbcm) : $dbh;
|
||||
};
|
||||
|
||||
# percentage complete
|
||||
my $status = sub {
|
||||
my ($ct, $tot, $units, $user) = @_;
|
||||
my $len = length($tot);
|
||||
|
||||
my $usertxt = $user ? " Moving user: $user" : '';
|
||||
return sprintf(" \[%6.2f%%: %${len}d/%${len}d $units]$usertxt\n",
|
||||
($ct / $tot) * 100, $ct, $tot);
|
||||
};
|
||||
|
||||
my $header = sub {
|
||||
my $size = 50;
|
||||
return "\n" .
|
||||
("#" x $size) . "\n" .
|
||||
"# $_[0] " . (" " x ($size - length($_[0]) - 4)) . "#\n" .
|
||||
("#" x $size) . "\n\n";
|
||||
};
|
||||
|
||||
my $zeropad = sub {
|
||||
return sprintf("%d", $_[0]);
|
||||
};
|
||||
|
||||
# mover function
|
||||
my $move_user = sub {
|
||||
my $u = shift;
|
||||
|
||||
# make sure our user is of the proper dversion
|
||||
return 0 unless $u->{'dversion'} == 5;
|
||||
|
||||
# at this point, try to get a lock for this user
|
||||
my $lock;
|
||||
if ($opts{locktype} eq 'ddlockd') {
|
||||
$lock = LJ::locker()->trylock("d5d6-$u->{user}");
|
||||
return 1 unless $lock;
|
||||
}
|
||||
|
||||
# get a handle for every user to revalidate our connection?
|
||||
my ($dbh, $dbcm) = $get_db_handles->($u->{clusterid});
|
||||
return 0 unless $dbh;
|
||||
|
||||
if ($dbcm) {
|
||||
# assign this dbcm to the user
|
||||
$u->set_dbcm($dbcm)
|
||||
or die "unable to set database for $u->{user}: dbcm=$dbcm\n";
|
||||
}
|
||||
|
||||
# verify dversion hasn't changed on us (done by another job?)
|
||||
my $dversion = $dbh->selectrow_array("SELECT dversion FROM user WHERE userid = $u->{userid}");
|
||||
return 1 unless $dversion == 5;
|
||||
|
||||
# ignore expunged users
|
||||
if ($u->{'statusvis'} eq "X" || $u->{'clusterid'} == 0) {
|
||||
LJ::update_user($u, { dversion => 6 })
|
||||
or die "error updating dversion";
|
||||
$u->{dversion} = 6; # update local copy in memory
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0 unless $dbcm;
|
||||
|
||||
# step 1: get all friend groups and move those. safe to just grab with no limit because
|
||||
# there are limits to how many friend groups you can have (30).
|
||||
my $rows = $dbh->selectall_arrayref('SELECT groupnum, groupname, sortorder, is_public ' .
|
||||
'FROM friendgroup WHERE userid = ?', undef, $u->{userid});
|
||||
if (@$rows) {
|
||||
# got some rows, create an update statement
|
||||
my (@bind, @vars);
|
||||
foreach my $row (@$rows) {
|
||||
push @bind, "($u->{userid}, ?, ?, ?, ?)";
|
||||
push @vars, $_ foreach @$row;
|
||||
}
|
||||
my $bind = join ',', @bind;
|
||||
eval {
|
||||
$u->do("INSERT INTO friendgroup2 (userid, groupnum, groupname, sortorder, is_public) " .
|
||||
"VALUES $bind", undef, @vars);
|
||||
};
|
||||
}
|
||||
|
||||
# general purpose flusher for use below
|
||||
my (@bind, @vars);
|
||||
my $flush = sub {
|
||||
return unless @bind;
|
||||
my ($table, $cols) = @_;
|
||||
|
||||
# insert data into cluster master
|
||||
my $bind = join(",", @bind);
|
||||
$u->do("REPLACE INTO $table ($cols) VALUES $bind", undef, @vars);
|
||||
die "error in flush $table: " . $u->errstr . "\n" if $u->err;
|
||||
|
||||
# reset values
|
||||
@bind = ();
|
||||
@vars = ();
|
||||
};
|
||||
|
||||
# step 1.5: see if the user has any data already? clear it if so.
|
||||
my $counter = $dbcm->selectrow_array("SELECT max FROM counter WHERE journalid = ? AND area = 'R'",
|
||||
undef, $u->{userid});
|
||||
$counter += 0;
|
||||
if ($counter > 0) {
|
||||
# yep, so we need to delete stuff, real data first
|
||||
foreach my $table (qw(memorable2 memkeyword2 userkeywords)) {
|
||||
$u->do("DELETE FROM $table WHERE userid = ?", undef, $u->{userid});
|
||||
die "error in clear: " . $u->errstr . "\n" if $u->err;
|
||||
}
|
||||
|
||||
# delete counters used (including memcache of such)
|
||||
$u->do("DELETE FROM counter WHERE journalid = ? AND area IN ('R', 'K')", undef, $u->{userid});
|
||||
die "error in clear: " . $u->errstr . "\n" if $u->err;
|
||||
LJ::MemCache::delete([$u->{userid}, "auc:$u->{userid}:R"]);
|
||||
LJ::MemCache::delete([$u->{userid}, "auc:$u->{userid}:K"]);
|
||||
}
|
||||
|
||||
# step 2: get all of their memories and move them, creating the oldmemid -> newmemid mapping
|
||||
# that we can use in later steps to migrate keywords
|
||||
my %bindings; # ( oldid => newid )
|
||||
my $sth = $dbh->prepare('SELECT memid, journalid, jitemid, des, security ' .
|
||||
'FROM memorable WHERE userid = ?');
|
||||
$sth->execute($u->{userid});
|
||||
while (my $row = $sth->fetchrow_hashref()) {
|
||||
# got a row, good
|
||||
my $newid = LJ::alloc_user_counter($u, 'R');
|
||||
die "Error: unable to allocate type 'R' counter for $u->{user}($u->{userid})\n"
|
||||
unless $newid;
|
||||
$bindings{$row->{memid}} = $newid;
|
||||
|
||||
# push data
|
||||
push @bind, "($u->{userid}, ?, ?, ?, ?, ?)";
|
||||
push @vars, ($newid, map { $row->{$_} } qw(journalid jitemid des security));
|
||||
|
||||
# flush if necessary
|
||||
$flush->('memorable2', 'userid, memid, journalid, ditemid, des, security')
|
||||
if @bind > $BLOCK_INSERT;
|
||||
}
|
||||
$flush->('memorable2', 'userid, memid, journalid, ditemid, des, security');
|
||||
|
||||
# step 3: get the list of keywords that these memories all use
|
||||
my %kwmap;
|
||||
if (%bindings) {
|
||||
my $memids = join ',', map { $_+0 } keys %bindings;
|
||||
my $rows = $dbh->selectall_arrayref("SELECT memid, kwid FROM memkeyword WHERE memid IN ($memids)");
|
||||
push @{$kwmap{$_->[1]}}, $_->[0] foreach @$rows; # kwid -> [ memid, memid, memid ... ]
|
||||
}
|
||||
|
||||
# step 4: get the actual keywords associated with these keyword ids
|
||||
my %kwidmap;
|
||||
if (%kwmap) {
|
||||
my $kwids = join ',', map { $_+0 } keys %kwmap;
|
||||
my $rows = $dbh->selectall_arrayref("SELECT kwid, keyword FROM keywords WHERE kwid IN ($kwids)");
|
||||
%kwidmap = map { $_->[0] => $_->[1] } @$rows; # kwid -> keyword
|
||||
}
|
||||
|
||||
# step 5: now migrate all keywords into userkeywords table
|
||||
my %mappings;
|
||||
while (my ($kwid, $keyword) = each %kwidmap) {
|
||||
# reallocate counter
|
||||
my $newkwid = LJ::alloc_user_counter($u, 'K');
|
||||
die "Error: unable to allocate type 'K' counter for $u->{user}($u->{userid})\n"
|
||||
unless $newkwid;
|
||||
$mappings{$kwid} = $newkwid;
|
||||
|
||||
# push data
|
||||
push @bind, "($u->{userid}, ?, ?)";
|
||||
push @vars, ($newkwid, $keyword);
|
||||
|
||||
# flush if necessary
|
||||
$flush->('userkeywords', 'userid, kwid, keyword')
|
||||
if @bind > $BLOCK_INSERT;
|
||||
}
|
||||
$flush->('userkeywords', 'userid, kwid, keyword');
|
||||
|
||||
# step 6: now we have to do some mapping conversions and put new data into memkeyword2 table
|
||||
while (my ($oldkwid, $oldmemids) = each %kwmap) {
|
||||
foreach my $oldmemid (@$oldmemids) {
|
||||
# get new data
|
||||
my ($newkwid, $newmemid) = ($mappings{$oldkwid}, $bindings{$oldmemid});
|
||||
|
||||
# push data
|
||||
push @bind, "($u->{userid}, ?, ?)";
|
||||
push @vars, ($newmemid, $newkwid);
|
||||
|
||||
# flush?
|
||||
$flush->('memkeyword2', 'userid, memid, kwid')
|
||||
if @bind > $BLOCK_INSERT;
|
||||
}
|
||||
}
|
||||
$flush->('memkeyword2', 'userid, memid, kwid');
|
||||
|
||||
# delete memcache keys that hold old data
|
||||
LJ::MemCache::delete([$u->{userid}, "memkwid:$u->{userid}"]);
|
||||
|
||||
# haven't died yet? everything is still going okay, so update dversion
|
||||
LJ::update_user($u, { 'dversion' => 6 })
|
||||
or die "error updating dversion";
|
||||
$u->{'dversion'} = 6; # update local copy in memory
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
# get dbh handle
|
||||
my $dbh = LJ::get_db_writer(); # just so we can get users...
|
||||
die "Could not connect to global master" unless $dbh;
|
||||
|
||||
# get user count
|
||||
my $total = $dbh->selectrow_array("SELECT COUNT(*) FROM user WHERE dversion = 5");
|
||||
$stats{'total_users'} = $total+0;
|
||||
|
||||
# print out header and total we're moving
|
||||
print $header->("Moving user data");
|
||||
print "Processing $stats{'total_users'} total users with the old dversion\n";
|
||||
|
||||
# loop until we have no more users to convert
|
||||
my $ct;
|
||||
while (1) {
|
||||
|
||||
# get blocks of $BLOCK_MOVE users at a time
|
||||
my $sth = $dbh->prepare("SELECT * FROM user WHERE dversion = 5 LIMIT $BLOCK_MOVE");
|
||||
$sth->execute();
|
||||
$ct = 0;
|
||||
my %us;
|
||||
|
||||
my %fast; # people to move fast
|
||||
|
||||
while (my $u = $sth->fetchrow_hashref()) {
|
||||
$us{$u->{userid}} = $u;
|
||||
$ct++;
|
||||
$fast{$u->{userid}} = 1;
|
||||
}
|
||||
|
||||
# jump out if we got nothing
|
||||
last unless $ct;
|
||||
|
||||
# now that we have %us, we can see who has data
|
||||
my $ids = join ',', map { $_+0 } keys %us;
|
||||
my $has_memorable = $dbh->selectcol_arrayref("SELECT DISTINCT userid FROM memorable WHERE userid IN ($ids)");
|
||||
my $has_fgroups = $dbh->selectcol_arrayref("SELECT DISTINCT userid FROM friendgroup WHERE userid IN ($ids)");
|
||||
my %uids = ( map { $_ => 1 } (@$has_memorable, @$has_fgroups) );
|
||||
|
||||
# these people actually have data to migrate; don't move them fast
|
||||
delete $fast{$_} foreach keys %uids;
|
||||
|
||||
# now see who we can do in a fast way
|
||||
my @fast_ids = map { $_+0 } keys %fast;
|
||||
if (@fast_ids) {
|
||||
print "Converting ", scalar(@fast_ids), " users quickly...\n";
|
||||
# update stats for counting and print
|
||||
$stats{'fast_moved'} += @fast_ids;
|
||||
print $status->($stats{'slow_moved'}+$stats{'fast_moved'}, $stats{'total_users'}, "users");
|
||||
|
||||
# block update
|
||||
LJ::update_user(\@fast_ids, { dversion => 6 });
|
||||
}
|
||||
|
||||
my $slow_todo = scalar keys %uids;
|
||||
print "Of $BLOCK_MOVE, $slow_todo have to be slow-converted...\n";
|
||||
my @ids = randlist(keys %uids);
|
||||
foreach my $id (@ids) {
|
||||
# this person has memories, move them the slow way
|
||||
die "Userid $id in \$has_memorable, but not in \%us...fatal error\n" unless $us{$id};
|
||||
|
||||
# now move the user
|
||||
bless $us{$id}, 'LJ::User';
|
||||
if ($move_user->($us{$id})) {
|
||||
$stats{'slow_moved'}++;
|
||||
print $status->($stats{'slow_moved'}+$stats{'fast_moved'}, $stats{'total_users'}, "users", $us{$id}{user});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# ...done?
|
||||
print $header->("Dversion 5->6 conversion completed");
|
||||
print " Users moved: " . $zeropad->($stats{'slow_moved'}) . "\n";
|
||||
print "Users updated: " . $zeropad->($stats{'fast_moved'}) . "\n\n";
|
||||
|
||||
# helper function to randomize stuff
|
||||
sub randlist
|
||||
{
|
||||
my @rlist = @_;
|
||||
my $size = scalar(@rlist);
|
||||
|
||||
my $i;
|
||||
for ($i=0; $i<$size; $i++) {
|
||||
unshift @rlist, splice(@rlist, $i+int(rand()*($size-$i)), 1);
|
||||
}
|
||||
return @rlist;
|
||||
}
|
||||
352
livejournal/bin/upgrading/d6d7-userpics.pl
Executable file
@@ -0,0 +1,352 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
|
||||
use strict;
|
||||
use Getopt::Long;
|
||||
$| = 1;
|
||||
|
||||
use lib "$ENV{'LJHOME'}/cgi-bin/";
|
||||
require "ljlib.pl";
|
||||
use LJ::Blob;
|
||||
use LJ::User;
|
||||
|
||||
use constant DEBUG => 0; # turn on for debugging (mostly db handle crap)
|
||||
|
||||
my $BLOCK_MOVE = 5000; # user rows to get at a time before moving
|
||||
my $BLOCK_INSERT = 25; # rows to insert at a time when moving users
|
||||
my $BLOCK_UPDATE = 1000; # users to update at a time if they had no data to move
|
||||
|
||||
# get options
|
||||
my %opts;
|
||||
exit 1 unless
|
||||
GetOptions("lock=s" => \$opts{locktype},
|
||||
"user=s" => \$opts{user},
|
||||
"total=i" => \$opts{total},);
|
||||
|
||||
|
||||
# if no locking, notify them about it
|
||||
die "ERROR: Lock must be of types 'ddlockd' or 'none'\n"
|
||||
if $opts{locktype} && $opts{locktype} !~ m/^(?:ddlockd|none)$/;
|
||||
|
||||
# used for keeping stats notes
|
||||
my %stats = (); # { 'stat' => 'value' }
|
||||
|
||||
my %handle;
|
||||
|
||||
# database handle retrieval sub
|
||||
my $get_db_handles = sub {
|
||||
# figure out what cluster to load
|
||||
my $cid = shift(@_) + 0;
|
||||
|
||||
my $dbh = $handle{0};
|
||||
unless ($dbh) {
|
||||
$dbh = $handle{0} = LJ::get_dbh({ raw => 1 }, "master");
|
||||
print "Connecting to master ($dbh)...\n";
|
||||
eval {
|
||||
$dbh->do("SET wait_timeout=28800");
|
||||
};
|
||||
$dbh->{'RaiseError'} = 1;
|
||||
}
|
||||
|
||||
my $dbcm;
|
||||
$dbcm = $handle{$cid} if $cid;
|
||||
if ($cid && ! $dbcm) {
|
||||
$dbcm = $handle{$cid} = LJ::get_cluster_master({ raw => 1 }, $cid);
|
||||
print "Connecting to cluster $cid ($dbcm)...\n";
|
||||
return undef unless $dbcm;
|
||||
eval {
|
||||
$dbcm->do("SET wait_timeout=28800");
|
||||
};
|
||||
$dbcm->{'RaiseError'} = 1;
|
||||
}
|
||||
|
||||
# return one or both, depending on what they wanted
|
||||
return $cid ? ($dbh, $dbcm) : $dbh;
|
||||
};
|
||||
|
||||
# percentage complete
|
||||
my $status = sub {
|
||||
my ($ct, $tot, $units, $user) = @_;
|
||||
my $len = length($tot);
|
||||
|
||||
my $usertxt = $user ? " Moving user: $user" : '';
|
||||
return sprintf(" \[%6.2f%%: %${len}d/%${len}d $units]$usertxt\n",
|
||||
($ct / $tot) * 100, $ct, $tot);
|
||||
};
|
||||
|
||||
my $header = sub {
|
||||
my $size = 50;
|
||||
return "\n" .
|
||||
("#" x $size) . "\n" .
|
||||
"# $_[0] " . (" " x ($size - length($_[0]) - 4)) . "#\n" .
|
||||
("#" x $size) . "\n\n";
|
||||
};
|
||||
|
||||
my $zeropad = sub {
|
||||
return sprintf("%d", $_[0]);
|
||||
};
|
||||
|
||||
# mover function
|
||||
my $move_user = sub {
|
||||
my $u = shift;
|
||||
|
||||
# make sure our user is of the proper dversion
|
||||
return 0 unless $u->{'dversion'} == 6;
|
||||
|
||||
# at this point, try to get a lock for this user
|
||||
my $lock;
|
||||
if ($opts{locktype} eq 'ddlockd') {
|
||||
$lock = LJ::locker()->trylock("d6d7-$u->{user}");
|
||||
return 1 unless $lock;
|
||||
}
|
||||
|
||||
# get a handle for every user to revalidate our connection?
|
||||
my ($dbh, $dbcm) = $get_db_handles->($u->{clusterid});
|
||||
return 0 unless $dbh;
|
||||
|
||||
# assign this dbcm to the user
|
||||
if ($dbcm) {
|
||||
$u->set_dbcm($dbcm)
|
||||
or die "unable to set database for $u->{user}: dbcm=$dbcm\n";
|
||||
}
|
||||
|
||||
# verify dversion hasn't changed on us (done by another job?)
|
||||
my $dversion = $dbh->selectrow_array("SELECT dversion FROM user WHERE userid = $u->{userid}");
|
||||
return 1 unless $dversion == 6;
|
||||
|
||||
# ignore expunged users
|
||||
if ($u->{'statusvis'} eq "X" || $u->{'clusterid'} == 0) {
|
||||
LJ::update_user($u, { dversion => 7 })
|
||||
or die "error updating dversion";
|
||||
$u->{dversion} = 7; # update local copy in memory
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0 unless $dbcm;
|
||||
|
||||
# step 0.5: delete all the bogus userblob rows for this user
|
||||
# This is due to the auto_increment for the blobid overflowing
|
||||
# and thus all entries recieving an id of max id for a mediumint.
|
||||
# This is lame.
|
||||
my $domainid = LJ::get_blob_domainid('userpic');
|
||||
$u->do("DELETE FROM userblob WHERE journalid=$u->{userid} AND domain=$domainid AND blobid>=16777216");
|
||||
die "error in delete: " . $u->errstr . "\n" if $u->err;
|
||||
|
||||
# step 1: get all user pictures and move those. safe to just grab with no limit
|
||||
# since users can only have a limited number of them
|
||||
my $rows = $dbh->selectall_arrayref('SELECT picid, userid, contenttype, width, height, state, picdate, md5base64 ' .
|
||||
'FROM userpic WHERE userid = ?', undef, $u->{userid}) || [];
|
||||
|
||||
if (@$rows) {
|
||||
# got some rows, create an update statement
|
||||
my (@bind, @vars, @blobids, @blobbind, @picinfo);
|
||||
foreach my $row (@$rows) {
|
||||
my $picid = $row->[0];
|
||||
push @bind, "(?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
$row->[2] = {'image/gif' => 'G',
|
||||
'image/jpeg' => 'J',
|
||||
'image/png' => 'P'}->{$row->[2]};
|
||||
push @vars, @$row;
|
||||
|
||||
# [picid, fmt]
|
||||
my $fmt = {'G' => 'gif',
|
||||
'J' => 'jpg',
|
||||
'P' => 'png'}->{$row->[2]};
|
||||
push @picinfo, [$picid, $fmt];
|
||||
|
||||
# picids
|
||||
push @blobids, $picid;
|
||||
push @blobbind, "?";
|
||||
}
|
||||
|
||||
my $bind = join ',', @bind;
|
||||
$u->do("REPLACE INTO userpic2 (picid, userid, fmt, width, height, state, picdate, md5base64) " .
|
||||
"VALUES $bind", undef, @vars);
|
||||
die "error in userpic2 replace: " . $u->errstr . "\n" if $u->err;
|
||||
|
||||
# step 1.5: insert missing rows into the userblob table
|
||||
my $blobbind = join ',', @blobbind;
|
||||
my $blobrows = $dbcm->selectall_hashref("SELECT blobid FROM userblob WHERE journalid=$u->{userid} AND domain=$domainid " .
|
||||
"AND blobid IN ($blobbind)", 'blobid', undef, @blobids) || {};
|
||||
|
||||
my (@insertbind, @insertvars);
|
||||
foreach my $pic (@picinfo) {
|
||||
my ($picid, $fmt) = @$pic;
|
||||
unless ($blobrows->{$picid}) {
|
||||
push @insertbind, "(?, ?, ?, ?)";
|
||||
|
||||
my $blob = LJ::Blob::get($u, "userpic", $fmt, $picid);
|
||||
my $length = length($blob);
|
||||
|
||||
push @insertvars, $u->{'userid'}, $domainid, $picid, $length;
|
||||
}
|
||||
}
|
||||
if (@insertbind) {
|
||||
my $insertbind = join ',', @insertbind;
|
||||
$u->do("INSERT IGNORE INTO userblob (journalid, domain, blobid, length) " .
|
||||
"VALUES $insertbind", undef, @insertvars);
|
||||
die "error in userblob insert: " . $u->errstr . "\n" if $u->err;
|
||||
}
|
||||
}
|
||||
|
||||
# general purpose flusher for use below
|
||||
my (@bind, @vars);
|
||||
my $flush = sub {
|
||||
return unless @bind;
|
||||
my ($table, $cols) = @_;
|
||||
|
||||
# insert data into cluster master
|
||||
my $bind = join(",", @bind);
|
||||
$u->do("REPLACE INTO $table ($cols) VALUES $bind", undef, @vars);
|
||||
die "error in flush $table: " . $u->errstr . "\n" if $u->err;
|
||||
|
||||
# reset values
|
||||
@bind = ();
|
||||
@vars = ();
|
||||
};
|
||||
|
||||
# step 2: get the mapping of all of their keywords
|
||||
my $kwrows = $dbh->selectall_arrayref('SELECT picid, kwid FROM userpicmap WHERE userid=?',
|
||||
undef, $u->{'userid'});
|
||||
my %kwmap;
|
||||
if (@$kwrows) {
|
||||
push @{$kwmap{$_->[1]}}, $_->[0] foreach @$kwrows; # kwid -> [ picid, picid, picid ... ]
|
||||
}
|
||||
|
||||
# step 3: get the actual keywords associated with these keyword ids
|
||||
my %kwidmap;
|
||||
if (%kwmap) {
|
||||
my $kwids = join ',', map { $_+0 } keys %kwmap;
|
||||
my $rows = $dbh->selectall_arrayref("SELECT kwid, keyword FROM keywords WHERE kwid IN ($kwids)");
|
||||
%kwidmap = map { $_->[0] => $_->[1] } @$rows; # kwid -> keyword
|
||||
}
|
||||
|
||||
# step 4: now migrate all keywords into userkeywords table
|
||||
my %mappings;
|
||||
while (my ($kwid, $keyword) = each %kwidmap) {
|
||||
# reallocate counter
|
||||
my $newkwid = LJ::get_keyword_id($u, $keyword);
|
||||
die "Error: unable to get keyword id for $u->{user}($u->{userid}), keyword '$keyword'\n"
|
||||
unless $newkwid;
|
||||
$mappings{$kwid} = $newkwid;
|
||||
}
|
||||
|
||||
# step 5: now we have to do some mapping conversions and put new data into userpicmap2 table
|
||||
while (my ($oldkwid, $picids) = each %kwmap) {
|
||||
foreach my $picid (@$picids) {
|
||||
# get new data
|
||||
my $newkwid = $mappings{$oldkwid};
|
||||
|
||||
# push data
|
||||
push @bind, "($u->{userid}, ?, ?)";
|
||||
push @vars, ($picid, $newkwid);
|
||||
|
||||
# flush?
|
||||
$flush->('userpicmap2', 'userid, picid, kwid')
|
||||
if @bind > $BLOCK_INSERT;
|
||||
}
|
||||
}
|
||||
$flush->('userpicmap2', 'userid, picid, kwid');
|
||||
|
||||
# delete memcache keys that hold old data
|
||||
LJ::MemCache::delete([$u->{userid}, "upicinf:$u->{userid}"]);
|
||||
|
||||
# haven't died yet? everything is still going okay, so update dversion
|
||||
LJ::update_user($u, { 'dversion' => 7 })
|
||||
or die "error updating dversion";
|
||||
$u->{'dversion'} = 7; # update local copy in memory
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
# get dbh handle
|
||||
my $dbh = LJ::get_db_writer(); # just so we can get users...
|
||||
die "Could not connect to global master" unless $dbh;
|
||||
|
||||
# get user count
|
||||
my $total = $opts{total} || $dbh->selectrow_array("SELECT COUNT(*) FROM user WHERE dversion = 6");
|
||||
$stats{'total_users'} = $total+0;
|
||||
|
||||
# print out header and total we're moving
|
||||
print $header->("Moving user data");
|
||||
print "Processing $stats{'total_users'} total users with the old dversion\n";
|
||||
|
||||
# loop until we have no more users to convert
|
||||
my $ct;
|
||||
while (1) {
|
||||
# get users to move
|
||||
my $sth;
|
||||
if ($opts{user}) {
|
||||
$sth = $dbh->prepare("SELECT * FROM user WHERE user = ? AND dversion = 6");
|
||||
$sth->execute($opts{user});
|
||||
} else {
|
||||
$sth = $dbh->prepare("SELECT * FROM user WHERE dversion = 6 LIMIT $BLOCK_MOVE");
|
||||
$sth->execute();
|
||||
}
|
||||
|
||||
# get blocks of $BLOCK_MOVE users at a time
|
||||
$ct = 0;
|
||||
my (%us, %fast);
|
||||
while (my $u = $sth->fetchrow_hashref()) {
|
||||
$us{$u->{userid}} = $u;
|
||||
$fast{$u->{userid}} = 1;
|
||||
$ct++;
|
||||
}
|
||||
|
||||
# jump out if we got nothing
|
||||
last unless $ct;
|
||||
|
||||
# now that we have %us, we can see who has data
|
||||
my $ids = join ',', map { $_+0 } keys %us;
|
||||
my $has_upics = $dbh->selectcol_arrayref("SELECT DISTINCT userid FROM userpic WHERE userid IN ($ids)");
|
||||
my %uids = ( map { $_ => 1 } (@$has_upics) );
|
||||
|
||||
# remove folks that have userpics from the fast list
|
||||
delete $fast{$_} foreach keys %uids;
|
||||
|
||||
# now see who we can do in a fast way
|
||||
my @fast_ids = map { $_+0 } keys %fast;
|
||||
if (@fast_ids) {
|
||||
# update stats for counting and print
|
||||
$stats{'fast_moved'} += @fast_ids;
|
||||
print $status->($stats{'slow_moved'}+$stats{'fast_moved'}, $stats{'total_users'}, "users");
|
||||
|
||||
# block update
|
||||
LJ::update_user(\@fast_ids, { dversion => 7 });
|
||||
}
|
||||
|
||||
my $slow_todo = scalar keys %uids;
|
||||
print "Of $BLOCK_MOVE, $slow_todo have to be slow-converted...\n";
|
||||
my @ids = randlist(keys %uids);
|
||||
foreach my $id (@ids) {
|
||||
# this person has userpics, move them the slow way
|
||||
die "Userid $id in \$has_upics, but not in \%us...fatal error\n" unless $us{$id};
|
||||
|
||||
# now move the user
|
||||
bless $us{$id}, 'LJ::User';
|
||||
if ($move_user->($us{$id})) {
|
||||
$stats{'slow_moved'}++;
|
||||
print $status->($stats{'slow_moved'}+$stats{'fast_moved'}, $stats{'total_users'}, "users", $us{$id}{user});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# ...done?
|
||||
print $header->("Dversion 6->7 conversion completed");
|
||||
print " Users moved: " . $zeropad->($stats{'slow_moved'}) . "\n";
|
||||
print "Users updated: " . $zeropad->($stats{'fast_moved'}) . "\n\n";
|
||||
|
||||
# helper function to randomize stuff
|
||||
sub randlist
|
||||
{
|
||||
my @rlist = @_;
|
||||
my $size = scalar(@rlist);
|
||||
|
||||
my $i;
|
||||
for ($i=0; $i<$size; $i++) {
|
||||
unshift @rlist, splice(@rlist, $i+int(rand()*($size-$i)), 1);
|
||||
}
|
||||
return @rlist;
|
||||
}
|
||||
207
livejournal/bin/upgrading/deadphrases.dat
Executable file
@@ -0,0 +1,207 @@
|
||||
# these get removed if found by texttool.pl
|
||||
#
|
||||
|
||||
general /allpics.bml.edit
|
||||
general /allpics.bml.nopics.text
|
||||
|
||||
general /community/join.bml.label.authpost
|
||||
general /community/join.bml.label.closedcomm
|
||||
|
||||
general /community/manage.bml.actmembers
|
||||
general /community/manage.bml.actsettings
|
||||
general /community/manage.bml.commlist.actmoderate
|
||||
|
||||
general /community/members.bml.manage
|
||||
|
||||
general /community/search.bml.contasmember
|
||||
general /community/search.bml.userlikes
|
||||
|
||||
general /community/settings.bml.label.admconsole
|
||||
general /community/settings.bml.manage
|
||||
|
||||
general /create.bml.aolnotice.head
|
||||
general /create.bml.aolnotice.text
|
||||
general /create.bml.error.seebelow
|
||||
general /create.bml.proceed.head
|
||||
general /create.bml.proceed.text
|
||||
|
||||
general /create.bml.tos.error
|
||||
general /create.bml.tos.haveread
|
||||
general /create.bml.tos.p1.2
|
||||
|
||||
general /editinfo.bml.allowshocontact.email.if_domainaddy
|
||||
general /editinfo.bml.allowshowcontact.email.reason
|
||||
general /editinfo.bml.newemail.body
|
||||
general /editinfo.bml.settings.about
|
||||
general /editinfo.bml.showsubjicons.about
|
||||
general /editinfo.bml.showsubjicons.header
|
||||
general /editinfo.bml.tm.about
|
||||
general /editinfo.bml.topicdir.about
|
||||
general /editinfo.bml.topicdir.header
|
||||
|
||||
general /friends/edit.bml.btn.proceed
|
||||
general /friends/edit.bml.edit.head
|
||||
general /friends/edit.bml.edit.text
|
||||
|
||||
general /editjournal.bml.enterlogin
|
||||
general /editjournal.bml.lostinfo.head
|
||||
general /editjournal.bml.lostinfo.text
|
||||
|
||||
general /editjournal_do.bml.error.mustlogin
|
||||
general /editjournal_do.bml.success.edit
|
||||
|
||||
general /friends/editgroups.bml.login.header
|
||||
general /friends/editgroups.bml.login.text
|
||||
|
||||
general /interests.bml.findsim.account.notallowed
|
||||
general /interests.bml.findsim.account.notloggedin
|
||||
general /interests.bml.findsim.btn.find
|
||||
general /interests.bml.findsim.head
|
||||
general /interests.bml.findsim.simtouser
|
||||
general /interests.bml.findsim.text
|
||||
general /interests.bml.interests.findsim1
|
||||
general /interests.bml.interests.findsim2
|
||||
|
||||
general /login.bml.error.forgotpass
|
||||
general /login.bml.error.noaccount
|
||||
|
||||
general /manage/index.bml.information.setlang.about
|
||||
general /manage/index.bml.information.setscheme.about
|
||||
|
||||
general /modify.bml.btn.proceed
|
||||
general /modify.bml.journalstatus.about
|
||||
general /modify.bml.journalstatus.head
|
||||
general /modify.bml.journalstatus.select.activated
|
||||
general /modify.bml.journalstatus.select.deleted
|
||||
general /modify.bml.journalstatus.select.head
|
||||
general /modify.bml.journalstatus.select.suspended
|
||||
general /modify.bml.lostinfo.head
|
||||
general /modify.bml.lostinfo.text
|
||||
general /modify.bml.modify.head
|
||||
general /modify.bml.modify.text
|
||||
|
||||
general /modify_do.bml.title
|
||||
|
||||
general /multisearch.bml.region.text
|
||||
|
||||
general /register.bml.new.body
|
||||
|
||||
general /setlang.bml.select
|
||||
general /setlang.bml.switch
|
||||
general /setlang.bml.title
|
||||
|
||||
general /setscheme.bml.current
|
||||
general /setscheme.bml.default
|
||||
general /setscheme.bml.noschemes
|
||||
general /setscheme.bml.select
|
||||
general /setscheme.bml.switch
|
||||
general /setscheme.bml.title
|
||||
|
||||
general /support/faqbrowse.bml.title
|
||||
|
||||
general /talkpost.bml.label.picturetouse
|
||||
|
||||
general /talkpost_do.bml.opt.spellcheck
|
||||
|
||||
general /talkread.bml.pageofpages
|
||||
|
||||
general /tools/memadd.bml.body.added.body
|
||||
|
||||
general /update.bml.update.about
|
||||
general /update.bml.login.success
|
||||
general /update.bml.htmlokay
|
||||
|
||||
general /uploadpic.bml.success.text
|
||||
general /uploadpic.bml.btn.proceed
|
||||
general /uploadpic.bml.error.badurl
|
||||
general /uploadpic.bml.error.databasedown
|
||||
general /uploadpic.bml.error.filetoolarge
|
||||
general /uploadpic.bml.error.imagetoolarge
|
||||
general /uploadpic.bml.error.invalidauth
|
||||
general /uploadpic.bml.error.invalidimage
|
||||
general /uploadpic.bml.error.toomanypics
|
||||
general /uploadpic.bml.error.unknownmode
|
||||
general /uploadpic.bml.error.urlerror
|
||||
general /uploadpic.bml.fromfile
|
||||
general /uploadpic.bml.fromfile.key
|
||||
general /uploadpic.bml.fromurl
|
||||
general /uploadpic.bml.fromurl.key
|
||||
general /uploadpic.bml.header
|
||||
general /uploadpic.bml.imagesize.by
|
||||
general /uploadpic.bml.kilobytes
|
||||
general /uploadpic.bml.makedefault
|
||||
general /uploadpic.bml.makedefault.key
|
||||
general /uploadpic.bml.restriction.fileformat
|
||||
general /uploadpic.bml.restriction.filesize
|
||||
general /uploadpic.bml.restriction.imagesize
|
||||
general /uploadpic.bml.success.editpics
|
||||
general /uploadpic.bml.success.header
|
||||
general /uploadpic.bml.success.preview
|
||||
general /uploadpic.bml.success.upload
|
||||
general /uploadpic.bml.text
|
||||
general /uploadpic.bml.title
|
||||
|
||||
general /uploadpic_do.bml.error.urlerror
|
||||
general uploadpic.error.toolarge
|
||||
|
||||
general /userinfo.bml.canpost
|
||||
general /userinfo.bml.closedmembership.body
|
||||
general /userinfo.bml.fbpictures
|
||||
general /userinfo.bml.label.viewlabel
|
||||
general /userinfo.bml.openmembership.body
|
||||
general /userinfo.bml.posthere
|
||||
general /userinfo.bml.rpmembership.body
|
||||
general /userinfo.bml.syn.lastnew
|
||||
|
||||
general /register.bml.error.alreadyvalidated
|
||||
|
||||
general /tools/memories.bml.entry
|
||||
general /tools/memories.bml.entries
|
||||
|
||||
general /create.bml.tos.p1
|
||||
general /create.bml.email.text
|
||||
general /create.bml.email.note
|
||||
|
||||
general /syn/index.bml.table.cost
|
||||
general /syn/index.bml.quota.text
|
||||
general /syn/index.bml.quota.your
|
||||
general /syn/index.bml.quota.numbers
|
||||
general /syn/index.bml.invalid.overquota
|
||||
general /syn/index.bml.invalid.overquota.text
|
||||
general /syn/index.bml.invalid.overquota.title
|
||||
general /syn/index.bml.invalid.overquota.username
|
||||
general /syn/index.bml.accounttype.notallowed
|
||||
general /syn/index.bml.add.other.title
|
||||
general /syn/index.bml.add.other.text
|
||||
general /syn/index.bml.notused
|
||||
general /userinfo.bml.syn.cost
|
||||
|
||||
general bml.needlogin.body
|
||||
|
||||
general /userinfo.bml.label.frsyndication
|
||||
|
||||
general /syn/index.bml.invalid.address
|
||||
|
||||
general /community/members.bml.key.name
|
||||
general /community/members.bml.success.addusers
|
||||
|
||||
general /userinfo.bml.label.totalfriends
|
||||
|
||||
general /community/settings.bml.label.closedmemb
|
||||
|
||||
general /talkscreen.bml.title
|
||||
|
||||
general /community/members.bml.success.message
|
||||
|
||||
general /community/transfer.bml.error.banned
|
||||
|
||||
general /create.bml.age.check.question
|
||||
general /create.bml.age.check.yes
|
||||
general /create.bml.age.check2.question
|
||||
general /create.bml.age.check2.yes
|
||||
general /create.bml.age.head
|
||||
|
||||
general /community/members.bml.reinvited
|
||||
general /community/membres.bml.success.invited
|
||||
|
||||
general /customize/index.bml.s1
|
||||
4676
livejournal/bin/upgrading/en.dat
Executable file
48
livejournal/bin/upgrading/import-includes.pl
Executable file
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/perl
|
||||
# This script goes through all of the files in your include directory
|
||||
# (LJHOME/htdocs/inc) and then imports ones that are specified by your
|
||||
# ljconfig.pl file (%LJ::FILEEDIT_VIA_DB) into your database if the file
|
||||
# on disk is newer than the one in the database.
|
||||
|
||||
use strict;
|
||||
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
|
||||
|
||||
# create list of files to check
|
||||
my $dir = "$ENV{'LJHOME'}/htdocs/inc";
|
||||
print "searching for files to check against database...";
|
||||
opendir DIR, $dir
|
||||
or die "Unable to open $ENV{'LJHOME'}/htdocs/inc for searching.\n";
|
||||
my @files = grep { $LJ::FILEEDIT_VIA_DB ||
|
||||
$LJ::FILEEDIT_VIA_DB{$_} } readdir(DIR);
|
||||
my $count = scalar(@files);
|
||||
print $count+0 . " found.\n";
|
||||
|
||||
# now iterate through and check times
|
||||
my $dbh = LJ::get_db_writer();
|
||||
foreach my $file (@files) {
|
||||
my $path = "$dir/$file";
|
||||
next unless -f $path;
|
||||
|
||||
# now get filetime
|
||||
my $ftimedisk = (stat($path))[9];
|
||||
my $ftimedb = $dbh->selectrow_array("SELECT updatetime
|
||||
FROM includetext WHERE incname=?", undef, $file)+0;
|
||||
|
||||
# check
|
||||
if ($ftimedisk > $ftimedb) {
|
||||
# load file
|
||||
open FILE, "<$path";
|
||||
my $content = join("", <FILE>);
|
||||
close FILE;
|
||||
|
||||
# now do SQL
|
||||
print "$file newer on disk...updating database...";
|
||||
$dbh->do("REPLACE INTO includetext (incname, inctext, updatetime)" .
|
||||
"VALUES (?,?,UNIX_TIMESTAMP())", undef, $file, $content);
|
||||
print $dbh->err ? "error: " . $dbh->errstr . ".\n" : "done.\n";
|
||||
} else {
|
||||
print "$file newer in database, ignored.\n";
|
||||
}
|
||||
}
|
||||
|
||||
print "all done.\n";
|
||||
53
livejournal/bin/upgrading/make_system.pl
Executable file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
|
||||
use strict;
|
||||
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
|
||||
|
||||
my $dbh = LJ::get_dbh("master");
|
||||
|
||||
print "
|
||||
This tool will create your LiveJournal 'system' account and
|
||||
set its password. Or, if you already have a system user, it'll change
|
||||
its password to whatever you specify.
|
||||
";
|
||||
|
||||
print "Enter password for the 'system' account: ";
|
||||
my $pass = <STDIN>;
|
||||
chomp $pass;
|
||||
|
||||
print "\n";
|
||||
|
||||
print "Creating system account...\n";
|
||||
unless (LJ::create_account({ 'user' => 'system',
|
||||
'name' => 'System Account',
|
||||
'password' => $pass }))
|
||||
{
|
||||
print "Already exists.\nModifying 'system' account...\n";
|
||||
$dbh->do("UPDATE user SET password=? WHERE user='system'",
|
||||
undef, $pass);
|
||||
}
|
||||
|
||||
my $u = LJ::load_user("system");
|
||||
unless ($u) {
|
||||
print "ERROR: can't find newly-created system account.\n";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
print "Giving 'system' account 'admin' priv on all areas...\n";
|
||||
if (LJ::check_priv($u, "admin", "*")) {
|
||||
print "Already has it.\n";
|
||||
} else {
|
||||
my $sth = $dbh->prepare("INSERT INTO priv_map (userid, prlid, arg) ".
|
||||
"SELECT $u->{'userid'}, prlid, '*' ".
|
||||
"FROM priv_list WHERE privcode='admin'");
|
||||
$sth->execute;
|
||||
if ($dbh->err || $sth->rows == 0) {
|
||||
print "Couldn't grant system account admin privs\n";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
|
||||
print "Done.\n\n";
|
||||
|
||||
|
||||
323
livejournal/bin/upgrading/migrate-phoneposts.pl
Executable file
@@ -0,0 +1,323 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use lib "$ENV{LJHOME}/cgi-bin";
|
||||
require 'ljlib.pl';
|
||||
use LJ::Blob;
|
||||
use LJ::User;
|
||||
use Getopt::Long;
|
||||
use IPC::Open3;
|
||||
use Digest::MD5;
|
||||
|
||||
# this script is a migrater that will move phone posts from an old storage method
|
||||
# into mogilefs.
|
||||
|
||||
# the basic theory is that we iterate over all clusters, find all phoneposts that
|
||||
# aren't in mogile right now, and put them there
|
||||
|
||||
# determine
|
||||
my ($one, $besteffort, $dryrun, $user, $verify, $verbose, $clusters, $purge);
|
||||
my $rv = GetOptions("best-effort" => \$besteffort,
|
||||
"one" => \$one,
|
||||
"dry-run" => \$dryrun,
|
||||
"user=s" => \$user,
|
||||
"verify" => \$verify,
|
||||
"verbose" => \$verbose,
|
||||
"purge-old" => \$purge,
|
||||
"clusters=s" => \$clusters,);
|
||||
unless ($rv) {
|
||||
die <<ERRMSG;
|
||||
This script supports the following command line arguments:
|
||||
|
||||
--clusters=X[-Y]
|
||||
Only handle clusters in this range. You can specify a single
|
||||
number, or a range of two numbers with a dash.
|
||||
|
||||
--user=username
|
||||
Only move this particular user.
|
||||
|
||||
--one
|
||||
Only move one user. (But it moves all their phone posts.) This is
|
||||
used for testing.
|
||||
|
||||
--verify
|
||||
If specified, this option will reload the phonepost from MogileFS and
|
||||
make sure it's been stored successfully.
|
||||
|
||||
--dry-run
|
||||
If on, do not update the database. This mode will put the phonepost
|
||||
in MogileFS and give you paths to examine the phone posts and make
|
||||
sure everything is okay. It will not update the phonepost2 table,
|
||||
though.
|
||||
|
||||
--best-effort
|
||||
Normally, if a problem is encountered (null phonepost, md5 mismatch,
|
||||
connection failure, etc) the script will die to make sure
|
||||
everything goes well. With this flag, we don't die and instead
|
||||
just print to standard error.
|
||||
|
||||
--purge-old
|
||||
Sometimes we run into data that is for users that have since
|
||||
moved to a different cluster. Normally we ignore it, but
|
||||
with this option, we'll clean that data up as we find it.
|
||||
|
||||
--verbose
|
||||
Be very chatty.
|
||||
ERRMSG
|
||||
}
|
||||
|
||||
# make sure ljconfig is setup right (or so we hope)
|
||||
die "Please define a 'phoneposts' class in your \%LJ::MOGILEFS_CONFIG\n"
|
||||
unless defined $LJ::MOGILEFS_CONFIG{classes}->{phoneposts};
|
||||
die "Unable to find MogileFS object (\%LJ::MOGILEFS_CONFIG not setup?)\n"
|
||||
unless $LJ::MogileFS;
|
||||
|
||||
# setup stderr if we're in best effort mode
|
||||
if ($besteffort) {
|
||||
my $oldfd = select(STDERR);
|
||||
$| = 1;
|
||||
select($oldfd);
|
||||
}
|
||||
|
||||
# operation modes
|
||||
if ($user) {
|
||||
# move a single user
|
||||
my $u = LJ::load_user($user);
|
||||
die "No such user: $user\n" unless $u;
|
||||
handle_userid($u->{userid}, $u->{clusterid});
|
||||
|
||||
} else {
|
||||
# parse the clusters
|
||||
my @clusters;
|
||||
if ($clusters) {
|
||||
if ($clusters =~ /^(\d+)(?:-(\d+))?$/) {
|
||||
my ($min, $max) = map { $_ + 0 } ($1, $2 || $1);
|
||||
push @clusters, $_ foreach $min..$max;
|
||||
} else {
|
||||
die "Error: --clusters argument not of right format.\n";
|
||||
}
|
||||
} else {
|
||||
@clusters = @LJ::CLUSTERS;
|
||||
}
|
||||
|
||||
# now iterate over the clusters to pick
|
||||
my $ctotal = scalar(@clusters);
|
||||
my $ccount = 0;
|
||||
foreach my $cid (sort { $a <=> $b } @clusters) {
|
||||
# status report
|
||||
$ccount++;
|
||||
print "\nChecking cluster $cid...\n\n";
|
||||
|
||||
# get a handle
|
||||
my $dbcm = get_db_handle($cid);
|
||||
|
||||
# get all userids
|
||||
print "Getting userids...\n";
|
||||
my $limit = $one ? 'LIMIT 1' : '';
|
||||
my $userids = $dbcm->selectcol_arrayref
|
||||
("SELECT DISTINCT userid FROM phonepostentry WHERE (location='blob' OR location IS NULL) $limit");
|
||||
my $total = scalar(@$userids);
|
||||
|
||||
# iterate over userids
|
||||
my $count = 0;
|
||||
print "Beginning iteration over userids...\n";
|
||||
foreach my $userid (@$userids) {
|
||||
# move this phonepost
|
||||
my $extra = sprintf("[%6.2f%%, $ccount of $ctotal] ", (++$count/$total*100));
|
||||
handle_userid($userid, $cid, $extra);
|
||||
}
|
||||
|
||||
# don't hit up more clusters
|
||||
last if $one;
|
||||
}
|
||||
}
|
||||
print "\n";
|
||||
|
||||
print "Updater terminating.\n";
|
||||
|
||||
#############################################################################
|
||||
### helper subs down here
|
||||
|
||||
# take a userid and move their phone posts
|
||||
sub handle_userid {
|
||||
my ($userid, $cid, $extra) = @_;
|
||||
|
||||
# load user to move and do some sanity checks
|
||||
my $u = LJ::load_userid($userid);
|
||||
unless ($u) {
|
||||
LJ::end_request();
|
||||
LJ::start_request();
|
||||
$u = LJ::load_userid($userid);
|
||||
}
|
||||
die "ERROR: Unable to load userid $userid\n"
|
||||
unless $u;
|
||||
|
||||
# if they're expunged, they might have data somewhere if they were
|
||||
# copy-moved from A to B, then expunged on B. now we're on A and
|
||||
# need to delete it ourselves (if purge-old is on)
|
||||
if ($u->{clusterid} == 0 && $u->{statusvis} eq "X") {
|
||||
return unless $purge;
|
||||
# if we get here, the user has indicated they want data purged, get handle
|
||||
my $to_purge_dbcm = get_db_handle($cid);
|
||||
my $ct = $to_purge_dbcm->do("DELETE FROM phonepostentry WHERE userid = ?", undef, $u->{userid});
|
||||
print "\tnotice: purged $ct old rows.\n\n"
|
||||
if $verbose;
|
||||
return;
|
||||
}
|
||||
|
||||
# get a handle
|
||||
my $dbcm = get_db_handle($u->{clusterid});
|
||||
|
||||
# print that we're doing this user
|
||||
print "$extra$u->{user}($u->{userid})\n";
|
||||
|
||||
# if a user has been moved to another cluster, but the source data from
|
||||
# phonepostentry wasn't deleted, we need to ignore the user or purge their data
|
||||
if ($u->{clusterid} != $cid) {
|
||||
return unless $purge;
|
||||
|
||||
# verify they have some rows on the new side
|
||||
my $count = $dbcm->selectrow_array
|
||||
("SELECT COUNT(*) FROM phonepostentry WHERE userid = ?",
|
||||
undef, $u->{userid});
|
||||
return unless $count;
|
||||
|
||||
# if we get here, the user has indicated they want data purged, get handle
|
||||
my $to_purge_dbcm = get_db_handle($cid);
|
||||
|
||||
# delete the old data
|
||||
if ($dryrun) {
|
||||
print "\tnotice: need to delete phonepostentry rows.\n\n"
|
||||
if $verbose;
|
||||
} else {
|
||||
my $ct = $to_purge_dbcm->do("DELETE FROM phonepostentry WHERE userid = ?", undef, $u->{userid});
|
||||
print "\tnotice: purged $ct old rows.\n\n"
|
||||
if $verbose;
|
||||
}
|
||||
|
||||
# nothing else to do here
|
||||
return;
|
||||
}
|
||||
|
||||
# get all their photos that aren't in mogile already
|
||||
my $rows = $dbcm->selectall_arrayref
|
||||
("SELECT filetype, blobid FROM phonepostentry WHERE userid = ? ".
|
||||
"AND (location = 'blob' OR location IS NULL)",
|
||||
undef, $u->{userid});
|
||||
return unless @$rows;
|
||||
|
||||
# if a user has been moved to another cluster, but the source data from
|
||||
# phonepost2 wasn't deleted, we need to ignore the user
|
||||
return unless $u->{clusterid} == $cid;
|
||||
|
||||
# now we have a userid and blobids, get the photos from the blob server
|
||||
foreach my $row (@$rows) {
|
||||
my ($filetype, $blobid) = @$row;
|
||||
print "\tstarting move for blobid $blobid\n"
|
||||
if $verbose;
|
||||
my $format = { 0 => 'mp3', 1 => 'ogg', 2 => 'wav' }->{$filetype};
|
||||
my $data = LJ::Blob::get($u, "phonepost", $format, $blobid);
|
||||
|
||||
# get length
|
||||
my $len = length($data);
|
||||
|
||||
if (! $len) {
|
||||
my $has_blob = $dbcm->selectrow_array("SELECT COUNT(*) FROM userblob WHERE ".
|
||||
"journalid=? AND domain=? AND blobid=?",
|
||||
undef, $u->{userid},
|
||||
LJ::get_blob_domainid("phonepost"),
|
||||
$blobid);
|
||||
if (! $has_blob) {
|
||||
$dbcm->do("UPDATE phonepostentry SET location='none' ".
|
||||
"WHERE userid=? AND blobid=?", undef, $u->{userid}, $blobid);
|
||||
print "\tnote: changed phonepost entry location to 'none'\n\n"
|
||||
if $verbose;
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
if ($besteffort && !$len) {
|
||||
print STDERR "empty_phonepost userid=$u->{userid} blobid=$blobid\n";
|
||||
print "\twarning: empty phonepost.\n\n"
|
||||
if $verbose;
|
||||
next;
|
||||
}
|
||||
die "Error: data from blob empty ($u->{user}, 'phonepost', $format, $blobid)\n"
|
||||
unless $len;
|
||||
|
||||
# get filehandle to Mogile and put the file there
|
||||
print "\tdata length = $len bytes, uploading to MogileFS...\n"
|
||||
if $verbose;
|
||||
my $fh = $LJ::MogileFS->new_file("pp:$u->{userid}:$blobid", 'phoneposts');
|
||||
if ($besteffort && !$fh) {
|
||||
print STDERR "new_file_failed userid=$u->{userid} blobid=$blobid\n";
|
||||
print "\twarning: failed in call to new_file\n\n"
|
||||
if $verbose;
|
||||
next;
|
||||
}
|
||||
die "Unable to get filehandle to save file to MogileFS\n"
|
||||
unless $fh;
|
||||
|
||||
# now save the file and close the handles
|
||||
$fh->print($data);
|
||||
my $rv = $fh->close;
|
||||
if ($besteffort && !$rv) {
|
||||
print STDERR "close_failed userid=$u->{userid} blobid=$blobid reason=$@\n";
|
||||
print "\twarning: failed in call to cloes: $@\n\n"
|
||||
if $verbose;
|
||||
next;
|
||||
}
|
||||
die "Unable to save file to MogileFS: $@\n"
|
||||
unless $rv;
|
||||
|
||||
# extra verification
|
||||
if ($verify) {
|
||||
my $data2 = $LJ::MogileFS->get_file_data("pp:$u->{userid}:$blobid");
|
||||
my $eq = ($data2 && $$data2 eq $data) ? 1 : 0;
|
||||
if ($besteffort && !$eq) {
|
||||
print STDERR "verify_failed userid=$u->{userid} blobid=$blobid\n";
|
||||
print "\twarning: verify failed; phone post not updated\n\n"
|
||||
if $verbose;
|
||||
next;
|
||||
}
|
||||
die "\tERROR: phone post NOT stored successfully, content mismatch\n"
|
||||
unless $eq;
|
||||
print "\tverified length = " . length($$data2) . " bytes...\n"
|
||||
if $verbose;
|
||||
}
|
||||
|
||||
# done moving this phone post
|
||||
unless ($dryrun) {
|
||||
print "\tupdating database for this phone post...\n"
|
||||
if $verbose;
|
||||
$dbcm->do("UPDATE phonepostentry SET location = 'mogile' WHERE userid = ? AND blobid = ?",
|
||||
undef, $u->{userid}, $blobid);
|
||||
}
|
||||
|
||||
# get the paths so the user can verify if they want
|
||||
if ($verbose) {
|
||||
my @paths = $LJ::MogileFS->get_paths("pp:$u->{userid}:$blobid", 1);
|
||||
print "\tverify mogile path: $_\n" foreach @paths;
|
||||
print "\tphone post update complete.\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# a sub to get a cluster handle and set it up for our use
|
||||
sub get_db_handle {
|
||||
my $cid = shift;
|
||||
|
||||
my $dbcm = LJ::get_cluster_master({ raw => 1 }, $cid);
|
||||
unless ($dbcm) {
|
||||
print STDERR "handle_unavailable clusterid=$cid\n";
|
||||
die "ERROR: unable to get raw handle to cluster $cid\n";
|
||||
}
|
||||
eval {
|
||||
$dbcm->do("SET wait_timeout = 28800");
|
||||
die $dbcm->errstr if $dbcm->err;
|
||||
};
|
||||
die "Couldn't set wait_timeout on $cid: $@\n" if $@;
|
||||
$dbcm->{'RaiseError'} = 1;
|
||||
|
||||
return $dbcm;
|
||||
}
|
||||
318
livejournal/bin/upgrading/migrate-userpics.pl
Executable file
@@ -0,0 +1,318 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use lib "$ENV{LJHOME}/cgi-bin";
|
||||
require 'ljlib.pl';
|
||||
use LJ::Blob;
|
||||
use LJ::User;
|
||||
use Getopt::Long;
|
||||
use IPC::Open3;
|
||||
use Digest::MD5;
|
||||
|
||||
# this script is a migrater that will move userpics from an old storage method
|
||||
# into mogilefs.
|
||||
|
||||
# the basic theory is that we iterate over all clusters, find all userpics that
|
||||
# aren't in mogile right now, and put them there
|
||||
|
||||
# determine
|
||||
my ($one, $besteffort, $dryrun, $user, $verify, $verbose, $clusters, $purge);
|
||||
my $rv = GetOptions("best-effort" => \$besteffort,
|
||||
"one" => \$one,
|
||||
"dry-run" => \$dryrun,
|
||||
"user=s" => \$user,
|
||||
"verify" => \$verify,
|
||||
"verbose" => \$verbose,
|
||||
"purge-old" => \$purge,
|
||||
"clusters=s" => \$clusters,);
|
||||
unless ($rv) {
|
||||
die <<ERRMSG;
|
||||
This script supports the following command line arguments:
|
||||
|
||||
--clusters=X[-Y]
|
||||
Only handle clusters in this range. You can specify a
|
||||
single number, or a range of two numbers with a dash.
|
||||
|
||||
--user=username
|
||||
Only move this particular user.
|
||||
|
||||
--one
|
||||
Only move one user. (But it moves all their pictures.)
|
||||
This is used for testing.
|
||||
|
||||
--verify
|
||||
If specified, this option will reload the userpic from
|
||||
MogileFS and make sure it's been stored successfully.
|
||||
|
||||
--dry-run
|
||||
If on, do not update the database. This mode will put the
|
||||
userpic in MogileFS and give you paths to examine the picture
|
||||
and make sure everything is okay. It will not update the
|
||||
userpic2 table, though.
|
||||
|
||||
--best-effort
|
||||
Normally, if a problem is encountered (null userpic, md5
|
||||
mismatch, connection failure, etc) the script will die to
|
||||
make sure everything goes well. With this flag, we don't
|
||||
die and instead just print to standard error.
|
||||
|
||||
--purge-old
|
||||
Sometimes we run into data that is for users that have since
|
||||
moved to a different cluster. Normally we ignore it, but
|
||||
with this option, we'll clean that data up as we find it.
|
||||
|
||||
--verbose
|
||||
Be very chatty.
|
||||
ERRMSG
|
||||
}
|
||||
|
||||
# make sure ljconfig is setup right (or so we hope)
|
||||
die "Please define a 'userpics' class in your \%LJ::MOGILEFS_CONFIG\n"
|
||||
unless defined $LJ::MOGILEFS_CONFIG{classes}->{userpics};
|
||||
die "Unable to find MogileFS object (\%LJ::MOGILEFS_CONFIG not setup?)\n"
|
||||
unless $LJ::MogileFS;
|
||||
|
||||
# setup stderr if we're in best effort mode
|
||||
if ($besteffort) {
|
||||
my $oldfd = select(STDERR);
|
||||
$| = 1;
|
||||
select($oldfd);
|
||||
}
|
||||
|
||||
# operation modes
|
||||
if ($user) {
|
||||
# move a single user
|
||||
my $u = LJ::load_user($user);
|
||||
die "No such user: $user\n" unless $u;
|
||||
handle_userid($u->{userid}, $u->{clusterid});
|
||||
|
||||
} else {
|
||||
# parse the clusters
|
||||
my @clusters;
|
||||
if ($clusters) {
|
||||
if ($clusters =~ /^(\d+)(?:-(\d+))?$/) {
|
||||
my ($min, $max) = map { $_ + 0 } ($1, $2 || $1);
|
||||
push @clusters, $_ foreach $min..$max;
|
||||
} else {
|
||||
die "Error: --clusters argument not of right format.\n";
|
||||
}
|
||||
} else {
|
||||
@clusters = @LJ::CLUSTERS;
|
||||
}
|
||||
|
||||
# now iterate over the clusters to pick
|
||||
my $ctotal = scalar(@clusters);
|
||||
my $ccount = 0;
|
||||
foreach my $cid (sort { $a <=> $b } @clusters) {
|
||||
# status report
|
||||
$ccount++;
|
||||
print "\nChecking cluster $cid...\n\n";
|
||||
|
||||
# get a handle
|
||||
my $dbcm = get_db_handle($cid);
|
||||
|
||||
# get all userids
|
||||
print "Getting userids...\n";
|
||||
my $limit = $one ? 'LIMIT 1' : '';
|
||||
my $userids = $dbcm->selectcol_arrayref
|
||||
("SELECT DISTINCT userid FROM userpic2 WHERE location <> 'mogile' OR location IS NULL $limit");
|
||||
my $total = scalar(@$userids);
|
||||
|
||||
# iterate over userids
|
||||
my $count = 0;
|
||||
print "Beginning iteration over userids...\n";
|
||||
foreach my $userid (@$userids) {
|
||||
# move this userpic
|
||||
my $extra = sprintf("[%6.2f%%, $ccount of $ctotal] ", (++$count/$total*100));
|
||||
handle_userid($userid, $cid, $extra);
|
||||
}
|
||||
|
||||
# don't hit up more clusters
|
||||
last if $one;
|
||||
}
|
||||
}
|
||||
print "\n";
|
||||
|
||||
print "Updater terminating.\n";
|
||||
|
||||
#############################################################################
|
||||
### helper subs down here
|
||||
|
||||
# take a userid and move their pictures. returns 0 on error, 1 on successful
|
||||
# move of a user's pictures, and 2 meaning the user isn't ready for moving
|
||||
# (dversion < 7, etc)
|
||||
sub handle_userid {
|
||||
my ($userid, $cid, $extra) = @_;
|
||||
|
||||
# load user to move and do some sanity checks
|
||||
my $u = LJ::load_userid($userid);
|
||||
unless ($u) {
|
||||
LJ::end_request();
|
||||
LJ::start_request();
|
||||
$u = LJ::load_userid($userid);
|
||||
}
|
||||
die "ERROR: Unable to load userid $userid\n"
|
||||
unless $u;
|
||||
|
||||
# if they're expunged, they might have data somewhere if they were
|
||||
# copy-moved from A to B, then expunged on B. now we're on A and
|
||||
# need to delete it ourselves (if purge-old is on)
|
||||
if ($u->{clusterid} == 0 && $u->{statusvis} eq "X") {
|
||||
return unless $purge;
|
||||
# if we get here, the user has indicated they want data purged, get handle
|
||||
my $to_purge_dbcm = get_db_handle($cid);
|
||||
my $ct = $to_purge_dbcm->do("DELETE FROM userpic2 WHERE userid = ?", undef, $u->{userid});
|
||||
print "\tnotice: purged $ct old rows.\n\n"
|
||||
if $verbose;
|
||||
return;
|
||||
}
|
||||
|
||||
# get a handle
|
||||
my $dbcm = get_db_handle($u->{clusterid});
|
||||
|
||||
# print that we're doing this user
|
||||
print "$extra$u->{user}($u->{userid})\n";
|
||||
|
||||
# if a user has been moved to another cluster, but the source data from
|
||||
# userpic2 wasn't deleted, we need to ignore the user or purge their data
|
||||
if ($u->{clusterid} != $cid) {
|
||||
return unless $purge;
|
||||
|
||||
# verify they have some rows on the new side
|
||||
my $count = $dbcm->selectrow_array
|
||||
("SELECT COUNT(*) FROM userpic2 WHERE userid = ?",
|
||||
undef, $u->{userid});
|
||||
return unless $count;
|
||||
|
||||
# if we get here, the user has indicated they want data purged, get handle
|
||||
my $to_purge_dbcm = get_db_handle($cid);
|
||||
|
||||
# delete the old data
|
||||
if ($dryrun) {
|
||||
print "\tnotice: need to delete userpic2 rows.\n\n"
|
||||
if $verbose;
|
||||
} else {
|
||||
my $ct = $to_purge_dbcm->do("DELETE FROM userpic2 WHERE userid = ?", undef, $u->{userid});
|
||||
print "\tnotice: purged $ct old rows.\n\n"
|
||||
if $verbose;
|
||||
}
|
||||
|
||||
# nothing else to do here
|
||||
return;
|
||||
}
|
||||
|
||||
# get all their photos that aren't in mogile already
|
||||
my $picids = $dbcm->selectall_arrayref
|
||||
("SELECT picid, md5base64, fmt FROM userpic2 WHERE userid = ? AND (location <> 'mogile' OR location IS NULL)",
|
||||
undef, $u->{userid});
|
||||
return unless @$picids;
|
||||
|
||||
# now we have a userid and picids, get the photos from the blob server
|
||||
foreach my $row (@$picids) {
|
||||
my ($picid, $md5, $fmt) = @$row;
|
||||
print "\tstarting move for picid $picid\n"
|
||||
if $verbose;
|
||||
my $format = { G => 'gif', J => 'jpg', P => 'png' }->{$fmt};
|
||||
my $data = LJ::Blob::get($u, "userpic", $format, $picid);
|
||||
|
||||
# get length
|
||||
my $len = length($data);
|
||||
if ($besteffort && !$len) {
|
||||
print STDERR "empty_userpic userid=$u->{userid} picid=$picid\n";
|
||||
print "\twarning: empty userpic.\n\n"
|
||||
if $verbose;
|
||||
next;
|
||||
}
|
||||
die "Error: data from blob empty ($u->{user}, 'userpic', $format, $picid)\n"
|
||||
unless $len;
|
||||
|
||||
# verify the md5 of this picture with what's in the database
|
||||
my $blobmd5 = Digest::MD5::md5_base64($data);
|
||||
if ($besteffort && ($md5 ne $blobmd5)) {
|
||||
print STDERR "md5_mismatch userid=$u->{userid} picid=$picid dbmd5=$md5 blobmd5=$blobmd5\n";
|
||||
print "\twarning: md5 mismatch; database=$md5, blobserver=$blobmd5\n\n"
|
||||
if $verbose;
|
||||
next;
|
||||
}
|
||||
die "\tError: data from blobserver md5 mismatch: database=$md5, blobserver=$blobmd5\n"
|
||||
unless $md5 eq $blobmd5;
|
||||
print "\tverified md5; database=$md5, blobserver=$blobmd5\n"
|
||||
if $verbose;
|
||||
|
||||
# get filehandle to Mogile and put the file there
|
||||
print "\tdata length = $len bytes, uploading to MogileFS...\n"
|
||||
if $verbose;
|
||||
my $fh = $LJ::MogileFS->new_file($u->mogfs_userpic_key($picid), 'userpics');
|
||||
if ($besteffort && !$fh) {
|
||||
print STDERR "new_file_failed userid=$u->{userid} picid=$picid\n";
|
||||
print "\twarning: failed in call to new_file\n\n"
|
||||
if $verbose;
|
||||
next;
|
||||
}
|
||||
die "Unable to get filehandle to save file to MogileFS\n"
|
||||
unless $fh;
|
||||
|
||||
# now save the file and close the handles
|
||||
$fh->print($data);
|
||||
my $rv = $fh->close;
|
||||
if ($besteffort && !$rv) {
|
||||
print STDERR "close_failed userid=$u->{userid} picid=$picid reason=$@\n";
|
||||
print "\twarning: failed in call to cloes: $@\n\n"
|
||||
if $verbose;
|
||||
next;
|
||||
}
|
||||
die "Unable to save file to MogileFS: $@\n"
|
||||
unless $rv;
|
||||
|
||||
# extra verification
|
||||
if ($verify) {
|
||||
my $data2 = $LJ::MogileFS->get_file_data($u->mogfs_userpic_key($picid));
|
||||
my $eq = ($data2 && $$data2 eq $data) ? 1 : 0;
|
||||
if ($besteffort && !$eq) {
|
||||
print STDERR "verify_failed userid=$u->{userid} picid=$picid\n";
|
||||
print "\twarning: verify failed; picture not updated\n\n"
|
||||
if $verbose;
|
||||
next;
|
||||
}
|
||||
die "\tERROR: picture NOT stored successfully, content mismatch\n"
|
||||
unless $eq;
|
||||
print "\tverified length = " . length($$data2) . " bytes...\n"
|
||||
if $verbose;
|
||||
}
|
||||
|
||||
# done moving this picture
|
||||
unless ($dryrun) {
|
||||
print "\tupdating database for this picture...\n"
|
||||
if $verbose;
|
||||
$dbcm->do("UPDATE userpic2 SET location = 'mogile' WHERE userid = ? AND picid = ?",
|
||||
undef, $u->{userid}, $picid);
|
||||
}
|
||||
|
||||
# get the paths so the user can verify if they want
|
||||
if ($verbose) {
|
||||
my @paths = $LJ::MogileFS->get_paths($u->mogfs_userpic_key($picid), 1);
|
||||
print "\tverify mogile path: $_\n" foreach @paths;
|
||||
print "\tverify site url: $LJ::SITEROOT/userpic/$picid/$u->{userid}\n";
|
||||
print "\tpicture update complete.\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# a sub to get a cluster handle and set it up for our use
|
||||
sub get_db_handle {
|
||||
my $cid = shift;
|
||||
|
||||
my $dbcm = LJ::get_cluster_master({ raw => 1 }, $cid);
|
||||
unless ($dbcm) {
|
||||
print STDERR "handle_unavailable clusterid=$cid\n";
|
||||
die "ERROR: unable to get raw handle to cluster $cid\n";
|
||||
}
|
||||
eval {
|
||||
$dbcm->do("SET wait_timeout = 28800");
|
||||
die $dbcm->errstr if $dbcm->err;
|
||||
};
|
||||
die "Couldn't set wait_timeout on $cid: $@\n" if $@;
|
||||
$dbcm->{'RaiseError'} = 1;
|
||||
|
||||
return $dbcm;
|
||||
}
|
||||
162
livejournal/bin/upgrading/migrate-userprop.pl
Executable file
@@ -0,0 +1,162 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use lib "$ENV{'LJHOME'}/cgi-bin";
|
||||
require 'ljlib.pl';
|
||||
|
||||
# so output happens quickly
|
||||
$| = 1;
|
||||
|
||||
# make sure we got a parameter
|
||||
my $propname = shift;
|
||||
die "ERROR: no property specified\n" unless $propname;
|
||||
|
||||
# verify it's a valid property
|
||||
my $prop = LJ::get_prop('user', $propname);
|
||||
|
||||
# see if we know how to handle this parameter
|
||||
if ($propname eq 'external_foaf_url' && $prop->{cldversion} == 0) {
|
||||
# this one is simple; we're moving this one to the clusters 1000 users at a time
|
||||
print "Beginning initial data migration...\n";
|
||||
cluster_property($prop);
|
||||
|
||||
# update the property to be indexed
|
||||
print "Updating property data in userproplist...\n";
|
||||
update_property($prop, { indexed => 0, cldversion => 4 });
|
||||
|
||||
# strongly recommend a restart
|
||||
print "\n";
|
||||
print "* " x 38 . "\n";
|
||||
print "WARNING: It is recommended that you restart your web nodes now to cause the\n";
|
||||
print " updated property to start to take effect. Please press enter when\n";
|
||||
print " this is done.\n";
|
||||
print "* " x 38 . "\n";
|
||||
readline STDIN;
|
||||
|
||||
# now let's hope they restarted and let's migrate anybody who is still stuck
|
||||
print "Beginning final data migration...\n";
|
||||
cluster_property($prop);
|
||||
|
||||
# done
|
||||
print "Finished migrating external_foaf_url property.\n";
|
||||
|
||||
} else {
|
||||
# don't know how to handle it
|
||||
die "ERROR: don't know how to handle '$propname' (has it already been handled?)\n";
|
||||
}
|
||||
|
||||
##############################################################################
|
||||
### helper subs
|
||||
|
||||
sub cluster_property {
|
||||
my $prop = shift;
|
||||
|
||||
# some state tracking information
|
||||
my (%dbcms); # ( clusterid => dbcm )
|
||||
my (%to_write); # ( clusterid => [ [ userid, value ], [ userid, value ], ... ]
|
||||
# note: livejournal has only about 7500 external_foaf_urls... those should
|
||||
# be moved in less time than any database handle will time out, so I've made
|
||||
# the decision not to worry about handle timeouts right now. all other sites
|
||||
# are probably no more than this size, so it should be fine for everybody.
|
||||
|
||||
# setup our flushing sub that we'll need later
|
||||
my $flush = sub {
|
||||
my $cid = shift;
|
||||
|
||||
# get the ref from to_write etc
|
||||
my $aref = $to_write{$cid};
|
||||
delete $to_write{$cid};
|
||||
|
||||
# get handle to database if needed
|
||||
my $dbcm = $dbcms{$cid} || ($dbcms{$cid} = LJ::get_cluster_master($cid));
|
||||
|
||||
# notice that we're flushing data
|
||||
print "\tflushing " . scalar(@$aref) . " items to cluster $cid...";
|
||||
|
||||
# now construct SQL
|
||||
my $repstr = join(', ', map { "($_->[0], $prop->{upropid}, " .
|
||||
$dbcm->quote($_->[1]) . ")" } @$aref);
|
||||
$dbcm->do("REPLACE INTO userproplite2 (userid, upropid, value) VALUES $repstr");
|
||||
die "ERROR: database: " . $dbcm->errstr . "\n" if $dbcm->err;
|
||||
|
||||
# done, status update
|
||||
print "flushed\n";
|
||||
};
|
||||
|
||||
# start our main loop
|
||||
while (1) {
|
||||
# data storage for each loop
|
||||
my (%users, %values); # ( userid => user object or value )
|
||||
|
||||
# clear our handles
|
||||
$LJ::DBIRole->flush_cache();
|
||||
|
||||
# get main database handle
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
# select up to 1000 userid:value tuples
|
||||
print "Getting values...";
|
||||
my $vals = $dbh->selectall_arrayref
|
||||
('SELECT userid, value FROM userprop WHERE upropid = ? LIMIT 1000',
|
||||
undef, $prop->{upropid});
|
||||
die "ERROR: database: " . $dbh->errstr . "\n" if $dbh->err;
|
||||
print "got " . scalar(@$vals) . " values.\n";
|
||||
|
||||
# short circuit if we have 0
|
||||
return 1 if scalar @$vals == 0;
|
||||
|
||||
# get the userids to load
|
||||
my @to_load;
|
||||
foreach my $row (@$vals) {
|
||||
my ($userid, $value) = @$row;
|
||||
$values{$userid} = $value;
|
||||
push @to_load, $userid;
|
||||
}
|
||||
|
||||
# now load the users in one big grab
|
||||
print "Loading users...";
|
||||
LJ::load_userids_multiple([ map { $_ => \$users{$_} } @to_load ]);
|
||||
print "loaded.\n";
|
||||
|
||||
# now push data onto the cluster lists
|
||||
while (my ($userid, $value) = each %values) {
|
||||
my $cid = $users{$userid}->{clusterid};
|
||||
|
||||
# clusterid 0 means the user is expunged or somesuch, so we
|
||||
# don't weant to migrate their settings anywhere and should
|
||||
# just delete it.
|
||||
next unless $cid;
|
||||
|
||||
# now push this onto the to_write array
|
||||
$to_write{$cid} ||= [];
|
||||
push @{$to_write{$cid}}, [ $userid, $value ];
|
||||
|
||||
# now, flush this list if it's large (100 or more)
|
||||
$flush->($cid) if scalar @{$to_write{$cid}} >= 100;
|
||||
}
|
||||
|
||||
# now flush everything that's left
|
||||
$flush->($_) foreach keys %to_write;
|
||||
|
||||
# now delete from the global for items that we've written
|
||||
print "Deleting " . scalar(keys %values) . " items from global...";
|
||||
my $instr = join(',', map { $_ + 0 } keys %values);
|
||||
$dbh->do("DELETE FROM userprop WHERE upropid = $prop->{upropid} AND userid IN ($instr)");
|
||||
die "ERROR: database: " . $dbh->errstr . "\n" if $dbh->err;
|
||||
print "deleted.\n";
|
||||
|
||||
# last if we had less than 1000 this time
|
||||
last if scalar @$vals < 1000;
|
||||
}
|
||||
}
|
||||
|
||||
sub update_property {
|
||||
my ($prop, $sets) = @_;
|
||||
die "ERROR: nothing to set\n" unless %$sets;
|
||||
|
||||
# now make the updates they want
|
||||
my $dbh = LJ::get_db_writer();
|
||||
my $updstr = join(', ', map { "$_ = " . $dbh->quote($sets->{$_}) } keys %$sets);
|
||||
$dbh->do("UPDATE userproplist SET $updstr WHERE upropid = $prop->{upropid}");
|
||||
die "ERROR: database: " . $dbh->errstr . "\n" if $dbh->err;
|
||||
}
|
||||
107
livejournal/bin/upgrading/moods.dat
Executable file
@@ -0,0 +1,107 @@
|
||||
MOOD 1 aggravated 2
|
||||
MOOD 2 angry 0
|
||||
MOOD 3 annoyed 2
|
||||
MOOD 4 anxious 46
|
||||
MOOD 5 bored 25
|
||||
MOOD 6 confused 0
|
||||
MOOD 7 crappy 25
|
||||
MOOD 8 cranky 2
|
||||
MOOD 9 depressed 25
|
||||
MOOD 10 discontent 25
|
||||
MOOD 11 energetic 0
|
||||
MOOD 12 enraged 2
|
||||
MOOD 14 exhausted 74
|
||||
MOOD 15 happy 0
|
||||
MOOD 16 high 41
|
||||
MOOD 18 hungry 74
|
||||
MOOD 19 infuriated 2
|
||||
MOOD 20 irate 2
|
||||
MOOD 21 jubilant 15
|
||||
MOOD 22 lonely 25
|
||||
MOOD 23 moody 2
|
||||
MOOD 25 sad 0
|
||||
MOOD 26 satisfied 53
|
||||
MOOD 28 stressed 2
|
||||
MOOD 30 thoughtful 0
|
||||
MOOD 31 tired 14
|
||||
MOOD 32 touched 15
|
||||
MOOD 33 lazy 61
|
||||
MOOD 34 drunk 74
|
||||
MOOD 41 excited 15
|
||||
MOOD 42 relieved 26
|
||||
MOOD 43 hopeful 70
|
||||
MOOD 44 amused 15
|
||||
MOOD 46 scared 0
|
||||
MOOD 47 frustrated 2
|
||||
MOOD 49 sleepy 31
|
||||
MOOD 51 groggy 31
|
||||
MOOD 52 hyper 11
|
||||
MOOD 53 relaxed 15
|
||||
MOOD 54 restless 74
|
||||
MOOD 55 disappointed 25
|
||||
MOOD 56 curious 6
|
||||
MOOD 61 okay 0
|
||||
MOOD 68 calm 53
|
||||
MOOD 70 optimistic 15
|
||||
MOOD 71 pessimistic 38
|
||||
MOOD 74 uncomfortable 25
|
||||
MOOD 79 embarrassed 46
|
||||
MOOD 80 envious 10
|
||||
MOOD 81 sympathetic 25
|
||||
MOOD 82 sick 74
|
||||
MOOD 83 hot 74
|
||||
MOOD 84 cold 74
|
||||
MOOD 85 worried 25
|
||||
MOOD 86 loved 15
|
||||
MOOD 87 awake 0
|
||||
MOOD 88 working 0
|
||||
MOOD 89 productive 88
|
||||
MOOD 90 accomplished 88
|
||||
MOOD 91 busy 88
|
||||
MOOD 93 full 26
|
||||
MOOD 95 grumpy 2
|
||||
MOOD 96 weird 66
|
||||
MOOD 98 ecstatic 15
|
||||
MOOD 101 contemplative 30
|
||||
MOOD 102 nerdy 0
|
||||
MOOD 103 geeky 102
|
||||
MOOD 104 cynical 2
|
||||
MOOD 106 crazy 66
|
||||
MOOD 107 creative 88
|
||||
MOOD 109 pleased 15
|
||||
MOOD 112 irritated 2
|
||||
MOOD 113 blank 78
|
||||
MOOD 114 apathetic 78
|
||||
MOOD 115 dorky 102
|
||||
MOOD 116 impressed 15
|
||||
MOOD 117 naughty 36
|
||||
MOOD 119 dirty 74
|
||||
MOOD 120 giddy 66
|
||||
MOOD 121 surprised 15
|
||||
MOOD 122 shocked 121
|
||||
MOOD 123 rejected 25
|
||||
MOOD 124 numb 25
|
||||
MOOD 125 cheerful 15
|
||||
MOOD 126 good 15
|
||||
MOOD 127 distressed 4
|
||||
MOOD 128 intimidated 46
|
||||
MOOD 130 devious 0
|
||||
MOOD 131 thankful 15
|
||||
MOOD 132 grateful 15
|
||||
MOOD 133 jealous 25
|
||||
MOOD 134 nervous 46
|
||||
MOODTHEME Classic Smileys : The classic little yellow (and other color) smiley faces.
|
||||
2 /img/mood/classic/angry.gif 15 15
|
||||
6 /img/mood/classic/confused.gif 19 17
|
||||
11 /img/mood/classic/energetic.gif 17 17
|
||||
15 /img/mood/classic/smile.gif 15 15
|
||||
25 /img/mood/classic/sad.gif 15 15
|
||||
30 /img/mood/classic/thinking.gif 22 21
|
||||
31 /img/mood/classic/tired.gif 19 17
|
||||
34 /img/mood/classic/drunk.gif 15 15
|
||||
46 /img/mood/classic/shock.gif 15 15
|
||||
61 /img/mood/classic/blah.gif 15 15
|
||||
66 /img/mood/classic/wink.gif 15 15
|
||||
79 /img/mood/classic/blush.gif 15 15
|
||||
82 /img/mood/classic/sick.gif 15 15
|
||||
130 /img/mood/classic/devious.gif 15 15
|
||||
886
livejournal/bin/upgrading/move0cluster.pl
Executable file
@@ -0,0 +1,886 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# Moves a user between clusters.
|
||||
#
|
||||
|
||||
use strict;
|
||||
use Getopt::Long;
|
||||
|
||||
my $opt_del = 0;
|
||||
my $opt_destdel = 0;
|
||||
my $opt_useslow = 0;
|
||||
my $opt_slowalloc = 0;
|
||||
my $opt_verbose = 1;
|
||||
my $opt_movemaster = 0;
|
||||
my $opt_prelocked = 0;
|
||||
my $opt_expungedel = 0;
|
||||
my $opt_ignorebit = 0;
|
||||
exit 1 unless GetOptions('delete' => \$opt_del,
|
||||
'destdelete' => \$opt_destdel,
|
||||
'useslow' => \$opt_useslow, # use slow db role for read
|
||||
'slowalloc' => \$opt_slowalloc, # see note below
|
||||
'verbose=i' => \$opt_verbose,
|
||||
'movemaster|mm' => \$opt_movemaster,
|
||||
'prelocked' => \$opt_prelocked,
|
||||
'expungedel' => \$opt_expungedel,
|
||||
'ignorebit' => \$opt_ignorebit,
|
||||
);
|
||||
my $optv = $opt_verbose;
|
||||
|
||||
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
|
||||
require "$ENV{'LJHOME'}/cgi-bin/ljcmdbuffer.pl";
|
||||
|
||||
my $dbh = LJ::get_dbh({raw=>1}, "master");
|
||||
die "No master db available.\n" unless $dbh;
|
||||
$dbh->do("SET wait_timeout=28800");
|
||||
|
||||
my $dbr = $dbh;
|
||||
if ($opt_useslow) {
|
||||
$dbr = LJ::get_dbh({raw=>1}, "slow");
|
||||
unless ($dbr) { die "Can't get slow db from which to read.\n"; }
|
||||
}
|
||||
|
||||
my $user = LJ::canonical_username(shift @ARGV);
|
||||
my $dclust = shift @ARGV;
|
||||
|
||||
# tables which are dumbly copied by sucking all into memory first.
|
||||
# use smarter mover code for anything that shouldn't all go into memory.
|
||||
# also, to use this you have to define the primary keys below
|
||||
my @manual_move = qw(loginstall ratelog sessions userproplite2
|
||||
sessions_data userbio userpicblob2 userpropblob
|
||||
s1usercache modlog modblob counter
|
||||
s1style s1overrides links userblob clustertrack2);
|
||||
sub usage {
|
||||
die "Usage:\n movecluster.pl <user> <destination cluster #>\n";
|
||||
}
|
||||
|
||||
usage() unless defined $user;
|
||||
usage() unless defined $dclust;
|
||||
|
||||
die "Failed to get move lock.\n"
|
||||
unless ($dbh->selectrow_array("SELECT GET_LOCK('moveucluster-$user', 10)"));
|
||||
|
||||
my $u = $dbh->selectrow_hashref("SELECT * FROM user WHERE user=?", undef, $user);
|
||||
die "Non-existent user $user.\n" unless $u;
|
||||
|
||||
die "Can't move back to legacy cluster 0\n" unless $dclust;
|
||||
|
||||
my $dbch = LJ::get_cluster_master({raw=>1}, $dclust);
|
||||
|
||||
die "Undefined or down cluster \#$dclust\n" unless $dbch;
|
||||
$dbch->do("SET wait_timeout=28800");
|
||||
|
||||
my $separate_cluster = LJ::use_diff_db("master", "cluster$dclust");
|
||||
|
||||
$dbh->{'RaiseError'} = 1;
|
||||
$dbch->{'RaiseError'} = 1;
|
||||
|
||||
my $sclust = $u->{'clusterid'};
|
||||
|
||||
if ($sclust == $dclust) {
|
||||
die "User '$user' is already on cluster $dclust\n";
|
||||
}
|
||||
|
||||
if ($sclust) {
|
||||
verify_movable_tables();
|
||||
}
|
||||
|
||||
# original cluster db handle.
|
||||
my $dbo;
|
||||
if ($sclust) {
|
||||
$dbo = $opt_movemaster ?
|
||||
LJ::get_dbh({raw=>1}, "cluster$u->{clusterid}movemaster") :
|
||||
LJ::get_cluster_master({raw=>1}, $u);
|
||||
die "Can't get source cluster handle.\n" unless $dbo;
|
||||
$dbo->{'RaiseError'} = 1;
|
||||
$dbo->do("SET wait_timeout=28800");
|
||||
}
|
||||
|
||||
my $userid = $u->{'userid'};
|
||||
|
||||
# find readonly cap class, complain if not found
|
||||
my $readonly_bit = undef;
|
||||
foreach (keys %LJ::CAP) {
|
||||
if ($LJ::CAP{$_}->{'_name'} eq "_moveinprogress" &&
|
||||
$LJ::CAP{$_}->{'readonly'} == 1) {
|
||||
$readonly_bit = $_;
|
||||
last;
|
||||
}
|
||||
}
|
||||
unless (defined $readonly_bit) {
|
||||
die "Won't move user without %LJ::CAP capability class named '_moveinprogress' with readonly => 1\n";
|
||||
}
|
||||
|
||||
# make sure a move isn't already in progress
|
||||
if ($opt_prelocked) {
|
||||
unless (($u->{'caps'}+0) & (1 << $readonly_bit)) {
|
||||
die "User '$user' should have been prelocked.\n";
|
||||
}
|
||||
} else {
|
||||
if (($u->{'caps'}+0) & (1 << $readonly_bit)) {
|
||||
die "User '$user' is already in the process of being moved? (cap bit $readonly_bit set)\n"
|
||||
unless $opt_ignorebit;
|
||||
}
|
||||
}
|
||||
|
||||
if ($opt_expungedel && $u->{'statusvis'} eq "D" &&
|
||||
LJ::mysqldate_to_time($u->{'statusvisdate'}) < time() - 86400*31) {
|
||||
|
||||
print "Expunging user '$u->{'user'}'\n";
|
||||
$dbh->do("INSERT INTO clustermove (userid, sclust, dclust, timestart, timedone) ".
|
||||
"VALUES (?,?,?,UNIX_TIMESTAMP(),UNIX_TIMESTAMP())", undef,
|
||||
$userid, $sclust, 0);
|
||||
LJ::update_user($userid, { clusterid => 0,
|
||||
statusvis => 'X',
|
||||
raw => "caps=caps&~(1<<$readonly_bit), statusvisdate=NOW()" });
|
||||
exit 0;
|
||||
}
|
||||
|
||||
print "Moving '$u->{'user'}' from cluster $sclust to $dclust\n" if $optv >= 1;
|
||||
|
||||
# mark that we're starting the move
|
||||
$dbh->do("INSERT INTO clustermove (userid, sclust, dclust, timestart) ".
|
||||
"VALUES (?,?,?,UNIX_TIMESTAMP())", undef, $userid, $sclust, $dclust);
|
||||
my $cmid = $dbh->{'mysql_insertid'};
|
||||
|
||||
# set readonly cap bit on user
|
||||
LJ::update_user($userid, { raw => "caps=caps|(1<<$readonly_bit)" })
|
||||
unless $opt_prelocked;
|
||||
$dbh->do("SELECT RELEASE_LOCK('moveucluster-$user')");
|
||||
|
||||
unless ($opt_prelocked) {
|
||||
# wait a bit for writes to stop if journal is somewhat active (last week update)
|
||||
my $secidle = $dbh->selectrow_array("SELECT UNIX_TIMESTAMP()-UNIX_TIMESTAMP(timeupdate) ".
|
||||
"FROM userusage WHERE userid=$userid");
|
||||
if ($secidle) {
|
||||
sleep(2) unless $secidle > 86400*7;
|
||||
sleep(1) unless $secidle > 86400;
|
||||
}
|
||||
}
|
||||
|
||||
# make sure slow is caught up:
|
||||
if ($opt_useslow)
|
||||
{
|
||||
my $ms = $dbh->selectrow_hashref("SHOW MASTER STATUS");
|
||||
my $loop = 1;
|
||||
while ($loop) {
|
||||
my $ss = $dbr->selectrow_hashref("SHOW SLAVE STATUS");
|
||||
$loop = 0;
|
||||
unless ($ss->{'Log_File'} gt $ms->{'File'} ||
|
||||
($ss->{'Log_File'} eq $ms->{'File'} && $ss->{'Pos'} >= $ms->{'Position'}))
|
||||
{
|
||||
$loop = 1;
|
||||
print "Waiting for slave ($ss->{'Pos'} < $ms->{'Position'})\n";
|
||||
sleep 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $last = time();
|
||||
my $stmsg = sub {
|
||||
my $msg = shift;
|
||||
my $now = time();
|
||||
return if ($now < $last + 1);
|
||||
$last = $now;
|
||||
print $msg;
|
||||
};
|
||||
|
||||
my %bufcols = (); # db|table -> scalar "(foo, anothercol, lastcol)" or undef or ""
|
||||
my %bufrows = (); # db|table -> [ []+ ]
|
||||
my %bufdbmap = (); # scalar(DBI hashref) -> DBI hashref
|
||||
|
||||
my $flush_buffer = sub {
|
||||
my $dbandtable = shift;
|
||||
my ($db, $table) = split(/\|/, $dbandtable);
|
||||
$db = $bufdbmap{$db};
|
||||
return unless exists $bufcols{$dbandtable};
|
||||
my $sql = "REPLACE INTO $table $bufcols{$dbandtable} VALUES ";
|
||||
$sql .= join(", ",
|
||||
map { my $r = $_;
|
||||
"(" . join(", ",
|
||||
map { $db->quote($_) } @$r) . ")" }
|
||||
@{$bufrows{$dbandtable}});
|
||||
$db->do($sql);
|
||||
delete $bufrows{$dbandtable};
|
||||
delete $bufcols{$dbandtable};
|
||||
};
|
||||
|
||||
my $flush_all = sub {
|
||||
foreach (keys %bufcols) {
|
||||
$flush_buffer->($_);
|
||||
}
|
||||
};
|
||||
|
||||
my $replace_into = sub {
|
||||
my $db = ref $_[0] ? shift : $dbch; # optional first arg
|
||||
my ($table, $cols, $max, @vals) = @_;
|
||||
my $dbandtable = scalar($db) . "|$table";
|
||||
$bufdbmap{$db} = $db;
|
||||
if (exists $bufcols{$dbandtable} && $bufcols{$dbandtable} ne $cols) {
|
||||
$flush_buffer->($dbandtable);
|
||||
}
|
||||
$bufcols{$dbandtable} = $cols;
|
||||
push @{$bufrows{$dbandtable}}, [ @vals ];
|
||||
|
||||
if (scalar @{$bufrows{$dbandtable}} > $max) {
|
||||
$flush_buffer->($dbandtable);
|
||||
}
|
||||
};
|
||||
|
||||
# assume never tried to move this user before. however, if reported crap
|
||||
# in the oldids table, we'll revert to slow alloc_id functionality,
|
||||
# where we do a round-trip to $dbh for everything and see if every id
|
||||
# has been remapped already. otherwise we do it in perl and batch
|
||||
# updates to the oldids table, which is the common/fast case.
|
||||
my $first_move = ! $opt_slowalloc;
|
||||
|
||||
my %alloc_data;
|
||||
my %alloc_arealast;
|
||||
my $alloc_id = sub {
|
||||
my ($area, $orig) = @_;
|
||||
|
||||
# fast version
|
||||
if ($first_move) {
|
||||
my $id = $alloc_data{$area}->{$orig} = ++$alloc_arealast{$area};
|
||||
$replace_into->($dbh, "oldids", "(area, oldid, userid, newid)", 250,
|
||||
$area, $orig, $userid, $id);
|
||||
return $id;
|
||||
}
|
||||
|
||||
# slow version
|
||||
$dbh->{'RaiseError'} = 0;
|
||||
$dbh->do("INSERT INTO oldids (area, oldid, userid, newid) ".
|
||||
"VALUES ('$area', $orig, $userid, NULL)");
|
||||
my $id;
|
||||
if ($dbh->err) {
|
||||
$id = $dbh->selectrow_array("SELECT newid FROM oldids WHERE area='$area' AND oldid=$orig");
|
||||
} else {
|
||||
$id = $dbh->{'mysql_insertid'};
|
||||
}
|
||||
$dbh->{'RaiseError'} = 1;
|
||||
$alloc_data{$area}->{$orig} = $id;
|
||||
return $id;
|
||||
};
|
||||
|
||||
my $bufread;
|
||||
|
||||
if ($sclust == 0)
|
||||
{
|
||||
# do bio stuff
|
||||
{
|
||||
my $bio = $dbr->selectrow_array("SELECT bio FROM userbio WHERE userid=$userid");
|
||||
my $bytes = length($bio);
|
||||
$dbch->do("REPLACE INTO dudata (userid, area, areaid, bytes) VALUES ($userid, 'B', 0, $bytes)");
|
||||
if ($separate_cluster) {
|
||||
$bio = $dbh->quote($bio);
|
||||
$dbch->do("REPLACE INTO userbio (userid, bio) VALUES ($userid, $bio)");
|
||||
}
|
||||
}
|
||||
|
||||
my @itemids = reverse @{$dbr->selectcol_arrayref("SELECT itemid FROM log ".
|
||||
"WHERE ownerid=$u->{'userid'} ".
|
||||
"ORDER BY ownerid, rlogtime")};
|
||||
|
||||
$bufread = make_buffer_reader("itemid", \@itemids);
|
||||
|
||||
my $todo = @itemids;
|
||||
my $done = 0;
|
||||
my $stime = time();
|
||||
print "Total: $todo\n";
|
||||
|
||||
# moving time, journal item at a time, and everything recursively under it
|
||||
foreach my $itemid (@itemids) {
|
||||
movefrom0_logitem($itemid);
|
||||
$done++;
|
||||
my $percent = $done/$todo;
|
||||
my $elapsed = time() - $stime;
|
||||
my $totaltime = $elapsed * (1 / $percent);
|
||||
my $timeremain = int($totaltime - $elapsed);
|
||||
$stmsg->(sprintf "$user: copy $done/$todo (%.2f%%) +${elapsed}s -${timeremain}s\n", 100*$percent);
|
||||
}
|
||||
|
||||
$flush_all->();
|
||||
|
||||
# update their memories. in particular, any memories of their own
|
||||
# posts need to to be updated from the (0, globalid) to
|
||||
# (journalid, jitemid) format, to make the memory filter feature
|
||||
# work. (it checks the first 4 bytes only, not joining the
|
||||
# globalid on the clustered log table)
|
||||
print "Fixing memories.\n";
|
||||
my @fix = @{$dbh->selectall_arrayref("SELECT memid, jitemid FROM memorable WHERE ".
|
||||
"userid=$u->{'userid'} AND journalid=0")};
|
||||
foreach my $f (@fix) {
|
||||
my ($memid, $newid) = ($f->[0], $alloc_data{'L'}->{$f->[1]});
|
||||
next unless $newid;
|
||||
my ($newid2, $anum) = $dbch->selectrow_array("SELECT jitemid, anum FROM log2 ".
|
||||
"WHERE journalid=$u->{'userid'} AND ".
|
||||
"jitemid=$newid");
|
||||
if ($newid2 == $newid) {
|
||||
my $ditemid = $newid * 256 + $anum;
|
||||
print "UPDATE $memid TO $ditemid\n";
|
||||
$dbh->do("UPDATE memorable SET journalid=$u->{'userid'}, jitemid=$ditemid ".
|
||||
"WHERE memid=$memid");
|
||||
}
|
||||
}
|
||||
|
||||
# fix polls
|
||||
print "Fixing polls.\n";
|
||||
@fix = @{$dbh->selectall_arrayref("SELECT pollid, itemid FROM poll ".
|
||||
"WHERE journalid=$u->{'userid'}")};
|
||||
foreach my $f (@fix) {
|
||||
my ($pollid, $newid) = ($f->[0], $alloc_data{'L'}->{$f->[1]});
|
||||
next unless $newid;
|
||||
my ($newid2, $anum) = $dbch->selectrow_array("SELECT jitemid, anum FROM log2 ".
|
||||
"WHERE journalid=$u->{'userid'} AND ".
|
||||
"jitemid=$newid");
|
||||
if ($newid2 == $newid) {
|
||||
my $ditemid = $newid * 256 + $anum;
|
||||
print "UPDATE $pollid TO $ditemid\n";
|
||||
$dbh->do("UPDATE poll SET itemid=$ditemid WHERE pollid=$pollid");
|
||||
}
|
||||
}
|
||||
|
||||
# move userpics
|
||||
print "Copying over userpics.\n";
|
||||
my @pics = @{$dbr->selectcol_arrayref("SELECT picid FROM userpic WHERE ".
|
||||
"userid=$u->{'userid'}")};
|
||||
foreach my $picid (@pics) {
|
||||
print " picid\#$picid...\n";
|
||||
my $imagedata = $dbr->selectrow_array("SELECT imagedata FROM userpicblob ".
|
||||
"WHERE picid=$picid");
|
||||
$imagedata = $dbh->quote($imagedata);
|
||||
$dbch->do("REPLACE INTO userpicblob2 (userid, picid, imagedata) VALUES ".
|
||||
"($u->{'userid'}, $picid, $imagedata)");
|
||||
}
|
||||
|
||||
$dbh->do("UPDATE userusage SET lastitemid=0 WHERE userid=$userid");
|
||||
|
||||
my $dversion = 2;
|
||||
|
||||
# if everything's good (nothing's died yet), then delete all from source
|
||||
if ($opt_del)
|
||||
{
|
||||
# before we start deleting, record they've moved servers.
|
||||
LJ::update_user($userid, { dversion => $dversion, clusterid => $dclust });
|
||||
|
||||
$done = 0;
|
||||
$stime = time();
|
||||
foreach my $itemid (@itemids) {
|
||||
deletefrom0_logitem($itemid);
|
||||
$done++;
|
||||
my $percent = $done/$todo;
|
||||
my $elapsed = time() - $stime;
|
||||
my $totaltime = $elapsed * (1 / $percent);
|
||||
my $timeremain = int($totaltime - $elapsed);
|
||||
$stmsg->(sprintf "$user: delete $done/$todo (%.2f%%) +${elapsed}s -${timeremain}s\n", 100*$percent);
|
||||
}
|
||||
|
||||
# delete bio from source, if necessary
|
||||
if ($separate_cluster) {
|
||||
$dbh->do("DELETE FROM userbio WHERE userid=$userid");
|
||||
}
|
||||
|
||||
# delete source userpics
|
||||
print "Deleting cluster0 userpics...\n";
|
||||
foreach my $picid (@pics) {
|
||||
print " picid\#$picid...\n";
|
||||
$dbh->do("DELETE FROM userpicblob WHERE picid=$picid");
|
||||
}
|
||||
|
||||
# unset read-only bit (marks the move is complete, also, and not aborted mid-delete)
|
||||
LJ::update_user($userid, { raw => "caps=caps&~(1<<$readonly_bit)" });
|
||||
$dbh->do("UPDATE clustermove SET sdeleted='1', timedone=UNIX_TIMESTAMP() ".
|
||||
"WHERE cmid=?", undef, $cmid);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
# unset readonly and move to new cluster in one update
|
||||
LJ::update_user($userid, { dversion => $dversion, clusterid => $dclust,
|
||||
raw => "caps=caps&~(1<<$readonly_bit)" });
|
||||
$dbh->do("UPDATE clustermove SET sdeleted='0', timedone=UNIX_TIMESTAMP() ".
|
||||
"WHERE cmid=?", undef, $cmid);
|
||||
}
|
||||
exit 0;
|
||||
}
|
||||
elsif ($sclust > 0)
|
||||
{
|
||||
print "Moving away from cluster $sclust\n" if $optv;
|
||||
|
||||
while (my $cmd = $dbo->selectrow_array("SELECT cmd FROM cmdbuffer WHERE journalid=$userid")) {
|
||||
my $dbcm = LJ::get_cluster_master($sclust);
|
||||
print "Flushing cmdbuffer for cmd: $cmd\n" if $optv > 1;
|
||||
LJ::Cmdbuffer::flush($dbh, $dbcm, $cmd, $userid);
|
||||
}
|
||||
|
||||
my $pri_key = {
|
||||
# flush this first:
|
||||
'cmdbuffer' => 'journalid',
|
||||
|
||||
# this is populated as we do log/talk
|
||||
'dudata' => 'userid',
|
||||
|
||||
# manual
|
||||
'loginstall' => 'userid',
|
||||
'ratelog' => 'userid',
|
||||
'sessions' => 'userid',
|
||||
'sessions_data' => 'userid',
|
||||
'userbio' => 'userid',
|
||||
'userpicblob2' => 'userid',
|
||||
'userproplite2' => 'userid',
|
||||
's1usercache' => 'userid',
|
||||
'modlog' => 'journalid',
|
||||
'modblob' => 'journalid',
|
||||
'counter' => 'journalid',
|
||||
'userblob' => 'journalid',
|
||||
'userpropblob' => 'userid',
|
||||
'clustertrack2' => 'userid',
|
||||
|
||||
# log
|
||||
'log2' => 'journalid',
|
||||
'logsec2' => 'journalid',
|
||||
'logprop2' => 'journalid',
|
||||
'logtext2' => 'journalid',
|
||||
|
||||
# talk
|
||||
'talk2' => 'journalid',
|
||||
'talkprop2' => 'journalid',
|
||||
'talktext2' => 'journalid',
|
||||
|
||||
# no primary key... move up by posttime
|
||||
'talkleft' => 'userid',
|
||||
|
||||
# s1 styles
|
||||
's1style' => 'userid',
|
||||
's1overrides' => 'userid',
|
||||
|
||||
# link lists
|
||||
'links' => 'journalid',
|
||||
};
|
||||
|
||||
# ask the local mods if they have any tables to move
|
||||
my @local_tables;
|
||||
my $local_tables = LJ::run_hook("moveucluster_local_tables");
|
||||
if ($local_tables) {
|
||||
while (my ($tab, $key) = each %$local_tables) {
|
||||
push @local_tables, $tab;
|
||||
$pri_key->{$tab} = $key;
|
||||
}
|
||||
}
|
||||
|
||||
my @existing_data;
|
||||
print "Checking for existing data on target cluster...\n" if $optv > 1;
|
||||
foreach my $table (sort keys %$pri_key) {
|
||||
my $pri = $pri_key->{$table};
|
||||
my $is_there = $dbch->selectrow_array("SELECT $pri FROM $table WHERE $pri=$userid LIMIT 1");
|
||||
next unless $is_there;
|
||||
if ($opt_destdel) {
|
||||
while ($dbch->do("DELETE FROM $table WHERE $pri=$userid LIMIT 500") > 0) {
|
||||
print " deleted from $table\n" if $optv;
|
||||
}
|
||||
} else {
|
||||
push @existing_data, $table;
|
||||
}
|
||||
}
|
||||
if (@existing_data) {
|
||||
die " Existing data in tables: @existing_data\n";
|
||||
}
|
||||
|
||||
my %pendreplace; # "logprop2:(col,col)" => { 'values' => [ [a, b, c], [d, e, f] ],
|
||||
# 'bytes' => 3043, 'recs' => 35 }
|
||||
my $flush = sub {
|
||||
my $dest = shift;
|
||||
return 1 unless $pendreplace{$dest};
|
||||
my ($table, $cols) = split(/:/, $dest);
|
||||
my $vals;
|
||||
foreach my $v (@{$pendreplace{$dest}->{'values'}}) {
|
||||
$vals .= "," if $vals;
|
||||
$vals .= "(" . join(',', map { $dbch->quote($_) } @$v) . ")";
|
||||
}
|
||||
print " flushing write to $table\n" if $optv > 1;
|
||||
$dbch->do("REPLACE INTO $table $cols VALUES $vals");
|
||||
die $dbh->errstr if $dbch->err;
|
||||
delete $pendreplace{$dest};
|
||||
return 1;
|
||||
};
|
||||
|
||||
my $write = sub {
|
||||
my $dest = shift;
|
||||
my @values = @_;
|
||||
my $new_bytes = 0; foreach (@values) { $new_bytes += length($_); }
|
||||
push @{$pendreplace{$dest}->{'values'}}, \@values;
|
||||
$pendreplace{$dest}->{'bytes'} += $new_bytes;
|
||||
$pendreplace{$dest}->{'recs'}++;
|
||||
if ($pendreplace{$dest}->{'bytes'} > 1024*500 ||
|
||||
$pendreplace{$dest}->{'recs'} > 500) { $flush->($dest); }
|
||||
};
|
||||
|
||||
my @styleids = ();
|
||||
|
||||
# manual moving (dumb copies)
|
||||
foreach my $table (@manual_move, @local_tables) {
|
||||
next if ($table eq "modlog" || $table eq "modblob") && $u->{journaltype} eq "P";
|
||||
print " moving $table ...\n" if $optv > 1;
|
||||
my @cols;
|
||||
my $sth = $dbo->prepare("DESCRIBE $table");
|
||||
$sth->execute;
|
||||
my $styleidcolnum = -1;
|
||||
my $colnum = 0;
|
||||
while ($_ = $sth->fetchrow_hashref) {
|
||||
push @cols, $_->{'Field'};
|
||||
$styleidcolnum = $colnum if $_->{'Field'} eq 'styleid';
|
||||
$colnum++;
|
||||
}
|
||||
my $cols = join(',', @cols);
|
||||
my $dest = "$table:($cols)";
|
||||
my $pri = $pri_key->{$table};
|
||||
$sth = $dbo->prepare("SELECT $cols FROM $table WHERE $pri=$userid");
|
||||
$sth->execute;
|
||||
while (my @vals = $sth->fetchrow_array) {
|
||||
$write->($dest, @vals);
|
||||
if ($styleidcolnum > -1 && $table eq 's1style') {
|
||||
push @styleids, $vals[$styleidcolnum];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# size of bio
|
||||
my $bio_size = $dbch->selectrow_array("SELECT LENGTH(bio) FROM userbio WHERE userid=$userid");
|
||||
$write->("dudata:(userid,area,areaid,bytes)", $userid, 'B', 0, $bio_size) if $bio_size;
|
||||
|
||||
# journal items
|
||||
{
|
||||
my $maxjitem = $dbo->selectrow_array("SELECT MAX(jitemid) FROM log2 WHERE journalid=$userid");
|
||||
my $load_amt = 1000;
|
||||
my ($lo, $hi) = (1, $load_amt);
|
||||
my $sth;
|
||||
my $cols = "security,allowmask,journalid,jitemid,posterid,eventtime,logtime,compressed,anum,replycount,year,month,day,rlogtime,revttime"; # order matters. see indexes below
|
||||
while ($lo <= $maxjitem) {
|
||||
print " log ($lo - $hi, of $maxjitem)\n" if $optv > 1;
|
||||
|
||||
# log2/logsec2
|
||||
$sth = $dbo->prepare("SELECT $cols FROM log2 ".
|
||||
"WHERE journalid=$userid AND jitemid BETWEEN $lo AND $hi");
|
||||
$sth->execute;
|
||||
while (my @vals = $sth->fetchrow_array) {
|
||||
$write->("log2:($cols)", @vals);
|
||||
|
||||
if ($vals[0] eq "usemask") {
|
||||
$write->("logsec2:(journalid,jitemid,allowmask)",
|
||||
$userid, $vals[3], $vals[1]);
|
||||
}
|
||||
}
|
||||
|
||||
# logprop2
|
||||
$sth = $dbo->prepare("SELECT journalid,jitemid,propid,value ".
|
||||
"FROM logprop2 WHERE journalid=$userid AND jitemid BETWEEN $lo AND $hi");
|
||||
$sth->execute;
|
||||
while (my @vals = $sth->fetchrow_array) {
|
||||
$write->("logprop2:(journalid,jitemid,propid,value)", @vals);
|
||||
}
|
||||
|
||||
# logtext2
|
||||
$sth = $dbo->prepare("SELECT journalid,jitemid,subject,event ".
|
||||
"FROM logtext2 WHERE journalid=$userid AND jitemid BETWEEN $lo AND $hi");
|
||||
$sth->execute;
|
||||
while (my @vals = $sth->fetchrow_array) {
|
||||
my $size = length($vals[2]) + length($vals[3]);
|
||||
LJ::text_compress(\$vals[3]);
|
||||
$write->("logtext2:(journalid,jitemid,subject,event)", @vals);
|
||||
$write->("dudata:(userid,area,areaid,bytes)", $userid, 'L', $vals[1], $size);
|
||||
}
|
||||
|
||||
$hi += $load_amt; $lo += $load_amt;
|
||||
}
|
||||
}
|
||||
|
||||
# comments
|
||||
{
|
||||
my $maxtalkid = $dbo->selectrow_array("SELECT MAX(jtalkid) FROM talk2 WHERE journalid=$userid");
|
||||
my $load_amt = 1000;
|
||||
my ($lo, $hi) = (1, $load_amt);
|
||||
my $sth;
|
||||
|
||||
my %cols = ('talk2' => 'journalid,jtalkid,nodetype,nodeid,parenttalkid,posterid,datepost,state',
|
||||
'talkprop2' => 'journalid,jtalkid,tpropid,value',
|
||||
'talktext2' => 'journalid,jtalkid,subject,body');
|
||||
while ($lo <= $maxtalkid) {
|
||||
print " talk ($lo - $hi, of $maxtalkid)\n" if $optv > 1;
|
||||
foreach my $table (keys %cols) {
|
||||
$sth = $dbo->prepare("SELECT $cols{$table} FROM $table ".
|
||||
"WHERE journalid=$userid AND jtalkid BETWEEN $lo AND $hi");
|
||||
$sth->execute;
|
||||
while (my @vals = $sth->fetchrow_array) {
|
||||
LJ::text_compress(\$vals[3]) if $table eq "talktext2";
|
||||
$write->("$table:($cols{$table})", @vals);
|
||||
}
|
||||
}
|
||||
|
||||
$hi += $load_amt; $lo += $load_amt;
|
||||
}
|
||||
}
|
||||
|
||||
# talkleft table.
|
||||
{
|
||||
# no primary key... delete all of target first.
|
||||
while ($dbch->do("DELETE FROM talkleft WHERE userid=$userid LIMIT 1000") > 0) {
|
||||
print " deleted from talkleft\n" if $optv > 1;
|
||||
}
|
||||
|
||||
my $last_max = 0;
|
||||
my $cols = "userid,posttime,journalid,nodetype,nodeid,jtalkid,publicitem";
|
||||
while (defined $last_max) {
|
||||
print " talkleft: $last_max\n" if $optv > 1;
|
||||
my $sth = $dbo->prepare("SELECT $cols FROM talkleft WHERE userid=$userid ".
|
||||
"AND posttime > $last_max ORDER BY posttime LIMIT 1000");
|
||||
$sth->execute;
|
||||
undef $last_max;
|
||||
while (my @vals = $sth->fetchrow_array) {
|
||||
$write->("talkleft:($cols)", @vals);
|
||||
$last_max = $vals[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# flush remaining items
|
||||
foreach (keys %pendreplace) { $flush->($_); }
|
||||
|
||||
# unset readonly and move to new cluster in one update
|
||||
LJ::update_user($userid, { clusterid => $dclust, raw => "caps=caps&~(1<<$readonly_bit)" });
|
||||
print "Moved.\n" if $optv;
|
||||
|
||||
# delete from source cluster
|
||||
if ($opt_del) {
|
||||
print "Deleting from source cluster...\n" if $optv;
|
||||
foreach my $table (sort keys %$pri_key) {
|
||||
my $pri = $pri_key->{$table};
|
||||
while ($dbo->do("DELETE FROM $table WHERE $pri=$userid LIMIT 500") > 0) {
|
||||
print " deleted from $table\n" if $optv;
|
||||
}
|
||||
}
|
||||
|
||||
# s1stylecache table
|
||||
if (@styleids) {
|
||||
my $styleids_in = join(",", map { $dbo->quote($_) } @styleids);
|
||||
if ($dbo->do("DELETE FROM s1stylecache WHERE styleid IN ($styleids_in)") > 0) {
|
||||
print " deleted from s1stylecache\n" if $optv;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# at minimum, we delete the clustertrack2 row so it doesn't get
|
||||
# included in a future ljumover.pl query from that cluster.
|
||||
$dbo->do("DELETE FROM clustertrack2 WHERE userid=$userid");
|
||||
}
|
||||
|
||||
$dbh->do("UPDATE clustermove SET sdeleted=?, timedone=UNIX_TIMESTAMP() ".
|
||||
"WHERE cmid=?", undef, $opt_del ? 1 : 0, $cmid);
|
||||
exit 0;
|
||||
}
|
||||
|
||||
sub deletefrom0_logitem
|
||||
{
|
||||
my $itemid = shift;
|
||||
|
||||
# delete all the comments
|
||||
my $talkids = $dbh->selectcol_arrayref("SELECT talkid FROM talk ".
|
||||
"WHERE nodetype='L' AND nodeid=$itemid");
|
||||
|
||||
my $talkidin = join(",", @$talkids);
|
||||
if ($talkidin) {
|
||||
foreach my $table (qw(talktext talkprop talk)) {
|
||||
$dbh->do("DELETE FROM $table WHERE talkid IN ($talkidin)");
|
||||
}
|
||||
}
|
||||
|
||||
$dbh->do("DELETE FROM logsec WHERE ownerid=$userid AND itemid=$itemid");
|
||||
foreach my $table (qw(logprop logtext log)) {
|
||||
$dbh->do("DELETE FROM $table WHERE itemid=$itemid");
|
||||
}
|
||||
}
|
||||
|
||||
sub movefrom0_logitem
|
||||
{
|
||||
my $itemid = shift;
|
||||
|
||||
my $item = $bufread->(100, "SELECT * FROM log", $itemid);
|
||||
my $itemtext = $bufread->(50, "SELECT itemid, subject, event FROM logtext", $itemid);
|
||||
return 1 unless $item && $itemtext; # however that could happen.
|
||||
|
||||
# we need to allocate a new jitemid (journal-specific itemid) for this item now.
|
||||
my $jitemid = $alloc_id->('L', $itemid);
|
||||
unless ($jitemid) {
|
||||
die "ERROR: could not allocate a new jitemid\n";
|
||||
}
|
||||
$dbh->{'RaiseError'} = 1;
|
||||
$item->{'jitemid'} = $jitemid;
|
||||
$item->{'anum'} = int(rand(256));
|
||||
|
||||
# copy item over:
|
||||
$replace_into->("log2", "(journalid, jitemid, posterid, eventtime, logtime, ".
|
||||
"compressed, security, allowmask, replycount, year, month, day, ".
|
||||
"rlogtime, revttime, anum)",
|
||||
50, map { $item->{$_} } qw(ownerid jitemid posterid eventtime
|
||||
logtime compressed security allowmask replycount
|
||||
year month day rlogtime revttime anum));
|
||||
|
||||
$replace_into->("logtext2", "(journalid, jitemid, subject, event)", 10,
|
||||
$userid, $jitemid, map { $itemtext->{$_} } qw(subject event));
|
||||
|
||||
# add disk usage info! (this wasn't in cluster0 anywhere)
|
||||
my $bytes = length($itemtext->{'event'}) + length($itemtext->{'subject'});
|
||||
$replace_into->("dudata", "(userid, area, areaid, bytes)", 50, $userid, 'L', $jitemid, $bytes);
|
||||
|
||||
# add the logsec item, if necessary:
|
||||
if ($item->{'security'} ne "public") {
|
||||
$replace_into->("logsec2", "(journalid, jitemid, allowmask)", 50,
|
||||
map { $item->{$_} } qw(ownerid jitemid allowmask));
|
||||
}
|
||||
|
||||
# copy its logprop over:
|
||||
while (my $lp = $bufread->(50, "SELECT itemid, propid, value FROM logprop", $itemid)) {
|
||||
next unless $lp->{'value'};
|
||||
$replace_into->("logprop2", "(journalid, jitemid, propid, value)", 50,
|
||||
$userid, $jitemid, $lp->{'propid'}, $lp->{'value'});
|
||||
}
|
||||
|
||||
# copy its talk shit over:
|
||||
my %newtalkids = (0 => 0); # 0 maps back to 0 still
|
||||
my $talkids = $dbr->selectcol_arrayref("SELECT talkid FROM talk ".
|
||||
"WHERE nodetype='L' AND nodeid=$itemid");
|
||||
my @talkids = sort { $a <=> $b } @$talkids;
|
||||
my $treader = make_buffer_reader("talkid", \@talkids);
|
||||
foreach my $t (@talkids) {
|
||||
movefrom0_talkitem($t, $jitemid, \%newtalkids, $item, $treader);
|
||||
}
|
||||
}
|
||||
|
||||
sub movefrom0_talkitem
|
||||
{
|
||||
my $talkid = shift;
|
||||
my $jitemid = shift;
|
||||
my $newtalkids = shift;
|
||||
my $logitem = shift;
|
||||
my $treader = shift;
|
||||
|
||||
my $item = $treader->(100, "SELECT *, UNIX_TIMESTAMP(datepost) AS 'datepostunix' FROM talk", $talkid);
|
||||
my $itemtext = $treader->(50, "SELECT talkid, subject, body FROM talktext", $talkid);
|
||||
return 1 unless $item && $itemtext; # however that could happen.
|
||||
|
||||
# abort if this is a stranded entry. (shouldn't happen, anyway. even if it does, it's
|
||||
# not like we're losing data: the UI (talkread.bml) won't show it anyway)
|
||||
return unless defined $newtalkids->{$item->{'parenttalkid'}};
|
||||
|
||||
# we need to allocate a new jitemid (journal-specific itemid) for this item now.
|
||||
my $jtalkid = $alloc_id->('T', $talkid);
|
||||
unless ($jtalkid) {
|
||||
die "ERROR: could not allocate a new jtalkid\n";
|
||||
}
|
||||
$newtalkids->{$talkid} = $jtalkid;
|
||||
$dbh->{'RaiseError'} = 1;
|
||||
|
||||
# copy item over:
|
||||
$replace_into->("talk2", "(journalid, jtalkid, parenttalkid, nodeid, ".
|
||||
"nodetype, posterid, datepost, state)", 50,
|
||||
$userid, $jtalkid, $newtalkids->{$item->{'parenttalkid'}},
|
||||
$jitemid, 'L', map { $item->{$_} } qw(posterid datepost state));
|
||||
|
||||
|
||||
$replace_into->("talktext2", "(journalid, jtalkid, subject, body)",
|
||||
20, $userid, $jtalkid, map { $itemtext->{$_} } qw(subject body));
|
||||
|
||||
# copy its logprop over:
|
||||
while (my $lp = $treader->(50, "SELECT talkid, tpropid, value FROM talkprop", $talkid)) {
|
||||
next unless $lp->{'value'};
|
||||
$replace_into->("talkprop2", "(journalid, jtalkid, tpropid, value)", 50,
|
||||
$userid, $jtalkid, $lp->{'tpropid'}, $lp->{'value'});
|
||||
}
|
||||
|
||||
# note that poster commented here
|
||||
if ($item->{'posterid'}) {
|
||||
my $pub = $logitem->{'security'} eq "public" ? 1 : 0;
|
||||
my ($table, $db) = ("talkleft_xfp", $dbh);
|
||||
($table, $db) = ("talkleft", $dbch) if $userid == $item->{'posterid'};
|
||||
$replace_into->($db, $table, "(userid, posttime, journalid, nodetype, ".
|
||||
"nodeid, jtalkid, publicitem)", 50,
|
||||
$item->{'posterid'}, $item->{'datepostunix'}, $userid,
|
||||
'L', $jitemid, $jtalkid, $pub);
|
||||
}
|
||||
}
|
||||
|
||||
sub make_buffer_reader
|
||||
{
|
||||
my $pricol = shift;
|
||||
my $valsref = shift;
|
||||
|
||||
my %bfd; # buffer read data. halfquery -> { 'rows' => { id => [] },
|
||||
# 'remain' => [], 'loaded' => { id => 1 } }
|
||||
return sub
|
||||
{
|
||||
my ($amt, $hq, $pid) = @_;
|
||||
if (not defined $bfd{$hq}->{'loaded'}->{$pid})
|
||||
{
|
||||
if (not exists $bfd{$hq}->{'remain'}) {
|
||||
$bfd{$hq}->{'remain'} = [ @$valsref ];
|
||||
}
|
||||
|
||||
my @todo;
|
||||
for (1..$amt) {
|
||||
next unless @{$bfd{$hq}->{'remain'}};
|
||||
my $id = shift @{$bfd{$hq}->{'remain'}};
|
||||
push @todo, $id;
|
||||
$bfd{$hq}->{'loaded'}->{$id} = 1;
|
||||
}
|
||||
|
||||
if (@todo) {
|
||||
my $sql = "$hq WHERE $pricol IN (" . join(",", @todo) . ")";
|
||||
my $sth = $dbr->prepare($sql);
|
||||
$sth->execute;
|
||||
while (my $r = $sth->fetchrow_hashref) {
|
||||
push @{$bfd{$hq}->{'rows'}->{$r->{$pricol}}}, $r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return shift @{$bfd{$hq}->{'rows'}->{$pid}};
|
||||
};
|
||||
}
|
||||
|
||||
# this function needs to die loudly if moveucluster.pl is unable to move
|
||||
# any type of table that exists on this installation
|
||||
sub verify_movable_tables {
|
||||
my %table; # tablename -> unhandled flag
|
||||
|
||||
# first, assume everything's unhandled
|
||||
foreach my $t (@LJ::USER_TABLES, @LJ::USER_TABLES_LOCAL) {
|
||||
$table{$t} = 1;
|
||||
}
|
||||
|
||||
# now, clear things we know how to move
|
||||
foreach my $t (qw(cmdbuffer dudata log2 logsec2 logprop2 logtext2
|
||||
talk2 talkprop2 talktext2 talkleft
|
||||
), @manual_move) {
|
||||
delete $table{$t};
|
||||
}
|
||||
|
||||
# local stuff
|
||||
my $local_tables = LJ::run_hook("moveucluster_local_tables");
|
||||
if ($local_tables) {
|
||||
while (my ($tab, $key) = each %$local_tables) {
|
||||
delete $table{$tab};
|
||||
}
|
||||
}
|
||||
|
||||
# things we list as active tables but don't use yet
|
||||
delete $table{"events"};
|
||||
|
||||
# things we don't move because it doesn't really matter
|
||||
delete $table{"s1stylecache"};
|
||||
delete $table{"captcha_session"};
|
||||
|
||||
if (%table) {
|
||||
die "ERROR. Won't try to move user, because this mover script can't move all live tables for this user. List of tables without mover code available: \n -- " . join("\n -- ", sort keys %table), "\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
1; # return true;
|
||||
84
livejournal/bin/upgrading/pop-clusterprops.pl
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# This script converts from dversion 3 to dversion 4,
|
||||
# which makes most userprops clustered
|
||||
#
|
||||
|
||||
use strict;
|
||||
|
||||
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
|
||||
|
||||
my $fromver = shift;
|
||||
die "Usage: pop-clusterprops.pl <fromdversion>\n\t(where fromdversion is one of: 3)\n"
|
||||
unless $fromver == 3;
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
my $todo = $dbh->selectrow_array("SELECT COUNT(*) FROM user WHERE dversion=$fromver");
|
||||
my $done = 0;
|
||||
unless ($todo) {
|
||||
print "Nothing to convert.\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
sub get_some {
|
||||
my @list;
|
||||
my $sth = $dbh->prepare("SELECT * FROM user WHERE dversion=$fromver LIMIT 200");
|
||||
$sth->execute;
|
||||
push @list, $_ while $_ = $sth->fetchrow_hashref;
|
||||
@list;
|
||||
}
|
||||
|
||||
my $tover = $fromver + 1;
|
||||
print "Converting $todo users from data version $fromver to $tover...\n";
|
||||
|
||||
my @props;
|
||||
my $sth = $dbh->prepare("SELECT upropid FROM userproplist WHERE cldversion=?");
|
||||
$sth->execute($tover);
|
||||
push @props, $_ while $_ = $sth->fetchrow_array;
|
||||
my $in = join(',', @props);
|
||||
die "No values?" unless $in;
|
||||
|
||||
my $start = time();
|
||||
while (my @list = get_some()) {
|
||||
LJ::start_request();
|
||||
|
||||
my %cluster; # clusterid -> [ $u* ]
|
||||
foreach my $u (@list) {
|
||||
push @{$cluster{$u->{'clusterid'}}}, $u;
|
||||
}
|
||||
|
||||
foreach my $cid (keys %cluster) {
|
||||
my $dbcm = LJ::get_cluster_master($cid);
|
||||
next unless $dbcm;
|
||||
|
||||
my $uid_in = join(',', map { $_->{'userid'} } @{$cluster{$cid}});
|
||||
|
||||
my @vals;
|
||||
foreach my $table (qw(userprop userproplite)) {
|
||||
$sth = $dbh->prepare("SELECT userid, upropid, value FROM $table ".
|
||||
"WHERE userid IN ($uid_in) AND upropid IN ($in)");
|
||||
$sth->execute();
|
||||
while (my ($uid, $pid, $v) = $sth->fetchrow_array) {
|
||||
push @vals, "($uid,$pid," . $dbh->quote($v) . ")";
|
||||
}
|
||||
}
|
||||
if (@vals) {
|
||||
my $sql = "REPLACE INTO userproplite2 VALUES " . join(',', @vals);
|
||||
$dbcm->do($sql);
|
||||
if ($dbcm->err) {
|
||||
die "Error: " . $dbcm->errstr . "\n\n(Do you need to --runsql on your clusters first?)\n";
|
||||
}
|
||||
$dbh->do("DELETE FROM userprop WHERE userid IN ($uid_in) AND upropid IN ($in)");
|
||||
$dbh->do("DELETE FROM userproplite WHERE userid IN ($uid_in) AND upropid IN ($in)");
|
||||
}
|
||||
$dbh->do("UPDATE user SET dversion=$tover WHERE userid IN ($uid_in) AND dversion=$fromver");
|
||||
$done += scalar @{$cluster{$cid}};
|
||||
}
|
||||
|
||||
my $perc = $done/$todo;
|
||||
my $elapsed = time() - $start;
|
||||
my $total_time = $elapsed / $perc;
|
||||
my $min_remain = int(($total_time - $elapsed) / 60);
|
||||
printf "%d/%d complete (%.02f%%) minutes_remain=%d\n", $done, $todo, ($perc*100), $min_remain;
|
||||
}
|
||||
68
livejournal/bin/upgrading/pop-weekuu.pl
Executable file
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# This script converts from dversion 2 (clustered + userpicblobs clustered)
|
||||
# to dversion 3, which adds weekuserusage population.
|
||||
#
|
||||
|
||||
use strict;
|
||||
|
||||
require "$ENV{'LJHOME'}/cgi-bin/ljlib.pl";
|
||||
|
||||
die "This script is no longer useful.\n";
|
||||
|
||||
my $dbh = LJ::get_db_writer();
|
||||
|
||||
my $todo = $dbh->selectrow_array("SELECT COUNT(*) FROM user WHERE dversion=2");
|
||||
my $done = 0;
|
||||
unless ($todo) {
|
||||
print "Nothing to convert.\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
sub get_some {
|
||||
my @list;
|
||||
my $sth = $dbh->prepare("SELECT * FROM user WHERE dversion=2 LIMIT 200");
|
||||
$sth->execute;
|
||||
push @list, $_ while $_ = $sth->fetchrow_hashref;
|
||||
@list;
|
||||
}
|
||||
|
||||
print "Converting $todo users from data version 2 to 3...\n";
|
||||
my $start = time();
|
||||
while (my @list = get_some()) {
|
||||
LJ::start_request();
|
||||
foreach my $u (@list) {
|
||||
my $dbcm = LJ::get_cluster_master($u);
|
||||
next unless $dbcm;
|
||||
|
||||
my %week;
|
||||
my $sth = $dbcm->prepare("SELECT rlogtime FROM log2 ".
|
||||
"WHERE journalid=? AND rlogtime < 2147483647");
|
||||
$sth->execute($u->{'userid'});
|
||||
while (my $t = $sth->fetchrow_array) {
|
||||
my ($week, $uafter, $ubefore) = LJ::weekuu_parts($t);
|
||||
if (! $week{$week}) {
|
||||
$week{$week} = [ $uafter, $ubefore ];
|
||||
} elsif ($ubefore < $week{$week}->[1]) {
|
||||
$week{$week}->[1] = $ubefore;
|
||||
}
|
||||
}
|
||||
|
||||
if (%week) {
|
||||
my $sql = "REPLACE INTO weekuserusage (wknum,userid,uafter,ubefore) VALUES " .
|
||||
join(",", map { "($_,$u->{'userid'},$week{$_}->[0],$week{$_}->[1])" } keys %week);
|
||||
my $rv = $dbh->do($sql);
|
||||
die $dbh->errstr if $dbh->err;
|
||||
next unless $rv; # error? try later.
|
||||
}
|
||||
|
||||
$dbh->do("UPDATE user SET dversion=3 WHERE userid=?", undef, $u->{'userid'});
|
||||
$done++;
|
||||
}
|
||||
|
||||
my $perc = $done/$todo;
|
||||
my $elapsed = time() - $start;
|
||||
my $total_time = $elapsed / $perc;
|
||||
my $min_remain = int(($total_time - $elapsed) / 60);
|
||||
printf "%d/%d complete (%.02f%%) minutes_remain=%d\n", $done, $todo, ($perc*100), $min_remain;
|
||||
}
|
||||
85
livejournal/bin/upgrading/s1style-rw.pl
Executable file
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# Library to read/write s1styles.dat
|
||||
#
|
||||
|
||||
sub s1styles_read
|
||||
{
|
||||
my $ss = {};
|
||||
|
||||
open (F, "$ENV{'LJHOME'}/bin/upgrading/s1styles.dat");
|
||||
my $uniq;
|
||||
my $entry;
|
||||
my $read_entry = 0;
|
||||
my $line = 0;
|
||||
while (<F>)
|
||||
{
|
||||
$line++;
|
||||
if ($read_entry && $entry)
|
||||
{
|
||||
if ($_ eq ".\n") {
|
||||
chop $entry->{'formatdata'}; # we added a newline
|
||||
$read_entry = 0;
|
||||
undef $entry;
|
||||
next;
|
||||
}
|
||||
s!^\.!!;
|
||||
$entry->{'formatdata'} .= $_;
|
||||
next;
|
||||
}
|
||||
|
||||
if (m!^Style:\s*(\w+?)/(.+?)\s*$!) {
|
||||
$uniq = "$1/$2";
|
||||
die "Repeat style in s1styles.dat at line $line!"
|
||||
if exists $ss->{$uniq};
|
||||
$entry = $ss->{$uniq} = {
|
||||
'type' => $1,
|
||||
'styledes' => $2,
|
||||
};
|
||||
$read_entry = 0;
|
||||
next;
|
||||
}
|
||||
|
||||
if ($entry && $_ eq "\n") {
|
||||
$read_entry = 1;
|
||||
next;
|
||||
}
|
||||
|
||||
next unless $entry;
|
||||
if (/^(\w+):\s*(.+?)\s*$/) {
|
||||
$entry->{$1} = $2;
|
||||
next;
|
||||
}
|
||||
|
||||
die "s1styles.dat:$line: bogus line\n" if /\S/;
|
||||
}
|
||||
close F;
|
||||
|
||||
return $ss;
|
||||
}
|
||||
|
||||
sub s1styles_write
|
||||
{
|
||||
my $ss = shift;
|
||||
|
||||
open (F, ">$ENV{'LJHOME'}/bin/upgrading/s1styles.dat")
|
||||
or die "Can't open s1styles.dat for writing.\n";
|
||||
|
||||
foreach my $uniq (sort keys %$ss) {
|
||||
my $s = $ss->{$uniq};
|
||||
print F "Style: $uniq\n";
|
||||
foreach (qw(is_public is_embedded is_colorfree opt_cache lastupdate)) {
|
||||
next unless exists $s->{$_};
|
||||
print F "$_: $s->{$_}\n";
|
||||
}
|
||||
|
||||
my $formatdata = $s->{'formatdata'};
|
||||
$formatdata =~ s/\r//g; # die, DOS line endings!
|
||||
$formatdata =~ s/\n\./\n\.\./g;
|
||||
print F "\n$formatdata\n.\n\n";
|
||||
}
|
||||
close F;
|
||||
|
||||
}
|
||||
|
||||
1;
|
||||
7523
livejournal/bin/upgrading/s1styles.dat
Executable file
54
livejournal/bin/upgrading/s2layers.dat
Executable file
@@ -0,0 +1,54 @@
|
||||
################################################################
|
||||
# base filename layer type parent
|
||||
|
||||
core1 core -
|
||||
i18nc/da1 i18nc core1
|
||||
i18nc/de1 i18nc core1
|
||||
i18nc/en1 i18nc core1
|
||||
i18nc/eo1 i18nc core1
|
||||
i18nc/fi1 i18nc core1
|
||||
i18nc/fr1 i18nc core1
|
||||
i18nc/ja1 i18nc core1
|
||||
i18nc/ru1 i18nc core1
|
||||
|
||||
classic/layout layout core1
|
||||
classic/en i18n classic/layout
|
||||
classic/themes theme+ classic/layout
|
||||
|
||||
cleansimple/layout layout core1
|
||||
cleansimple/en i18n cleansimple/layout
|
||||
cleansimple/themes theme+ cleansimple/layout
|
||||
|
||||
digitalmultiplex/layout layout core1
|
||||
digitalmultiplex/en i18n digitalmultiplex/layout
|
||||
|
||||
haven/layout layout core1
|
||||
haven/themes theme+ haven/layout
|
||||
|
||||
generator/layout layout core1
|
||||
generator/en i18n generator/layout
|
||||
generator/themes theme+ generator/layout
|
||||
|
||||
magazine/layout layout core1
|
||||
magazine/en i18n magazine/layout
|
||||
magazine/themes theme+ magazine/layout
|
||||
|
||||
notepad/layout layout core1
|
||||
notepad/en i18n notepad/layout
|
||||
#notepad/themes theme+ notepad/layout
|
||||
|
||||
punquin/layout layout core1
|
||||
punquin/en i18n punquin/layout
|
||||
punquin/themes theme+ punquin/layout
|
||||
|
||||
tabularindent/layout layout core1
|
||||
tabularindent/en i18n tabularindent/layout
|
||||
tabularindent/themes theme+ tabularindent/layout
|
||||
|
||||
sturdygesture/layout layout core1
|
||||
sturdygesture/themes theme+ sturdygesture/layout
|
||||
|
||||
variableflow/layout layout core1
|
||||
|
||||
# include local file
|
||||
s2layers-local.dat INCLUDE
|
||||
BIN
livejournal/bin/upgrading/s2layers/classic/classic.jpg
Executable file
|
After Width: | Height: | Size: 21 KiB |
16
livejournal/bin/upgrading/s2layers/classic/en.s2
Executable file
@@ -0,0 +1,16 @@
|
||||
# -*-s2-*-
|
||||
|
||||
layerinfo type = "i18n";
|
||||
layerinfo name = "English";
|
||||
layerinfo redist_uniq = "classic/en";
|
||||
|
||||
set text_meta_music = "Current Music";
|
||||
set text_meta_mood = "Current Mood";
|
||||
|
||||
set text_permalink = "Link";
|
||||
|
||||
set text_post_comment = "Comment on This";
|
||||
set text_post_comment_friends = "Comment on This";
|
||||
|
||||
set text_read_comments = "1 comment // # comments";
|
||||
set text_read_comments_friends = "1 comment // # comments";
|
||||
785
livejournal/bin/upgrading/s2layers/classic/layout.s2
Executable file
@@ -0,0 +1,785 @@
|
||||
# -*-s2-*-
|
||||
|
||||
layerinfo type = "layout";
|
||||
layerinfo name = "Classic";
|
||||
layerinfo redist_uniq = "classic/layout";
|
||||
layerinfo previews = "classic/classic.jpg";
|
||||
|
||||
propgroup colors {
|
||||
property Color body_bgcolor {
|
||||
des = "Background color of page";
|
||||
s1color = "stronger_back";
|
||||
}
|
||||
property Color main_bgcolor {
|
||||
des = "Background color of main text area";
|
||||
s1color = "page_back";
|
||||
}
|
||||
property Color main_fgcolor {
|
||||
des = "Color of text on main text areas";
|
||||
s1color = "page_text";
|
||||
}
|
||||
property Color headerbar_bgcolor {
|
||||
des = "Background color of header bars";
|
||||
s1color = "strong_back";
|
||||
}
|
||||
property Color headerbar_fgcolor {
|
||||
des = "Color of text on header bars";
|
||||
s1color = "strong_text";
|
||||
}
|
||||
property Color metabar_bgcolor {
|
||||
des = "Background color of side bar";
|
||||
s1color = "weak_back";
|
||||
}
|
||||
property Color metabar_fgcolor {
|
||||
des = "Color of text on side bar";
|
||||
s1color = "weak_text";
|
||||
}
|
||||
property Color page_title_color {
|
||||
des = "Text color of the page's main title";
|
||||
s1color = "page_text_title";
|
||||
}
|
||||
property Color page_subtitle_color {
|
||||
des = "Text color of the page's subtitles";
|
||||
s1color = "page_text_em";
|
||||
}
|
||||
property Color link_color {
|
||||
des = "Text color of links";
|
||||
s1color = "page_link";
|
||||
}
|
||||
property Color vlink_color {
|
||||
des = "Text color of visited links";
|
||||
s1color = "page_vlink";
|
||||
}
|
||||
property Color alink_color {
|
||||
des = "Text color of active links";
|
||||
s1color = "page_alink";
|
||||
}
|
||||
property Color comment_bar_one_bgcolor {
|
||||
des = "Alternating background color for comment bars (one)";
|
||||
}
|
||||
property Color comment_bar_two_fgcolor {
|
||||
des = "Text color on alternating comment bars (one)";
|
||||
}
|
||||
property Color comment_bar_two_bgcolor {
|
||||
des = "Alternating background color for comment bars (two)";
|
||||
}
|
||||
property Color comment_bar_one_fgcolor {
|
||||
des = "Text color on alternating comment bars (two)";
|
||||
}
|
||||
property Color comment_bar_screened_bgcolor {
|
||||
des = "Background bar color for screened comments";
|
||||
}
|
||||
property Color comment_bar_screened_fgcolor {
|
||||
des = "Text color on background bar for screened comments";
|
||||
}
|
||||
}
|
||||
set body_bgcolor = "#6666cc";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set headerbar_bgcolor = "#c0c0ff";
|
||||
set headerbar_fgcolor = "#000000";
|
||||
set metabar_bgcolor = "#eeeeff";
|
||||
set metabar_fgcolor = "#000000";
|
||||
set page_title_color = "#8b1a1a";
|
||||
set page_subtitle_color = "#c00000";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#c0c0ff";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#eeeeff";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
set comment_bar_screened_bgcolor = "#dddddd";
|
||||
set comment_bar_screened_fgcolor = "#000000";
|
||||
set tags_aware = true;
|
||||
|
||||
propgroup presentation {
|
||||
property bool show_entry_userpic {
|
||||
des = "Show your userpic with your journal's entries?";
|
||||
}
|
||||
property use font_base;
|
||||
property use font_fallback;
|
||||
property use page_recent_items;
|
||||
property use page_friends_items;
|
||||
property use view_entry_disabled;
|
||||
property use use_shared_pic;
|
||||
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;
|
||||
}
|
||||
set show_entry_userpic = false;
|
||||
set font_base = "Arial, Helvetica";
|
||||
set font_fallback = "sans-serif";
|
||||
set page_recent_items = 20;
|
||||
set page_friends_items = 25;
|
||||
set view_entry_disabled = false;
|
||||
set show_entrynav_icons = true;
|
||||
set page_background_image = "";
|
||||
|
||||
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_website_default_name;
|
||||
}
|
||||
|
||||
function print_stylesheet ()
|
||||
{
|
||||
print clean_url($*page_background_image) != "" ? "body { background-image: url($*page_background_image); }" : "";
|
||||
var string font;
|
||||
if ($*font_base) {
|
||||
$font = "\"$*font_base\"";
|
||||
if ($*font_fallback != "none") {
|
||||
$font = "$font, ";
|
||||
}
|
||||
}
|
||||
if ($*font_fallback != "none") {
|
||||
$font = "$font $*font_fallback";
|
||||
}
|
||||
|
||||
if ($font != "") {
|
||||
"""
|
||||
body, table, td, th, .page_title, #yearheader {
|
||||
font-family: $font;
|
||||
}
|
||||
""";
|
||||
}
|
||||
|
||||
"""
|
||||
body,.body {
|
||||
background-color: $*body_bgcolor;
|
||||
color: $*main_fgcolor;
|
||||
padding: 5pt;
|
||||
}
|
||||
a, a:link {
|
||||
color: $*link_color;
|
||||
}
|
||||
a:vlink {
|
||||
color: $*vlink_color;
|
||||
}
|
||||
a:alink {
|
||||
color: $*alink_color;
|
||||
}
|
||||
table.main {
|
||||
background-color: $*main_bgcolor;
|
||||
color: $*main_fgcolor;
|
||||
}
|
||||
.page_title {
|
||||
color: $*page_title_color;
|
||||
font-size: 18pt;
|
||||
}
|
||||
.view_links {
|
||||
font-family: monospace;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.view_links2 {
|
||||
font-family: monospace;
|
||||
font-size: 9pt;
|
||||
}
|
||||
th.headerbar {
|
||||
background-color: $*headerbar_bgcolor;
|
||||
color: $*headerbar_fgcolor;
|
||||
font-weight: bold;
|
||||
font-size: 16pt;
|
||||
text-align: left;
|
||||
}
|
||||
td.metabar {
|
||||
text-align: right;
|
||||
white-space: nowrap;
|
||||
background-color: $*metabar_bgcolor;
|
||||
color: $*metabar_fgcolor;
|
||||
}
|
||||
.subject {
|
||||
color: $*page_subtitle_color;
|
||||
font-weight: bold;
|
||||
}
|
||||
.comments {
|
||||
text-align: right;
|
||||
}
|
||||
#yearheader {
|
||||
color: $*page_subtitle_color;
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
font-size: 14pt;
|
||||
}
|
||||
th.monthheader {
|
||||
background-color: $*headerbar_bgcolor;
|
||||
font-size: 12pt;
|
||||
}
|
||||
th.daysheader {
|
||||
background-color: $*metabar_bgcolor;
|
||||
font-weight: normal;
|
||||
}
|
||||
td.weekday_empty {
|
||||
background-color: $*metabar_bgcolor;
|
||||
}
|
||||
.day_id {
|
||||
font-weight: bold;
|
||||
font-size: 10pt;
|
||||
}
|
||||
#archiveyearpage_nav {
|
||||
font-size: 14pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
""";
|
||||
}
|
||||
|
||||
function Page::lay_nav_blurb() { }
|
||||
|
||||
function Page::lay_primary_userpic() : Image {
|
||||
return $.journal.default_pic;
|
||||
}
|
||||
|
||||
function EntryPage::lay_primary_userpic() : Image {
|
||||
return $.entry.userpic;
|
||||
}
|
||||
|
||||
function Page::print_linklist() {
|
||||
if (size $.linklist <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var bool section_open = false;
|
||||
|
||||
println "<span class='view_links2'>";
|
||||
foreach var UserLink l ($.linklist) {
|
||||
if ($l.title) {
|
||||
if ($l.is_heading) {
|
||||
if ($section_open) {
|
||||
println "<br />";
|
||||
}
|
||||
println """<span style="font-weight: bold;">$l.title</span> """;
|
||||
$section_open = true;
|
||||
} else {
|
||||
println """[<a href="$l.url">$l.title</a>]""";
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($section_open) {
|
||||
println "</span><br /><br />";
|
||||
}
|
||||
println "";
|
||||
}
|
||||
|
||||
function Page::print ()
|
||||
{
|
||||
var string title = $this->title();
|
||||
var string userpic;
|
||||
var Image default_userpic = $this->lay_primary_userpic();
|
||||
if (defined $default_userpic)
|
||||
{
|
||||
$userpic = "<img align='right' style='padding: 2px' src='$default_userpic.url' "+
|
||||
"width='$default_userpic.width' height='$default_userpic.height' alt='' />";
|
||||
}
|
||||
var string website_name = $.journal.website_name ? $.journal.website_name : $*text_website_default_name;
|
||||
var string website = $.journal.website_url ?
|
||||
"""<td><a href="$.journal.website_url">$website_name</a></td><td class="body"> </td>""" :
|
||||
"";
|
||||
var string links;
|
||||
foreach var string v ($.views_order) {
|
||||
$links = $links + ($.view == $v ?
|
||||
"["+lang_viewname($v)+"]" :
|
||||
"[<a href='$.view_url{$v}'>"+lang_viewname($v)+"</a>]");
|
||||
}
|
||||
"""
|
||||
<html>
|
||||
<head>
|
||||
""";
|
||||
|
||||
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>
|
||||
<table class="main" width='100%'><tr><td>
|
||||
$userpic
|
||||
<span class="page_title">$title</span>
|
||||
<p class="view_links">$links</p>
|
||||
""";
|
||||
if (size $.linklist > 0 and $*linklist_support) {
|
||||
$this->print_linklist();
|
||||
}
|
||||
|
||||
$this->lay_nav_blurb();
|
||||
$this->print_body();
|
||||
"</td></tr></table>\n";
|
||||
|
||||
### Affliations
|
||||
|
||||
"<table class='main' align='right'><tr>";
|
||||
|
||||
print $website; "<td>"; server_sig(); "</td></tr>";
|
||||
|
||||
"</table>\n</body>\n</html>";
|
||||
}
|
||||
|
||||
function print_entry (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text)
|
||||
{
|
||||
var string time = $e.time->time_format();
|
||||
var string userpic = "";
|
||||
if (defined $e.userpic)
|
||||
{
|
||||
$userpic = "<img src='$e.userpic.url' alt='[User Picture]' height='$e.userpic.height' width='$e.userpic.width' />";
|
||||
}
|
||||
if ($e.new_day or $p.view == "entry")
|
||||
{
|
||||
"<tr><th colspan='2' align='left' class='headerbar'>";
|
||||
print $e.time->date_format("%%month%% %%dayord%%, %%yyyy%%");
|
||||
"</th></tr>\n";
|
||||
} elseif ($p.view == "day") {
|
||||
"<tr><th class='headerbar'>Time</td><td class='headerbar' style='width: 100%'>Event</th></tr>";
|
||||
}
|
||||
"<tr valign='top'>";
|
||||
|
||||
# Metabar
|
||||
"<td style='background-color: $bgcolor;' class='metabar'>";
|
||||
# Time
|
||||
"<em>$time</em><br />";
|
||||
# Altposter crap
|
||||
if ($p.view == "friends")
|
||||
{
|
||||
"<strong><a style='color: $fgcolor' href='" + $e.journal->base_url() + "/'>";
|
||||
print $e.journal.username;
|
||||
"</a></strong><br />";
|
||||
}
|
||||
if ($e.journal.username != $e.poster.username)
|
||||
{
|
||||
"[<a href='" + $e.poster->base_url() + "/'>";
|
||||
print $e.poster.username;
|
||||
"</a>]<br />";
|
||||
}
|
||||
if ($userpic != "" and ($p.view == "friends" or $*show_entry_userpic == true))
|
||||
{
|
||||
print $userpic;
|
||||
}
|
||||
# Security icon
|
||||
if ($e.security) { print $e.security_icon; }
|
||||
# Permalink
|
||||
"<p>[<a href='$e.permalink_url'>$*text_permalink</a>]</p>";
|
||||
"</td>";
|
||||
|
||||
# Entry
|
||||
"<td style='text-align:left'>";
|
||||
|
||||
if ($p.view == "entry" and $*show_entrynav_icons)
|
||||
{
|
||||
print "<div style='text-align: center'>";
|
||||
$e->print_linkbar();
|
||||
print "</div>";
|
||||
}
|
||||
|
||||
if ($e.subject) { "\n\n<span class='subject'>$e.subject</span><br />"; }
|
||||
if (not $hide_text) {
|
||||
print $e.text; "\n\n";
|
||||
if (size $e.metadata or size $e.tags)
|
||||
{
|
||||
"<p>";
|
||||
foreach var string k ($e.metadata)
|
||||
{
|
||||
var string key = $k;
|
||||
var string val = $e.metadata{$k};
|
||||
if ($k == "mood") { $key = $*text_meta_mood; }
|
||||
if ($k == "music") { $key = $*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' alt='' /> $val";
|
||||
}
|
||||
"<strong>$key:</strong> $val<br />";
|
||||
}
|
||||
|
||||
if ($e.tags) {
|
||||
var int tcount = 0;
|
||||
"<strong>Tags:</strong> ";
|
||||
foreach var Tag t ($e.tags) {
|
||||
"""<a rel="tag" href="$t.url">$t.name</a>""";
|
||||
$tcount++;
|
||||
if ($tcount != size $e.tags) { ", "; }
|
||||
}
|
||||
"<br />";
|
||||
}
|
||||
|
||||
"</p>";
|
||||
}
|
||||
}
|
||||
$e.comments->print();
|
||||
"</td>";
|
||||
"</tr>\n";
|
||||
}
|
||||
|
||||
function Page::print_entry (Entry e)
|
||||
{
|
||||
print_entry($this, $e, $*metabar_bgcolor, $*metabar_fgcolor, false);
|
||||
}
|
||||
|
||||
function FriendsPage::print_entry (Entry e)
|
||||
{
|
||||
var Friend f = $.friends{$e.journal.username};
|
||||
print_entry($this, $e, $f.bgcolor, $f.fgcolor, false);
|
||||
}
|
||||
|
||||
function RecentPage::lay_nav_blurb ()
|
||||
{
|
||||
var string user = "<a href='$.base_url/info'>$.journal.name</a>";
|
||||
if ($.nav.skip > 0)
|
||||
{
|
||||
"Below are $.nav.count entries, after skipping $.nav.skip most recent ones in the \"$user\" journal:";
|
||||
} else {
|
||||
"Below are the $.nav.count most recent journal entries recorded in the \"$user\" journal:";
|
||||
}
|
||||
}
|
||||
|
||||
function RecentPage::print_body ()
|
||||
{
|
||||
var string nav = "";
|
||||
if ($.nav.forward_url != "" or $.nav.backward_url != "")
|
||||
{
|
||||
if ($.nav.backward_url != "")
|
||||
{
|
||||
$nav = "<a href='$.nav.backward_url'><< Previous $.nav.backward_count entries</a>";
|
||||
}
|
||||
if ($.nav.backward_url != "" and $.nav.forward_url != "")
|
||||
{
|
||||
$nav = "$nav --";
|
||||
}
|
||||
if ($.nav.forward_url != "")
|
||||
{
|
||||
$nav = "$nav <a href='$.nav.forward_url'>Next $.nav.forward_count entries >></a>";
|
||||
}
|
||||
$nav = "<p align='center'>[$nav]</p>";
|
||||
}
|
||||
if ($nav != "") { print $nav; }
|
||||
"<table style='margin-left: 30px'>\n";
|
||||
foreach var Entry e ($.entries) { $this->print_entry($e); }
|
||||
"</table>\n";
|
||||
if ($nav != "") { print $nav; }
|
||||
}
|
||||
|
||||
function FriendsPage::lay_nav_blurb ()
|
||||
{
|
||||
var int total = size $.entries;
|
||||
if ($.nav.skip > 0)
|
||||
{
|
||||
"Below are $total friends entries, after skipping $.nav.skip most recent ones:";
|
||||
} else {
|
||||
"Below are the $total most recent friends journal entries:";
|
||||
}
|
||||
}
|
||||
|
||||
function CommentInfo::print ()
|
||||
{
|
||||
if (not $.enabled) { return; }
|
||||
"<p class='comments'>(";
|
||||
if ($.count > 0 or $.screened) {
|
||||
$this->print_readlink();
|
||||
" | ";
|
||||
}
|
||||
$this->print_postlink();
|
||||
")</p>";
|
||||
}
|
||||
|
||||
function YearPage::lay_nav_blurb()
|
||||
{
|
||||
"<p id='yearpage_nav'>";
|
||||
$this->print_year_links();
|
||||
"</p>";
|
||||
}
|
||||
|
||||
function YearPage::print_body
|
||||
{
|
||||
"<p id='yearheader'>$.year…</p>\n";
|
||||
foreach var YearMonth m ($.months) {
|
||||
$this->print_month($m);
|
||||
}
|
||||
}
|
||||
|
||||
function YearPage::print_year_links ()
|
||||
{
|
||||
foreach var YearYear y ($.years) {
|
||||
if ($y.displayed) {
|
||||
"[ $y.year ]";
|
||||
} else {
|
||||
"[ <a href=\"$y.url\">$y.year</a> ]";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function YearPage::print_month(YearMonth m)
|
||||
{
|
||||
if (not $m.has_entries) { return; }
|
||||
# Table Wrapper
|
||||
"<center><p><table border='1' cellpadding='4' width='80%'>\n";
|
||||
|
||||
# Month Header
|
||||
"<tr align='center'><th colspan='7' class='monthheader'>\n";
|
||||
print $m->month_format();
|
||||
"</th></tr>\n";
|
||||
|
||||
# Weekdays Header
|
||||
"<tr align='center'>\n";
|
||||
foreach var int d (weekdays()) {
|
||||
"<th class='daysheader'>"+$*lang_dayname_short[$d]+"</th>\n";
|
||||
}
|
||||
"</tr>\n";
|
||||
|
||||
# Weeks
|
||||
foreach var YearWeek w ($m.weeks) {
|
||||
$w->print();
|
||||
}
|
||||
|
||||
# Footer
|
||||
"<tr><td colspan='7'><div style='text-align: center'><a href='$m.url'>$*text_view_month</a></div></td></tr>\n";
|
||||
|
||||
# End Table
|
||||
"</table></p></center>\n";
|
||||
}
|
||||
|
||||
function YearWeek::print ()
|
||||
{
|
||||
"<tr>";
|
||||
if ($.pre_empty) { "<td colspan='$.pre_empty' class='weekday_empty'> </td>"; }
|
||||
foreach var YearDay d ($.days) {
|
||||
"<td valign='top'><span class='day_id'>$d.day</span><div style='text-align: center'>";
|
||||
if ($d.num_entries) {
|
||||
"<a href='$d.url'>$d.num_entries</a>";
|
||||
} else {
|
||||
" ";
|
||||
}
|
||||
"</div></td>\n";
|
||||
}
|
||||
if ($.post_empty) { "<td colspan='$.post_empty' class='weekday_empty'> </td>"; }
|
||||
"</tr>";
|
||||
}
|
||||
|
||||
function DayPage::print_body ()
|
||||
{
|
||||
"<h2 class='daypage_header'>"; print $.date->date_format("%%month%% %%dayord%%, %%yyyy%%"); "</h2>";
|
||||
if (not $.has_entries)
|
||||
{
|
||||
"<blockquote><em>"; print ehtml($*text_noentries_day); "</em></blockquote>";
|
||||
} else {
|
||||
"<table style='margin-left: 30px'>";
|
||||
foreach var Entry e ($.entries) { $this->print_entry($e); }
|
||||
"</table>";
|
||||
}
|
||||
|
||||
var string tprev = ehtml($*text_day_prev);
|
||||
var string tnext = ehtml($*text_day_next);
|
||||
|
||||
"<table align='center'><tr align='middle'>\n";
|
||||
|
||||
"<td width='33%' align='left'><a href='$.prev_url'>$tprev</a></td>\n";
|
||||
"<td align='center' width='33%'>";
|
||||
"<strong>"; print $.date->date_format("%%yyyy%%/%%mm%%/%%dd%%"); "</strong><br />";
|
||||
"[<a href='"; print $this.journal->base_url(); "/calendar'>$*text_view_archive</a>]</td>\n";
|
||||
"<td width='33%' align='right'><a href='$.next_url'>$tnext</a></td>\n";
|
||||
|
||||
"</tr></table>";
|
||||
|
||||
}
|
||||
|
||||
function EntryPage::print_body () {
|
||||
set_handler("unscreen_comment_#", [
|
||||
[ "style_bgcolor", "cmtbar#", "$*comment_bar_one_bgcolor", ],
|
||||
[ "style_color", "cmtbar#", "$*comment_bar_one_fgcolor", ],
|
||||
]);
|
||||
set_handler("screen_comment_#", [
|
||||
[ "style_bgcolor", "cmtbar#", "$*comment_bar_screened_bgcolor", ],
|
||||
[ "style_color", "cmtbar#", "$*comment_bar_screened_fgcolor", ],
|
||||
]);
|
||||
|
||||
"<table style='margin-left: 30px'>\n";
|
||||
print_entry($this, $.entry, $*metabar_bgcolor, $*metabar_fgcolor, $.viewing_thread);
|
||||
|
||||
if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0)
|
||||
{
|
||||
$this->print_multiform_start();
|
||||
"<tr valign='top'><th class='headerbar' colspan='2'>Comments</th></tr>";
|
||||
"<tr valign='top'><td style='background-color: $*metabar_bgcolor'> </td><td style='width: 100%'>";
|
||||
if ($.comment_pages.total_subitems > 0) {
|
||||
$.comment_pages->print();
|
||||
$this->print_comments($.comments);
|
||||
}
|
||||
"</td></tr>";
|
||||
if ($this.multiform_on) {
|
||||
"<tr valign='top'><th class='headerbar' colspan='2'>Mass Action</th></tr>";
|
||||
"<tr valign='top'><td style='background-color: $*metabar_bgcolor'> </td><td style='width: 100%'>";
|
||||
$this->print_multiform_actionline();
|
||||
$this->print_multiform_end();
|
||||
"</td></tr>";
|
||||
}
|
||||
}
|
||||
"</table>\n";
|
||||
}
|
||||
|
||||
function EntryPage::print_comment (Comment c) {
|
||||
var Color background; var Color color;
|
||||
if ($c.screened) {
|
||||
$background = $*comment_bar_screened_bgcolor;
|
||||
$color = $*comment_bar_screened_fgcolor;
|
||||
} elseif ($c.depth % 2) {
|
||||
$background = $*comment_bar_one_bgcolor;
|
||||
$color = $*comment_bar_one_fgcolor;
|
||||
} else {
|
||||
$background = $*comment_bar_two_bgcolor;
|
||||
$color = $*comment_bar_two_fgcolor;
|
||||
}
|
||||
var string poster = defined $c.poster ? $c.poster->as_string() : "<i>(Anonymous)</i>";
|
||||
var string sub_icon;
|
||||
if (defined $c.subject_icon) {
|
||||
$sub_icon = $c.subject_icon->as_string();
|
||||
}
|
||||
"<a name='$c.anchor'></a><div id='cmtbar$c.talkid' style='background-color: $background; color: $color; margin-top: 10px; width: 100%'>";
|
||||
"<table cellpadding='2' cellspacing='0' summary='0' style='width: 100%'><tr valign='top'>";
|
||||
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;
|
||||
}
|
||||
print "<td style='width: 102px'><img src='$c.userpic.url' width='$w' height='$h' alt='[User Picture]' /></td>";
|
||||
}
|
||||
|
||||
"<td style='width: 100%'><table style='width: 100%'><tr>";
|
||||
|
||||
### From, date, etc
|
||||
"<td align='left' style='width: 50%'>";
|
||||
print "<table>";
|
||||
print "<tr><th align='right'>From:</th><td>$poster</td></tr>\n";
|
||||
print "<tr><th align='right'>Date:</th><td style='white-space: nowrap'>";
|
||||
print $c.time->date_format("long") + " - " + $c.time->time_format() + "</td></tr>";
|
||||
if ($c.metadata{"poster_ip"}) { print "<tr><th align='right'>IP Address:</th><td>(" + $c.metadata{"poster_ip"} + ")</td></tr>"; }
|
||||
"</table></td>";
|
||||
|
||||
### Gadgets
|
||||
"<td align='right' style='width: 50%'>";
|
||||
if ($this.multiform_on) {
|
||||
" <label for='ljcomsel_$c.talkid'>$*text_multiform_check</label>";
|
||||
$c->print_multiform_check();
|
||||
}
|
||||
$c->print_linkbar();
|
||||
"</td></tr>";
|
||||
|
||||
### Subject / icon
|
||||
print "<tr valign='top'><td style='width: 50%'>";
|
||||
print (defined $c.subject_icon or $c.subject != "") ? "<h3>$c.subject_icon $c.subject</h3>" : "";
|
||||
print "</td>";
|
||||
|
||||
### Permalink
|
||||
print "<td style='width: 50%' align='right'><strong>(<a href='$c.permalink_url'>Link</a>)</strong></td></tr>";
|
||||
|
||||
print "</table></td></tr></table></div>";
|
||||
print "<div style='margin-left: 5px'>$c.text</div>";
|
||||
print "<div style='margin-top: 3px; font-size: smaller'>";
|
||||
if ($c.frozen) {
|
||||
print "(Replies frozen) ";
|
||||
} else {
|
||||
print "(<a href='$c.reply_url'>Reply to this</a>) ";
|
||||
}
|
||||
if ($c.parent_url != "") { "(<a href='$c.parent_url'>Parent</a>) "; }
|
||||
if ($c.thread_url != "") { "(<a href='$c.thread_url'>Thread</a>) "; }
|
||||
"</div>";
|
||||
}
|
||||
|
||||
function ReplyPage::print_body()
|
||||
{
|
||||
"<table style='margin-left: 30px'>\n";
|
||||
if (not $.entry.comments.enabled) {
|
||||
print "<tr><th class='headerbar'>$*text_reply_nocomments_header</th></tr><tr><td>$*text_reply_nocomments</td></tr></table>";
|
||||
return;
|
||||
}
|
||||
var string time = $.replyto.time->time_format();
|
||||
var string userpic = "";
|
||||
if (defined $.replyto.userpic)
|
||||
{
|
||||
$userpic = "<img src='$.replyto.userpic.url' />";
|
||||
}
|
||||
"<tr><th class='headerbar'>Time</td><th class='headerbar' style='width: 100%'>Text</th></tr>";
|
||||
"<tr valign='top'>";
|
||||
|
||||
# Metabar
|
||||
"<td style='background-color: $*metabar_bgcolor;' class='metabar'>";
|
||||
# Time
|
||||
"<em>$time</em><br />";
|
||||
if ($userpic)
|
||||
{
|
||||
print $userpic + "<br />\n";
|
||||
}
|
||||
print defined $.replyto.poster ? $.replyto.poster->as_string() : "<i>(Anonymous)</i>";
|
||||
# Permalink
|
||||
"<p>[<a href='$.replyto.permalink_url'>$*text_permalink</a>]</p>";
|
||||
"</td>";
|
||||
|
||||
# Text
|
||||
"<td style='text-align:left'>";
|
||||
if ($.replyto.subject != "") { "\n\n<span class='subject'>$.replyto.subject</span><br />"; }
|
||||
print $.replyto.text; "\n\n";
|
||||
|
||||
"</td></tr>\n";
|
||||
"<div align='center'><a href='$.entry.comments.read_url'>( Read Comments )</a></div>";
|
||||
"<tr valign='top'><th class='headerbar' colspan='2'>Reply:</th></tr>";
|
||||
"<tr valing='top'><td style='background-color: $*metabar_bgcolor'> </td><td>";
|
||||
$.form->print();
|
||||
"</td></tr></table>";
|
||||
}
|
||||
|
||||
function print_theme_preview ()
|
||||
{
|
||||
|
||||
"""
|
||||
<table width='100%' style='background-color: $*body_bgcolor'>
|
||||
<tr><td>
|
||||
<table height='95%' cellpadding='5' width='100%' bgcolor='$*main_bgcolor'>
|
||||
<tr><td>
|
||||
<span style='font: normal bold 16pt $*font_base, $*font_fallback; color: $*page_title_color'>John Doe</span>
|
||||
|
||||
<ul><table>
|
||||
<tr><td align="left" style="background-color: $*headerbar_bgcolor; color: $*headerbar_fgcolor" colspan="2">
|
||||
<span style='font: normal bold 14pt $*font_base, $*font_fallback'>Friday, November 15th, 2002</span>
|
||||
</td></tr>
|
||||
<tr valign="top"><td style="text-align: right; background-color: $*metabar_bgcolor; white-space: nowrap">
|
||||
<span style="font: italic normal 10pt $*font_base, $*font_fallback; color: $*metabar_fgcolor">
|
||||
10:21 pm</span>
|
||||
</td><td>
|
||||
|
||||
<p style="text-align:left">
|
||||
<span style="font: italic bold 10pt $*font_base, $*font_fallback; color: $*page_subtitle_color">
|
||||
Neque porro quisquam est…
|
||||
</span><br />
|
||||
|
||||
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit
|
||||
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit
|
||||
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit
|
||||
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit
|
||||
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit
|
||||
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit
|
||||
|
||||
</p><p style="text-align:right; font-size: 8pt">
|
||||
(<a href="#" style="font-weight: bold; color: $*link_color">1 Comment</a> |
|
||||
<a href="#" style="color: $*vlink_color">Comment on this</a>)
|
||||
|
||||
</p>
|
||||
|
||||
</td></tr>
|
||||
</table></ul>
|
||||
</td></tr>
|
||||
</table>
|
||||
</td></tr>
|
||||
</table>
|
||||
""";
|
||||
}
|
||||
419
livejournal/bin/upgrading/s2layers/classic/themes.s2
Executable file
@@ -0,0 +1,419 @@
|
||||
#NEWLAYER: classic/calmfire
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Calm Fire";
|
||||
layerinfo redist_uniq = "classic/calmfire";
|
||||
set body_bgcolor = "#9e0610";
|
||||
set main_bgcolor = "#7d7d7d";
|
||||
set main_fgcolor = "#ffffff";
|
||||
set headerbar_bgcolor = "#ff6c1d";
|
||||
set headerbar_fgcolor = "#000000";
|
||||
set metabar_bgcolor = "#ff9364";
|
||||
set metabar_fgcolor = "#000000";
|
||||
set page_title_color = "#8b1a1a";
|
||||
set page_subtitle_color = "#c00000";
|
||||
set link_color = "#ff1010";
|
||||
set vlink_color = "#f10707";
|
||||
set alink_color = "#ff1d1d";
|
||||
set comment_bar_one_bgcolor = "#ff6c1d";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#ff9364";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: classic/shrinkvio
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Shrinking Violet";
|
||||
layerinfo redist_uniq = "classic/shrinkvio";
|
||||
set body_bgcolor = "#ad22e7";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set headerbar_bgcolor = "#5d0383";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set metabar_bgcolor = "#5d0343";
|
||||
set metabar_fgcolor = "#ffffff";
|
||||
set page_title_color = "#d9a1f1";
|
||||
set page_subtitle_color = "#d9a1f1";
|
||||
set link_color = "#2e053f";
|
||||
set vlink_color = "#611627";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#5d0383";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#5d0343";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: classic/pistmint
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Pistachio Mint";
|
||||
layerinfo redist_uniq = "classic/pistmint";
|
||||
set body_bgcolor = "#133422";
|
||||
set main_bgcolor = "#a7c4b4";
|
||||
set main_fgcolor = "#000000";
|
||||
set headerbar_bgcolor = "#096d36";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set metabar_bgcolor = "#096d36";
|
||||
set metabar_fgcolor = "#ffffff";
|
||||
set page_title_color = "#096d36";
|
||||
set page_subtitle_color = "#096d36";
|
||||
set link_color = "#8afabc";
|
||||
set vlink_color = "#1da65a";
|
||||
set alink_color = "#f9f5f5";
|
||||
set comment_bar_one_bgcolor = "#096d36";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#096d36";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: classic/mexicanfood
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Mexican Food";
|
||||
layerinfo redist_uniq = "classic/mexicanfood";
|
||||
set body_bgcolor = "#ff0000";
|
||||
set main_bgcolor = "#f8ff3e";
|
||||
set main_fgcolor = "#f15601";
|
||||
set headerbar_bgcolor = "#bdbf3e";
|
||||
set headerbar_fgcolor = "#ff0000";
|
||||
set metabar_bgcolor = "#ffc664";
|
||||
set metabar_fgcolor = "#000000";
|
||||
set page_title_color = "#ff0000";
|
||||
set page_subtitle_color = "#e15a18";
|
||||
set link_color = "#f49e08";
|
||||
set vlink_color = "#b05403";
|
||||
set alink_color = "#ff7405";
|
||||
set comment_bar_one_bgcolor = "#bdbf3e";
|
||||
set comment_bar_one_fgcolor = "#ff0000";
|
||||
set comment_bar_two_bgcolor = "#ffc664";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: classic/ashfire
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Ash and Fire";
|
||||
layerinfo redist_uniq = "classic/ashfire";
|
||||
set body_bgcolor = "#b5b5b5";
|
||||
set main_bgcolor = "#ffb6af";
|
||||
set main_fgcolor = "#000000";
|
||||
set headerbar_bgcolor = "#e75454";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set metabar_bgcolor = "#ff9696";
|
||||
set metabar_fgcolor = "#ffffff";
|
||||
set page_title_color = "#ff1106";
|
||||
set page_subtitle_color = "#f06c88";
|
||||
set link_color = "#f70208";
|
||||
set vlink_color = "#b0161d";
|
||||
set alink_color = "#d70106";
|
||||
set comment_bar_one_bgcolor = "#e75454";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#ff9696";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: classic/desktop
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Classic Desktop";
|
||||
layerinfo redist_uniq = "classic/desktop";
|
||||
set body_bgcolor = "#00545c";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set headerbar_bgcolor = "#ff7b05";
|
||||
set headerbar_fgcolor = "#ffeddd";
|
||||
set metabar_bgcolor = "#ffffff";
|
||||
set metabar_fgcolor = "#000000";
|
||||
set page_title_color = "#ff7b05";
|
||||
set page_subtitle_color = "#ffeddd";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#5a76ff";
|
||||
set comment_bar_one_bgcolor = "#ff7b05";
|
||||
set comment_bar_one_fgcolor = "#ffeddd";
|
||||
set comment_bar_two_bgcolor = "#ffffff";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: classic/satinhandshake
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Satin Handshake";
|
||||
layerinfo redist_uniq = "classic/satinhandshake";
|
||||
set body_bgcolor = "#480c0c";
|
||||
set main_bgcolor = "#d06464";
|
||||
set main_fgcolor = "#00001d";
|
||||
set headerbar_bgcolor = "#aaaaaa";
|
||||
set headerbar_fgcolor = "#000000";
|
||||
set metabar_bgcolor = "#dddddd";
|
||||
set metabar_fgcolor = "#000000";
|
||||
set page_title_color = "#9d0404";
|
||||
set page_subtitle_color = "#9d0404";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#aaaaaa";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#dddddd";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: classic/deepmelodrama
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Deep MeloDrama";
|
||||
layerinfo redist_uniq = "classic/deepmelodrama";
|
||||
set body_bgcolor = "#872d89";
|
||||
set main_bgcolor = "#719cff";
|
||||
set main_fgcolor = "#8e48b2";
|
||||
set comment_bar_one_bgcolor = "#3794b3";
|
||||
set comment_bar_one_fgcolor = "#84b8e7";
|
||||
set metabar_bgcolor = "#65b2c1";
|
||||
set metabar_fgcolor = "#f5d3ff";
|
||||
set page_title_color = "#8e48b2";
|
||||
set page_subtitle_color = "#65b2c1";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#dfd3ff";
|
||||
set comment_bar_one_bgcolor = "#3794b3";
|
||||
set comment_bar_one_fgcolor = "#84b8e7";
|
||||
set comment_bar_two_bgcolor = "#65b2c1";
|
||||
set comment_bar_two_fgcolor = "#f5d3ff";
|
||||
|
||||
#NEWLAYER: classic/everwhite
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Everwhite";
|
||||
layerinfo redist_uniq = "classic/everwhite";
|
||||
set body_bgcolor = "#ffffff";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set comment_bar_one_bgcolor = "#ffffff";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set metabar_bgcolor = "#ffffff";
|
||||
set metabar_fgcolor = "#000000";
|
||||
set page_title_color = "#000000";
|
||||
set page_subtitle_color = "#ff0000";
|
||||
set link_color = "#e60000";
|
||||
set vlink_color = "#c10602";
|
||||
set alink_color = "#ff0600";
|
||||
set comment_bar_one_bgcolor = "#ffffff";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#ffffff";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: classic/everblue
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Everblue with Greys";
|
||||
layerinfo redist_uniq = "classic/everblue";
|
||||
set body_bgcolor = "#0f0c6d";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set headerbar_bgcolor = "#000000";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set metabar_bgcolor = "#aaaaaa";
|
||||
set metabar_fgcolor = "#000000";
|
||||
set page_title_color = "#000000";
|
||||
set page_subtitle_color = "#aaaaaa";
|
||||
set link_color = "#2f00f2";
|
||||
set vlink_color = "#060667";
|
||||
set alink_color = "#6691ff";
|
||||
set comment_bar_one_bgcolor = "#000000";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#aaaaaa";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: classic/brownleather
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Brown Leather Coat";
|
||||
layerinfo redist_uniq = "classic/brownleather";
|
||||
set body_bgcolor = "#d2b48c";
|
||||
set main_bgcolor = "#ffebcd";
|
||||
set main_fgcolor = "#8b4513";
|
||||
set headerbar_bgcolor = "#d48050";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set metabar_bgcolor = "#d48014";
|
||||
set metabar_fgcolor = "#d48014";
|
||||
set page_title_color = "#d48014";
|
||||
set page_subtitle_color = "#ffe1a1";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#867a55";
|
||||
set alink_color = "#fffab3";
|
||||
set comment_bar_one_bgcolor = "#d48014";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#d48050";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: classic/bruise
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Bruise";
|
||||
layerinfo redist_uniq = "classic/bruise";
|
||||
set body_bgcolor = "#000000";
|
||||
set main_bgcolor = "#bcbcbc";
|
||||
set main_fgcolor = "#000000";
|
||||
set headerbar_bgcolor = "#1114a0";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set metabar_bgcolor = "#21c2f1";
|
||||
set metabar_fgcolor = "#ffffff";
|
||||
set page_title_color = "#1114a0";
|
||||
set page_subtitle_color = "#21c2f1";
|
||||
set link_color = "#0000cc";
|
||||
set vlink_color = "#000088";
|
||||
set alink_color = "#0000ff";
|
||||
set comment_bar_one_bgcolor = "#1114a0";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#21c2f1";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: classic/ranchhand
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Ranch Hand";
|
||||
layerinfo redist_uniq = "classic/ranchhand";
|
||||
set body_bgcolor = "#2999c2";
|
||||
set main_bgcolor = "#cfe0ff";
|
||||
set main_fgcolor = "#000000";
|
||||
set headerbar_bgcolor = "#54442c";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set metabar_bgcolor = "#bababa";
|
||||
set metabar_fgcolor = "#000000";
|
||||
set page_title_color = "#9d995d";
|
||||
set page_subtitle_color = "#704400";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#6a20ff";
|
||||
set comment_bar_one_bgcolor = "#54442c";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#bababa";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: classic/victim
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Victim";
|
||||
layerinfo redist_uniq = "classic/victim";
|
||||
set body_bgcolor = "#2cd0ff";
|
||||
set main_bgcolor = "#505050";
|
||||
set main_fgcolor = "#ffffff";
|
||||
set headerbar_bgcolor = "#166bac";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set metabar_bgcolor = "#2098f3";
|
||||
set metabar_fgcolor = "#ffffff";
|
||||
set page_title_color = "#26b6ff";
|
||||
set page_subtitle_color = "#353535";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#166bac";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#2098f3";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: classic/forest
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Forest";
|
||||
layerinfo redist_uniq = "classic/forest";
|
||||
set body_bgcolor = "#778e64";
|
||||
set main_bgcolor = "#9b9ba5";
|
||||
set main_fgcolor = "#000000";
|
||||
set headerbar_bgcolor = "#72784c";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set metabar_bgcolor = "#72781c";
|
||||
set metabar_fgcolor = "#ffffff";
|
||||
set page_title_color = "#a0ac62";
|
||||
set page_subtitle_color = "#73777a";
|
||||
set link_color = "#3811e1";
|
||||
set vlink_color = "#310cbb";
|
||||
set alink_color = "#4e7bef";
|
||||
set comment_bar_one_bgcolor = "#72784c";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#72781c";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: classic/drone
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Drone";
|
||||
layerinfo redist_uniq = "classic/drone";
|
||||
set body_bgcolor = "#395f82";
|
||||
set main_bgcolor = "#f9fcfe";
|
||||
set main_fgcolor = "#000000";
|
||||
set headerbar_bgcolor = "#904094";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set metabar_bgcolor = "#f56efc";
|
||||
set metabar_fgcolor = "#ffffff";
|
||||
set page_title_color = "#ff93ff";
|
||||
set page_subtitle_color = "#eeeeff";
|
||||
set link_color = "#395f82";
|
||||
set vlink_color = "#395f82";
|
||||
set alink_color = "#5266ce";
|
||||
set comment_bar_one_bgcolor = "#904094";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#f56efc";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: classic/lowercurtain
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Lower the Curtain";
|
||||
layerinfo redist_uniq = "classic/lowercurtain";
|
||||
set body_bgcolor = "#000000";
|
||||
set main_bgcolor = "#6b6b6b";
|
||||
set main_fgcolor = "#ffffff";
|
||||
set headerbar_bgcolor = "#363636";
|
||||
set headerbar_fgcolor = "#f0f5fb";
|
||||
set metabar_bgcolor = "#c6c6c6";
|
||||
set metabar_fgcolor = "#222222";
|
||||
set page_title_color = "#363636";
|
||||
set page_subtitle_color = "#c5c8ca";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#3314ba";
|
||||
set comment_bar_one_bgcolor = "#363636";
|
||||
set comment_bar_one_fgcolor = "#f0f5fb";
|
||||
set comment_bar_two_bgcolor = "#c6c6c6";
|
||||
set comment_bar_two_fgcolor = "#222222";
|
||||
|
||||
#NEWLAYER: classic/sunny
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Sunny Day";
|
||||
layerinfo redist_uniq = "classic/sunny";
|
||||
set body_bgcolor = "#55e0f9";
|
||||
set main_bgcolor = "#e38202";
|
||||
set main_fgcolor = "#ffffff";
|
||||
set headerbar_bgcolor = "#fff500";
|
||||
set headerbar_fgcolor = "#e38202";
|
||||
set metabar_bgcolor = "#fff5c5";
|
||||
set metabar_fgcolor = "#e38202";
|
||||
set page_title_color = "#efe052";
|
||||
set page_subtitle_color = "#ffba03";
|
||||
set link_color = "#df0d12";
|
||||
set vlink_color = "#ac1b25";
|
||||
set alink_color = "#fe3b3b";
|
||||
set comment_bar_one_bgcolor = "#fff500";
|
||||
set comment_bar_one_fgcolor = "#e38202";
|
||||
set comment_bar_two_bgcolor = "#fff5c5";
|
||||
set comment_bar_two_fgcolor = "#e38202";
|
||||
|
||||
#NEWLAYER: classic/valentine
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Be Mine";
|
||||
layerinfo redist_uniq = "classic/valentine";
|
||||
set body_bgcolor = "#6f104a";
|
||||
set main_bgcolor = "#f2bce9";
|
||||
set main_fgcolor = "#000000";
|
||||
set headerbar_bgcolor = "#ff37ff";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set metabar_bgcolor = "#df2096";
|
||||
set metabar_fgcolor = "#ffffff";
|
||||
set page_title_color = "#ae1774";
|
||||
set page_subtitle_color = "#df2096";
|
||||
set link_color = "#ffffff";
|
||||
set vlink_color = "#a51014";
|
||||
set alink_color = "#ed8188";
|
||||
set comment_bar_one_bgcolor = "#ff37ff";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#df2096";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: classic/stripes
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Stripes";
|
||||
layerinfo redist_uniq = "classic/stripes";
|
||||
set body_bgcolor = "#ffffff";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set headerbar_bgcolor = "#e7212a";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set metabar_bgcolor = "#ffffff";
|
||||
set metabar_fgcolor = "#000000";
|
||||
set page_title_color = "#ffffff";
|
||||
set page_subtitle_color = "#ffcfdc";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ffafc1";
|
||||
set comment_bar_one_bgcolor = "#e7212a";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#ffffff";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
BIN
livejournal/bin/upgrading/s2layers/cleansimple/cleansimple.jpg
Executable file
|
After Width: | Height: | Size: 20 KiB |
11
livejournal/bin/upgrading/s2layers/cleansimple/en.s2
Executable file
@@ -0,0 +1,11 @@
|
||||
# -*-s2-*-
|
||||
|
||||
layerinfo type = "i18n";
|
||||
layerinfo name = "English";
|
||||
layerinfo redist_uniq = "cleansimple/en";
|
||||
|
||||
set text_meta_music = "music";
|
||||
set text_meta_mood = "mood";
|
||||
|
||||
set text_post_comment = "Comment on this";
|
||||
set text_post_comment_friends = "Comment on this";
|
||||
932
livejournal/bin/upgrading/s2layers/cleansimple/layout.s2
Executable file
@@ -0,0 +1,932 @@
|
||||
# -*-s2-*-
|
||||
|
||||
layerinfo type = "layout";
|
||||
layerinfo name = "Clean and Simple";
|
||||
layerinfo redist_uniq = "cleansimple/layout";
|
||||
layerinfo author_name = "Martin Atkins";
|
||||
layerinfo previews = "cleansimple/cleansimple.jpg";
|
||||
|
||||
propgroup colors {
|
||||
property Color body_bgcolor {
|
||||
des = "Page border color";
|
||||
note = "If you set the border size to 'None', this won't show up.";
|
||||
s1color = "stronger_back";
|
||||
}
|
||||
property Color entry_bgcolor {
|
||||
des = "Background of entries";
|
||||
s1color = "page_back";
|
||||
}
|
||||
property Color entry_fgcolor {
|
||||
des = "Text color of entries";
|
||||
s1color = "page_text";
|
||||
}
|
||||
property Color meta_color {
|
||||
des = "Color of entry headings and meta-information";
|
||||
s1color = "page_text_em";
|
||||
}
|
||||
property Color link_color {
|
||||
des = "Link color";
|
||||
s1color = "page_link";
|
||||
}
|
||||
property Color vlink_color {
|
||||
des = "Visited link color";
|
||||
s1color = "page_vlink";
|
||||
}
|
||||
property Color alink_color {
|
||||
des = "Active link color";
|
||||
s1color = "page_alink";
|
||||
}
|
||||
property Color topbar_bgcolor {
|
||||
des = "Background color of titlebar and userpic";
|
||||
s1color = "strong_back";
|
||||
}
|
||||
property Color topbar_fgcolor {
|
||||
des = "Titlebar text color";
|
||||
s1color = "strong_text";
|
||||
}
|
||||
property Color navbar_bgcolor {
|
||||
des = "Background color of sidebar";
|
||||
s1color = "weak_back";
|
||||
}
|
||||
property Color navbar_fgcolor {
|
||||
des = "Sidebar text color";
|
||||
s1color = "weak_text";
|
||||
}
|
||||
property string opt_navbar_pos {
|
||||
des = "Side Navbar Position";
|
||||
values = "left|Left|right|Right";
|
||||
}
|
||||
property Color comment_bar_one_bgcolor {
|
||||
des = "Alternating background color for comment bars (one)";
|
||||
}
|
||||
property Color comment_bar_two_fgcolor {
|
||||
des = "Text color on alternating comment bars (one)";
|
||||
}
|
||||
property Color comment_bar_two_bgcolor {
|
||||
des = "Alternating background color for comment bars (two)";
|
||||
}
|
||||
property Color comment_bar_one_fgcolor {
|
||||
des = "Text color on alternating comment bars (two)";
|
||||
}
|
||||
property Color comment_bar_screened_bgcolor {
|
||||
des = "Background bar color for screened comments";
|
||||
}
|
||||
property Color comment_bar_screened_fgcolor {
|
||||
des = "Text color on background bar for screened comments";
|
||||
}
|
||||
}
|
||||
set body_bgcolor = "#6666cc";
|
||||
set entry_bgcolor = "#ffffff";
|
||||
set entry_fgcolor = "#000000";
|
||||
set meta_color = "#c00000";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#00ffff";
|
||||
set topbar_bgcolor = "#c0c0ff";
|
||||
set topbar_fgcolor = "#000000";
|
||||
set navbar_bgcolor = "#eeeeff";
|
||||
set navbar_fgcolor = "#000000";
|
||||
set comment_bar_one_bgcolor = "#c0c0ff";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#eeeeff";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
set comment_bar_screened_bgcolor = "#dddddd";
|
||||
set comment_bar_screened_fgcolor = "#000000";
|
||||
set tags_aware = true;
|
||||
|
||||
propgroup fonts {
|
||||
property use font_base;
|
||||
property use font_fallback;
|
||||
property string font_topbar_base {
|
||||
des = "Preferred font for top bar";
|
||||
note = "As with the main font, leave blank if you don't care.";
|
||||
}
|
||||
property string font_topbar_fallback {
|
||||
des = "Alternative font style for top bar";
|
||||
values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default";
|
||||
}
|
||||
property string font_sidebar_base {
|
||||
des = "Preferred font for side navigation bar";
|
||||
note = "As with the main font, leave blank if you don't care.";
|
||||
}
|
||||
property string font_sidebar_fallback {
|
||||
des = "Alternative font style for side navigation bar";
|
||||
values = "sans-serif|Sans-serif|serif|Serif|cursive|Cursive|monospace|Monospaced|none|Use browser's default";
|
||||
}
|
||||
}
|
||||
set font_topbar_fallback = "none";
|
||||
set font_sidebar_fallback = "none";
|
||||
|
||||
propgroup presentation {
|
||||
property string opt_daylines_style {
|
||||
des = "Style of Lines Around Day Headings";
|
||||
values = "solid|Solid|dashed|Dashed|dotted|Dotted|double|Double|hidden|Invisible";
|
||||
}
|
||||
property use page_recent_items;
|
||||
property use page_friends_items;
|
||||
property string opt_margin_size {
|
||||
des = "Size of page border";
|
||||
values = "0|None|5px|Tiny|25px|Small|50px|Medium|75px|Large|100px|Extra Large";
|
||||
}
|
||||
property use view_entry_disabled;
|
||||
property use use_shared_pic;
|
||||
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 linklist_support;
|
||||
property use external_stylesheet;
|
||||
}
|
||||
set opt_navbar_pos = "left";
|
||||
set opt_daylines_style = "dashed";
|
||||
set opt_margin_size = "50px";
|
||||
set view_entry_disabled = false;
|
||||
set show_entrynav_icons = true;
|
||||
set page_background_image = "";
|
||||
set linklist_support = false;
|
||||
|
||||
propgroup text {
|
||||
property use text_post_comment;
|
||||
property use text_read_comments;
|
||||
property use text_post_comment_friends;
|
||||
property use text_read_comments_friends;
|
||||
}
|
||||
|
||||
function css_fontspec(string base, string fallback)
|
||||
"Prints a CSS font-family specification based on the base and fallback given"
|
||||
{
|
||||
if ($base != "" or $fallback != "none") {
|
||||
"font-family: ";
|
||||
if ($base != "") {
|
||||
"\"$base\"";
|
||||
if ($fallback != "none") {
|
||||
", ";
|
||||
}
|
||||
}
|
||||
if ($fallback != "none") {
|
||||
print $fallback;
|
||||
}
|
||||
";";
|
||||
}
|
||||
}
|
||||
|
||||
function print_stylesheet ()
|
||||
{
|
||||
var string bgimg = clean_url($*page_background_image) != "" ? "url($*page_background_image)" : "none";
|
||||
"""
|
||||
body {
|
||||
background: $*body_bgcolor $bgimg;
|
||||
color: $*entry_fgcolor;
|
||||
padding: $*opt_margin_size;
|
||||
margin: 0;
|
||||
""";
|
||||
css_fontspec($*font_base,$*font_fallback);
|
||||
"""
|
||||
}
|
||||
a:link {
|
||||
color: $*link_color;
|
||||
background: transparent;
|
||||
}
|
||||
a:visited {
|
||||
color: $*vlink_color;
|
||||
background: transparent;
|
||||
}
|
||||
a:active {
|
||||
color: $*alink_color;
|
||||
background: transparent;
|
||||
}
|
||||
img {
|
||||
vertical-align: absmiddle;
|
||||
}
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
pre {
|
||||
text-align: left;
|
||||
}
|
||||
#topbar {
|
||||
background: $*topbar_bgcolor none;
|
||||
color: $*topbar_fgcolor;
|
||||
""";
|
||||
css_fontspec($*font_topbar_base,$*font_topbar_fallback);
|
||||
"""
|
||||
}
|
||||
#topbar h1 {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 0;
|
||||
text-align: center;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
#topbar h2 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 5px;
|
||||
text-align: center;
|
||||
font-size: 1.25em;
|
||||
}
|
||||
#navbar {
|
||||
background: $*navbar_bgcolor none;
|
||||
color: $*navbar_fgcolor;
|
||||
width: 25%;
|
||||
""";
|
||||
css_fontspec($*font_sidebar_base,$*font_sidebar_fallback);
|
||||
"""
|
||||
}
|
||||
#navbar ul {
|
||||
list-style: none;
|
||||
margin: 10px;
|
||||
}
|
||||
#navbar ul li {
|
||||
margin: 0;
|
||||
}
|
||||
#navbar ul li.active {
|
||||
font-weight: bold;
|
||||
}
|
||||
#navbar a:link, #navbar a:active, #navbar a:visited {
|
||||
background: $*navbar_bgcolor none;
|
||||
color: $*navbar_fgcolor;
|
||||
text-decoration: none;
|
||||
}
|
||||
#navbar a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
#userlinklist ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
#mainstuff {
|
||||
width: 75%;
|
||||
background: $*entry_bgcolor none;
|
||||
color: $*entry_fgcolor;
|
||||
}
|
||||
#userpic {
|
||||
text-align: center;
|
||||
margin: 10px;
|
||||
}
|
||||
#userpic img {
|
||||
border: 2px solid $*topbar_bgcolor;
|
||||
background: $*topbar_bgcolor none;
|
||||
color: $*topbar_fgcolor;
|
||||
}
|
||||
#entries {
|
||||
margin: 10px;
|
||||
}
|
||||
#range {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
.day {
|
||||
border-top: 1px $*opt_daylines_style $*entry_fgcolor;
|
||||
clear: both;
|
||||
}
|
||||
.day h3 {
|
||||
border-bottom: 1px $*opt_daylines_style $*entry_fgcolor;
|
||||
padding: 2px;
|
||||
margin: 0;
|
||||
font-size: 1.1em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
address {
|
||||
text-align: center;
|
||||
font-style: normal;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
/* entries */
|
||||
.entrytext {
|
||||
padding: 2px;
|
||||
text-align: justify;
|
||||
}
|
||||
.entry {
|
||||
clear: both;
|
||||
}
|
||||
.entrytext p, .entrytext ul, .entrytext ol, .entrytext table {
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
.entryheading {
|
||||
font-weight: bold;
|
||||
}
|
||||
.timestamp, .subject, .altposter {
|
||||
font-weight: bold;
|
||||
color: $*meta_color;
|
||||
background: $*entry_bgcolor;
|
||||
}
|
||||
.altposter a {
|
||||
color: $*meta_color;
|
||||
background: $*entry_bgcolor;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.altposter img {
|
||||
border: 2px $*navbar_fgcolor solid;
|
||||
background: $*navbar_bgcolor none;
|
||||
color: $*navbar_fgcolor;
|
||||
}
|
||||
.talklinks {
|
||||
font-size: 0.75em;
|
||||
text-align: right;
|
||||
margin-bottom: 2px;
|
||||
clear: right;
|
||||
}
|
||||
.frienduserpic {
|
||||
border: 2px solid $*topbar_bgcolor;
|
||||
background: $*topbar_bgcolor none;
|
||||
color: $*topbar_fgcolor;
|
||||
}
|
||||
""";
|
||||
}
|
||||
|
||||
function Page::lay_viewspec_nav() {
|
||||
# Intentionally blank
|
||||
}
|
||||
function RecentPage::lay_viewspec_nav() {
|
||||
# FIXME: There is currently no decent way to i18nize this
|
||||
if ($.nav.forward_url != "" or $.nav.backward_url != "") {
|
||||
"<ul id=\"skiplinks\">";
|
||||
if ($.nav.forward_url != "") {
|
||||
println """<li><a href="$.nav.forward_url">Next</a></li>""";
|
||||
}
|
||||
if ($.nav.backward_url != "") {
|
||||
println """<li><a href="$.nav.backward_url">Previous</a></li>""";
|
||||
}
|
||||
"</ul>";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# This DEFINITELY should be in core
|
||||
function Page::lay_view_name(string view) : string
|
||||
"Don't bother overriding this, because it'll be deleted as soon as core can do it" {
|
||||
if ($view == "recent") {
|
||||
return $*text_view_recent;
|
||||
} elseif ($view == "friends") {
|
||||
return $*text_view_friends;
|
||||
} elseif ($view == "userinfo") {
|
||||
return $*text_view_userinfo;
|
||||
} elseif ($view == "archive") {
|
||||
return $*text_view_archive;
|
||||
} else {
|
||||
return "Something";
|
||||
}
|
||||
}
|
||||
|
||||
function Page::lay_viewspec_heading() : string
|
||||
"Returns some text to display under the main heading. Overridden in subclasses." {
|
||||
return "";
|
||||
}
|
||||
function RecentPage::lay_viewspec_heading() : string {
|
||||
return $*text_view_recent;
|
||||
}
|
||||
function FriendsPage::lay_viewspec_heading() : string {
|
||||
if ($.journal.journal_type == "C") {
|
||||
return $*text_view_friends_comm;
|
||||
} else {
|
||||
return $*text_view_friends;
|
||||
}
|
||||
}
|
||||
function DayPage::lay_viewspec_heading() : string {
|
||||
return $*text_view_archive;
|
||||
}
|
||||
function YearPage::lay_viewspec_heading() : string {
|
||||
return $*text_view_archive;
|
||||
}
|
||||
function MonthPage::lay_viewspec_heading() : string {
|
||||
return $*text_view_archive;
|
||||
}
|
||||
|
||||
function Page::print_linklist() {
|
||||
if (size $.linklist <= 0) {
|
||||
return;
|
||||
} elseif (not $*linklist_support) {
|
||||
return;
|
||||
}
|
||||
|
||||
var bool section_open = false;
|
||||
|
||||
println "<ul id='userlinklist'>";
|
||||
foreach var UserLink l ($.linklist) {
|
||||
if ($l.title) {
|
||||
if ($l.is_heading) {
|
||||
if ($section_open) {
|
||||
println "</ul></li>";
|
||||
}
|
||||
println """<li><span style="font-style: italic;">$l.title</span>\n<ul>""";
|
||||
$section_open = true;
|
||||
} else {
|
||||
println """<li><a href="$l.url">$l.title</a></li>""";
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($section_open) {
|
||||
println "</ul></li>";
|
||||
}
|
||||
println "</ul>";
|
||||
}
|
||||
|
||||
|
||||
function Page::lay_print_navbar() {
|
||||
var string userpic;
|
||||
var Image up_img = $.journal.default_pic;
|
||||
if (defined $up_img) {
|
||||
$userpic = """<div id="userpic"><img border="0" src="$up_img.url" height="$up_img.height" width="$up_img.width" alt="" /></div>""";
|
||||
}
|
||||
var string website_name = $.journal.website_name ? $.journal.website_name : $*text_website_default_name;
|
||||
var string website;
|
||||
if ($.journal.website_url != "") {
|
||||
$website = """<li><a href="$.journal.website_url">$website_name</a></li>""";
|
||||
}
|
||||
|
||||
"""<td id="navbar" valign="top">
|
||||
|
||||
<ul id="viewlinks">
|
||||
""";
|
||||
|
||||
foreach var string v ($.views_order) {
|
||||
if ($v == $.view) {
|
||||
println """<li class="active">"""+
|
||||
$this->lay_view_name($v)+
|
||||
"""</li>""";
|
||||
} else {
|
||||
println """<li><a href="$.view_url{$v}">"""+
|
||||
$this->lay_view_name($v)+
|
||||
"""</a></li>""";
|
||||
}
|
||||
}
|
||||
|
||||
"""
|
||||
$website
|
||||
</ul>
|
||||
""";
|
||||
$this->lay_viewspec_nav();
|
||||
"$userpic";
|
||||
|
||||
$this->print_linklist();
|
||||
|
||||
"</td>";
|
||||
}
|
||||
|
||||
function Page::print ()
|
||||
{
|
||||
var string title = $this->title();
|
||||
|
||||
"""<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>
|
||||
<table border="0" cellpadding="0" cellspacing="0">
|
||||
<tr><td colspan="2" id="topbar" valign="top">
|
||||
""";
|
||||
|
||||
"<h1>$.journal.name</h1>";
|
||||
"<h2>" + $this->lay_viewspec_heading() + "</h2>";
|
||||
|
||||
"""
|
||||
</td></tr>
|
||||
|
||||
<tr>
|
||||
""";
|
||||
|
||||
if ($*opt_navbar_pos == "left") {
|
||||
$this->lay_print_navbar();
|
||||
}
|
||||
|
||||
"""<td id="mainstuff" valign="top">
|
||||
<div id="entries">
|
||||
""";
|
||||
|
||||
$this->print_body();
|
||||
|
||||
"""
|
||||
</div>
|
||||
|
||||
<address>"""; server_sig(); """</address>
|
||||
|
||||
</td>
|
||||
""";
|
||||
|
||||
if ($*opt_navbar_pos == "right") {
|
||||
$this->lay_print_navbar();
|
||||
}
|
||||
|
||||
"""</tr>
|
||||
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
""";
|
||||
}
|
||||
|
||||
function print_entry (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text)
|
||||
{
|
||||
var string time = $e.time->time_format();
|
||||
if ($e.new_day) {
|
||||
"""<div class="day"><h3>"""+$e.time->date_format("long")+"</h3>";
|
||||
}
|
||||
"""<div class="entry" id="entry$e.itemid"><div class="entrytext">""";
|
||||
|
||||
if ($p.view == "entry" and $*show_entrynav_icons)
|
||||
{
|
||||
print "<div style='text-align: center'>";
|
||||
$e->print_linkbar();
|
||||
print "</div>";
|
||||
}
|
||||
|
||||
"""<span class="entryheading">""";
|
||||
|
||||
if ($p.view == "friends") {
|
||||
if ($e.poster.username != $e.journal.username) {
|
||||
"<span class=\"altposter\"><a href=\"";
|
||||
print get_url($e.poster,"userinfo");
|
||||
"\">"+$e.poster.username;
|
||||
"</a></span>, posting in ";
|
||||
}
|
||||
|
||||
"<a style=\"color: $fgcolor; background: $bgcolor; padding-left: 0.5em; padding-right: 0.5em;\"";
|
||||
" href=\""+get_url($e.journal,"userinfo")+"\">$e.journal.username</a> @ ";
|
||||
} else {
|
||||
if ($e.poster.username != $e.journal.username) {
|
||||
"<span class=\"altposter\">";
|
||||
if (defined $e.userpic) {
|
||||
"""<img src="$e.userpic.url" width="$e.userpic.width"
|
||||
height="$e.userpic.height" alt="" align="right" />""";
|
||||
}
|
||||
"<a href=\""+
|
||||
get_url($e.poster,"userinfo")+
|
||||
"\">$e.poster.username</a></span> @ ";
|
||||
}
|
||||
}
|
||||
"<span class=\"timestamp\">"+$e.time->time_format()+"</span>: ";
|
||||
|
||||
if ($e.security) {
|
||||
$e.security_icon->print();
|
||||
}
|
||||
if ($e.subject) {
|
||||
" <span class=\"subject\">$e.subject</span>";
|
||||
}
|
||||
println "</span>"+($e.subject != "" ? "<br />" : "");
|
||||
|
||||
if ($p.view == "friends" and defined $e.userpic) {
|
||||
"""<img src="$e.userpic.url" width="$e.userpic.width"
|
||||
style="color: $fgcolor; background: $bgcolor; border: 2px solid $bgcolor;"
|
||||
height="$e.userpic.height" alt="" align="right" class="frienduserpic" />""";
|
||||
}
|
||||
|
||||
if (not $hide_text) {
|
||||
print "$e.text<br /><br />";
|
||||
if (size $e.metadata) {
|
||||
"""<div class="currents">""";
|
||||
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='absmiddle'> $val";
|
||||
}
|
||||
"""<div class="current$k"><strong>$text:</strong> $val</div>""";
|
||||
}
|
||||
"</div>\n";
|
||||
}
|
||||
if ($e.tags) {
|
||||
var int tcount = 0;
|
||||
"<strong>Tags:</strong> ";
|
||||
foreach var Tag t ($e.tags) {
|
||||
"""<a rel="tag" href="$t.url">$t.name</a>""";
|
||||
$tcount++;
|
||||
if ($tcount != size $e.tags) { ", "; }
|
||||
}
|
||||
"<br />";
|
||||
}
|
||||
}
|
||||
|
||||
$e.comments->print(); "\n";
|
||||
|
||||
"</div>";
|
||||
|
||||
if ($e.end_day) {
|
||||
"</div>";
|
||||
}
|
||||
}
|
||||
|
||||
function Page::print_entry (Entry e)
|
||||
{
|
||||
print_entry($this, $e, null Color, null Color, false);
|
||||
}
|
||||
|
||||
function FriendsPage::print_entry (Entry e) {
|
||||
var Friend f = $.friends{$e.journal.username};
|
||||
print_entry($this, $e, $f.bgcolor, $f.fgcolor, false);
|
||||
}
|
||||
|
||||
function CommentInfo::print ()
|
||||
{
|
||||
if (not $.enabled) { return; }
|
||||
"""<div class="talklinks" clear="all">""";
|
||||
if ($.count > 0 or $.screened) {
|
||||
$this->print_readlink();
|
||||
" - ";
|
||||
}
|
||||
$this->print_postlink();
|
||||
"</div>";
|
||||
}
|
||||
|
||||
# This should really be provided in core
|
||||
function RecentPage::lay_range_text() : string {
|
||||
if ($.nav.skip == 0) {
|
||||
return "You are viewing the most recent "+(size $.entries)+" entries";
|
||||
} else {
|
||||
return "You are viewing "+(size $.entries)+" entries, $.nav.skip into the past";
|
||||
}
|
||||
}
|
||||
|
||||
function RecentPage::print_body ()
|
||||
{
|
||||
"""<p id="range">"""+$this->lay_range_text()+"""</p>""";
|
||||
foreach var Entry e ($.entries) {
|
||||
$this->print_entry($e);
|
||||
}
|
||||
}
|
||||
|
||||
function YearPage::print_year_links ()
|
||||
{
|
||||
"""<ul id="skiplinks">""";
|
||||
foreach var YearYear y ($.years) {
|
||||
if ($y.displayed) {
|
||||
println "<li class=\"active\">$y.year</span>";
|
||||
} else {
|
||||
println "<li><a href=\"$y.url\">$y.year</a></li>";
|
||||
}
|
||||
}
|
||||
"</ul>";
|
||||
|
||||
}
|
||||
|
||||
function YearPage::print_month (YearMonth m)
|
||||
{
|
||||
if (not $m.has_entries) { return; }
|
||||
"""<center><table border="0" cellpadding="4" cellspacing="0" style="margin-top: 10px; margin-bottom: 10px;">""";
|
||||
"""<tr align="center"><td colspan="7" bgcolor="$*topbar_bgcolor"><font color="$*topbar_fgcolor">""";
|
||||
|
||||
"<b>"; print $m->month_format(); """</b> (<a href="$m.url">...</a>)</font></td></tr>""";
|
||||
|
||||
"""<tr align="center" bgcolor="$*navbar_bgcolor">""";
|
||||
|
||||
foreach var int d (weekdays()) {
|
||||
"""<td><font color="$*navbar_fgcolor">"""; print $*lang_dayname_short[$d]; "</td>\n";
|
||||
}
|
||||
|
||||
"</tr>";
|
||||
|
||||
foreach var YearWeek w ($m.weeks) {
|
||||
$w->print();
|
||||
}
|
||||
|
||||
"</table></center>";
|
||||
}
|
||||
|
||||
function YearPage::lay_viewspec_nav() {
|
||||
$this->print_year_links();
|
||||
}
|
||||
|
||||
function YearPage::print_body() {
|
||||
"<h3>$.year</h3>";
|
||||
foreach var YearMonth m ($.months) {
|
||||
$this->print_month($m);
|
||||
}
|
||||
}
|
||||
|
||||
function YearWeek::print () {
|
||||
"<tr>";
|
||||
if ($.pre_empty) { "<td colspan='$.pre_empty'> </td>"; }
|
||||
foreach var YearDay d ($.days) {
|
||||
"""<td valign="top"><b><font size="-1">$d.day</font></b>""";
|
||||
if ($d.num_entries) {
|
||||
"""<center><a href="$d.url">$d.num_entries</a></center>""";
|
||||
} else {
|
||||
"<center> </center>";
|
||||
}
|
||||
"</td>";
|
||||
}
|
||||
if ($.post_empty) { "<td colspan='$.post_empty'> </td>"; }
|
||||
"</tr>";
|
||||
}
|
||||
|
||||
function DayPage::lay_viewspec_nav() {
|
||||
"""
|
||||
<ul id="skiplinks">
|
||||
<li><a href="$.prev_url">$*text_day_prev</a></li>
|
||||
<li><a href="$.next_url">$*text_day_next</a></li>
|
||||
</ul>
|
||||
""";
|
||||
}
|
||||
|
||||
function DayPage::print_body() {
|
||||
|
||||
"""<div class="day"><h3>""" + $.date->date_format("long") + "</h3>";
|
||||
|
||||
if (not $.has_entries) {
|
||||
println $*text_noentries_day;
|
||||
}
|
||||
|
||||
foreach var Entry e ($.entries) {
|
||||
$this->print_entry($e);
|
||||
}
|
||||
println "</div>";
|
||||
}
|
||||
|
||||
function EntryPage::print_body () {
|
||||
|
||||
set_handler("unscreen_comment_#", [
|
||||
[ "style_bgcolor", "cmtbar#", "$*comment_bar_one_bgcolor", ],
|
||||
[ "style_color", "cmtbar#", "$*comment_bar_one_fgcolor", ],
|
||||
]);
|
||||
set_handler("screen_comment_#", [
|
||||
[ "style_bgcolor", "cmtbar#", "$*comment_bar_screened_bgcolor", ],
|
||||
[ "style_color", "cmtbar#", "$*comment_bar_screened_fgcolor", ],
|
||||
]);
|
||||
|
||||
print_entry($this, $.entry, null Color, null Color, $.viewing_thread);
|
||||
|
||||
if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0)
|
||||
{
|
||||
$this->print_multiform_start();
|
||||
"""<div class="day"><h3>Comments</h3></div>""";
|
||||
if ($.comment_pages.total_subitems > 0) {
|
||||
$.comment_pages->print();
|
||||
$this->print_comments($.comments);
|
||||
}
|
||||
if ($this.multiform_on) {
|
||||
"""<div class="day"><h3>Mass Action</h3></div>""";
|
||||
$this->print_multiform_actionline();
|
||||
$this->print_multiform_end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Clean style. Hate to clutter it up with this:
|
||||
function EntryPage::print_comment (Comment c) {
|
||||
var Color background; var Color color;
|
||||
if ($c.screened) {
|
||||
$background = $*comment_bar_screened_bgcolor;
|
||||
$color = $*comment_bar_screened_fgcolor;
|
||||
} elseif ($c.depth % 2) {
|
||||
$background = $*comment_bar_one_bgcolor;
|
||||
$color = $*comment_bar_one_fgcolor;
|
||||
} else {
|
||||
$background = $*comment_bar_two_bgcolor;
|
||||
$color = $*comment_bar_two_fgcolor;
|
||||
}
|
||||
var string poster = defined $c.poster ? $c.poster->as_string() : "<i>(Anonymous)</i>";
|
||||
var string sub_icon;
|
||||
if (defined $c.subject_icon) {
|
||||
$sub_icon = $c.subject_icon->as_string();
|
||||
}
|
||||
"<a name='$c.anchor'></a><div id='cmtbar$c.talkid' style='background-color: $background; color: $color; margin-top: 10px; width: 100%'>";
|
||||
"<table cellpadding='2' cellspacing='0' summary='0' style='width: 100%'><tr valign='top'>";
|
||||
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;
|
||||
}
|
||||
print "<td style='width: 102px'><img src='$c.userpic.url' width='$w' height='$h' alt='[User Picture]' /></td>";
|
||||
}
|
||||
|
||||
"<td style='width: 100%'><table style='width: 100%'><tr>";
|
||||
|
||||
### From, date, etc
|
||||
"<td align='left' style='width: 50%'>";
|
||||
print "<table>";
|
||||
print "<tr><th align='right'>From:</th><td>$poster</td></tr>\n";
|
||||
print "<tr><th align='right'>Date:</th><td style='white-space: nowrap'>";
|
||||
print $c.time->date_format("long") + " - " + $c.time->time_format() + "</td></tr>";
|
||||
if ($c.metadata{"poster_ip"}) { print "<tr><th align='right'>IP Address:</th><td>(" + $c.metadata{"poster_ip"} + ")</td></tr>"; }
|
||||
"</table></td>";
|
||||
|
||||
### Gadgets
|
||||
"<td align='right' style='width: 50%'>";
|
||||
if ($this.multiform_on) {
|
||||
" <label for='ljcomsel_$c.talkid'>$*text_multiform_check</label>";
|
||||
$c->print_multiform_check();
|
||||
}
|
||||
$c->print_linkbar();
|
||||
"</td></tr>";
|
||||
|
||||
### Subject / icon
|
||||
print "<tr valign='top'><td style='width: 50%'>";
|
||||
print (defined $c.subject_icon or $c.subject != "") ? "<h3>$c.subject_icon $c.subject</h3>" : "";
|
||||
print "</td>";
|
||||
|
||||
### Permalink
|
||||
print "<td style='width: 50%' align='right'><strong>(<a href='$c.permalink_url'>Link</a>)</strong></td></tr>";
|
||||
|
||||
print "</table></td></tr></table></div>";
|
||||
print "<div style='margin-left: 5px'>$c.text</div>";
|
||||
print "<div style='margin-top: 3px; font-size: smaller'>";
|
||||
if ($c.frozen) {
|
||||
print "(Replies frozen) ";
|
||||
} else {
|
||||
print "(<a href='$c.reply_url'>Reply to this</a>) ";
|
||||
}
|
||||
if ($c.parent_url != "") { "(<a href='$c.parent_url'>Parent</a>) "; }
|
||||
if ($c.thread_url != "") { "(<a href='$c.thread_url'>Thread</a>) "; }
|
||||
"</div>";
|
||||
}
|
||||
|
||||
function ReplyPage::print_body () {
|
||||
var string time = $.replyto.time->time_format();
|
||||
"""
|
||||
<div class="entry">
|
||||
<div class="entrytext">
|
||||
<span class="entryheading">
|
||||
""";
|
||||
|
||||
if (not $.entry.comments.enabled)
|
||||
{
|
||||
print "<span class='subject'>$*text_reply_nocomments_header</span></span><br />
|
||||
$*text_reply_nocomments</div></div>";
|
||||
return;
|
||||
}
|
||||
"<span style='padding-left: 0.5em; padding-right: 0.5em;'>";
|
||||
print defined $.replyto.poster ? $.replyto.poster->as_string() : "<i>(Anonymous)</i>";
|
||||
"</span> @ ";
|
||||
"<span class='timestamp'>$time</span>: ";
|
||||
|
||||
if ($.replyto.subject) {
|
||||
" <span class=\"subject\">$.replyto.subject</span>";
|
||||
}
|
||||
println "</span>"+($.replyto.subject ? "<br />" : "");
|
||||
|
||||
if (defined $.replyto.userpic) {
|
||||
"""<img src="$.replyto.userpic.url" width="$.replyto.userpic.width"
|
||||
style="border: 2px solid $*entry_fgcolor;"
|
||||
height="$.replyto.userpic.height" alt="" align="right" class="frienduserpic" />""";
|
||||
}
|
||||
|
||||
print $.replyto.text;
|
||||
|
||||
"""<div class="talklinks" clear="all"><a href='$.entry.comments.read_url'>Read Comments</a></div>""";
|
||||
|
||||
"</div>";
|
||||
|
||||
"""<div class="day"><h3>Reply</h3></div>""";
|
||||
$.form->print();
|
||||
|
||||
}
|
||||
|
||||
function print_theme_preview ()
|
||||
{
|
||||
print """
|
||||
<div style="background: $*body_bgcolor none; color: $*entry_fgcolor;
|
||||
padding-left: 50px; padding-right: 50px; padding-top: 10px;
|
||||
padding-bottom: 10px; margin: 0;">
|
||||
|
||||
<table border="0" cellpadding="0" cellspacing="0">
|
||||
<tr><td colspan="2" style="background: $*topbar_bgcolor none; color: $*topbar_fgcolor" valign="top">
|
||||
<h1 style="margin-top: 5px; margin-bottom: 5px; text-align: center; font-size: 1.5em;">John Doe</h1>
|
||||
<h2 style="margin-top: 0; margin-bottom: 5px; text-align: center; font-size: 1.25em;">Recent Entries</h2>
|
||||
</td></tr>
|
||||
<tr><td style="background: $*navbar_bgcolor none; color: $*navbar_fgcolor; width: 25%;" valign="top">
|
||||
<ul style="list-style: none; margin: 10px">
|
||||
<li style="margin: 0; font-weight: bold;">Recent Entries</li>
|
||||
<li><a style="background: $*navbar_bgcolor none; color: $*navbar_fgcolor;" href="#">Archive</a></li>
|
||||
<li><a style="background: $*navbar_bgcolor none; color: $*navbar_fgcolor;" href="#">Friends</a></li>
|
||||
<li><a style="background: $*navbar_bgcolor none; color: $*navbar_fgcolor;" href="#">User Info</a></li>
|
||||
</ul>
|
||||
</td><td style="width: 75%; background: $*entry_bgcolor none; color: $*entry_fgcolor" valign="top">
|
||||
<div style="margin: 10px;">
|
||||
<div style="border-top: 1px dashed $*entry_fgcolor; clear: both;">
|
||||
<h3 style="border-bottom: 1px dashed $*entry_fgcolor; padding: 2px; margin: 0; font-size: 1.1em; text-align: center;">December 17th, 2002</h3>
|
||||
<div style="clear: both;" id="entry2839"><div style="padding: 2px; text-align: justify">
|
||||
<span style="font-weight: bold;">
|
||||
<span style="font-weight: bold; color: $*meta_color; background: $*entry_bgcolor none;">06:42 pm</span>:
|
||||
<span style="font-weight: bold; color: $*meta_color; background: $*entry_bgcolor none;">Neque porro quisquam…</span>
|
||||
</span>
|
||||
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit
|
||||
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit
|
||||
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit
|
||||
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit
|
||||
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit
|
||||
<div style="font-size: 0.75em; text-align: right; margin-bottom: 2px; clear: right;" >
|
||||
<a href="#" style="color: $*link_color;">2 Comments Posted</a> | <a href="#" style="color: $*vlink_color">Leave a comment</a></div>
|
||||
</div></div></div></div>
|
||||
</td></tr></table>
|
||||
</div>
|
||||
""";
|
||||
}
|
||||
420
livejournal/bin/upgrading/s2layers/cleansimple/themes.s2
Executable file
@@ -0,0 +1,420 @@
|
||||
#NEWLAYER: cleansimple/purpleblues
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Purples and Blues";
|
||||
layerinfo redist_uniq = "cleansimple/purpleblues";
|
||||
set body_bgcolor = "#660099";
|
||||
set entry_bgcolor = "#9966cc";
|
||||
set entry_fgcolor = "#ffff00";
|
||||
set meta_color = "#003399";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#00ffff";
|
||||
set topbar_bgcolor = "#c0c0ff";
|
||||
set topbar_fgcolor = "#000000";
|
||||
set navbar_bgcolor = "#eeeeff";
|
||||
set navbar_fgcolor = "#000000";
|
||||
set comment_bar_one_bgcolor = "#c0c0ff";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#eeeeff";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: cleansimple/flesh
|
||||
layerinfo type = "theme";
|
||||
layerinfo name = "Flesh";
|
||||
layerinfo redist_uniq = "cleansimple/flesh";
|
||||
set body_bgcolor = "#eeeeff";
|
||||
set entry_bgcolor = "#ffffff";
|
||||
set entry_fgcolor = "#000000";
|
||||
set meta_color = "#ff0000";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#00ffff";
|
||||
set topbar_bgcolor = "#fa83d7";
|
||||
set topbar_fgcolor = "#000000";
|
||||
set navbar_bgcolor = "#f677ad";
|
||||
set navbar_fgcolor = "#000000";
|
||||
set comment_bar_one_bgcolor = "#fa83d7";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#f677ad";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: cleansimple/shrinkvio
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Shrinking Violet";
|
||||
layerinfo redist_uniq = "cleansimple/shrinkvio";
|
||||
set body_bgcolor = "#ad22e7";
|
||||
set entry_bgcolor = "#ffffff";
|
||||
set entry_fgcolor = "#000000";
|
||||
set meta_color = "#381a45";
|
||||
set topbar_bgcolor = "#5d0383";
|
||||
set topbar_fgcolor = "#ffffff";
|
||||
set navbar_bgcolor = "#d9a1f1";
|
||||
set navbar_fgcolor = "#000000";
|
||||
set link_color = "#2e053f";
|
||||
set vlink_color = "#611627";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#5d0383";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#d9a1f1";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: cleansimple/pistmint
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Pistachio Mint";
|
||||
layerinfo redist_uniq = "cleansimple/pistmint";
|
||||
set body_bgcolor = "#133422";
|
||||
set entry_bgcolor = "#a7c4b4";
|
||||
set entry_fgcolor = "#000000";
|
||||
set meta_color = "#096d36";
|
||||
set topbar_bgcolor = "#096d36";
|
||||
set topbar_fgcolor = "#ffffff";
|
||||
set navbar_bgcolor = "#094f36";
|
||||
set navbar_fgcolor = "#000000";
|
||||
set link_color = "#8afabc";
|
||||
set vlink_color = "#1da65a";
|
||||
set alink_color = "#f9f5f5";
|
||||
set comment_bar_one_bgcolor = "#096d36";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#094f36";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: cleansimple/mexicanfood
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Mexican Food";
|
||||
layerinfo redist_uniq = "cleansimple/mexicanfood";
|
||||
set body_bgcolor = "#ff0000";
|
||||
set entry_bgcolor = "#f8ff3e";
|
||||
set entry_fgcolor = "#f15601";
|
||||
set meta_color = "#f50701";
|
||||
set topbar_bgcolor = "#bdbf3e";
|
||||
set topbar_fgcolor = "#ff0000";
|
||||
set navbar_bgcolor = "#e15a18";
|
||||
set navbar_fgcolor = "#ffffff";
|
||||
set link_color = "#f49e08";
|
||||
set vlink_color = "#b05403";
|
||||
set alink_color = "#ff7405";
|
||||
set comment_bar_one_bgcolor = "#bdbf3e";
|
||||
set comment_bar_two_fgcolor = "#ff0000";
|
||||
set comment_bar_two_bgcolor = "#e15a18";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: cleansimple/ashfire
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Ash and Fire";
|
||||
layerinfo redist_uniq = "cleansimple/ashfire";
|
||||
set body_bgcolor = "#b5b5b5";
|
||||
set entry_bgcolor = "#ffb6af";
|
||||
set entry_fgcolor = "#000000";
|
||||
set meta_color = "#d90308";
|
||||
set topbar_bgcolor = "#e75454";
|
||||
set topbar_fgcolor = "#ffffff";
|
||||
set navbar_bgcolor = "#f06c88";
|
||||
set navbar_fgcolor = "#000000";
|
||||
set link_color = "#f70208";
|
||||
set vlink_color = "#b0161d";
|
||||
set alink_color = "#d70106";
|
||||
set comment_bar_one_bgcolor = "#e75454";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#f06c88";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: cleansimple/desktop
|
||||
# for layout: 13 (cleansimple/layout)
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Classic Desktop";
|
||||
layerinfo redist_uniq = "cleansimple/desktop";
|
||||
set body_bgcolor = "#00545c";
|
||||
set entry_bgcolor = "#ffffff";
|
||||
set entry_fgcolor = "#000000";
|
||||
set meta_color = "#000000";
|
||||
set topbar_bgcolor = "#ff7b05";
|
||||
set topbar_fgcolor = "#ffeddd";
|
||||
set navbar_bgcolor = "#ffeddd";
|
||||
set navbar_fgcolor = "#000000";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#5a76ff";
|
||||
set comment_bar_one_bgcolor = "#ff7b05";
|
||||
set comment_bar_one_fgcolor = "#ffeddd";
|
||||
set comment_bar_two_bgcolor = "#ffeddd";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: cleansimple/satinhandshake
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Satin Handshake";
|
||||
layerinfo redist_uniq = "cleansimple/satinhandshake";
|
||||
set body_bgcolor = "#480c0c";
|
||||
set entry_bgcolor = "#d06464";
|
||||
set entry_fgcolor = "#00001d";
|
||||
set meta_color = "#000000";
|
||||
set topbar_bgcolor = "#aaaaaa";
|
||||
set topbar_fgcolor = "#000000";
|
||||
set navbar_bgcolor = "#9d0404";
|
||||
set navbar_fgcolor = "#000000";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#aaaaaa";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#9d0404";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: cleansimple/deepmelodrama
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Deep MeloDrama";
|
||||
layerinfo redist_uniq = "cleansimple/deepmelodrama";
|
||||
set body_bgcolor = "#872d89";
|
||||
set entry_bgcolor = "#719cff";
|
||||
set entry_fgcolor = "#8e48b2";
|
||||
set meta_color = "#8e48b2";
|
||||
set topbar_bgcolor = "#3794b3";
|
||||
set topbar_fgcolor = "#84b8e7";
|
||||
set navbar_bgcolor = "#65b2c1";
|
||||
set navbar_fgcolor = "#f5d3ff";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#dfd3ff";
|
||||
set comment_bar_one_bgcolor = "#3794b3";
|
||||
set comment_bar_one_fgcolor = "#84b8e7";
|
||||
set comment_bar_two_bgcolor = "#65b2c1";
|
||||
set comment_bar_two_fgcolor = "#f5d3ff";
|
||||
|
||||
#NEWLAYER: cleansimple/everwhite
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Everwhite";
|
||||
layerinfo redist_uniq = "cleansimple/everwhite";
|
||||
set body_bgcolor = "#ffffff";
|
||||
set entry_bgcolor = "#ffffff";
|
||||
set entry_fgcolor = "#000000";
|
||||
set meta_color = "#000000";
|
||||
set topbar_bgcolor = "#ffffff";
|
||||
set topbar_fgcolor = "#000000";
|
||||
set navbar_bgcolor = "#ffffff";
|
||||
set navbar_fgcolor = "#000000";
|
||||
set link_color = "#e60000";
|
||||
set vlink_color = "#c10602";
|
||||
set alink_color = "#ff0600";
|
||||
set comment_bar_one_bgcolor = "#ffffff";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#ffffff";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: cleansimple/everblue
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Everblue with Greys";
|
||||
layerinfo redist_uniq = "cleansimple/everblue";
|
||||
set body_bgcolor = "#0f0c6d";
|
||||
set entry_bgcolor = "#ffffff";
|
||||
set entry_fgcolor = "#000000";
|
||||
set meta_color = "#000000";
|
||||
set topbar_bgcolor = "#000000";
|
||||
set topbar_fgcolor = "#ffffff";
|
||||
set navbar_bgcolor = "#aaaaaa";
|
||||
set navbar_fgcolor = "#000000";
|
||||
set link_color = "#2f00f2";
|
||||
set vlink_color = "#060667";
|
||||
set alink_color = "#6691ff";
|
||||
set comment_bar_one_bgcolor = "#000000";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#aaaaaa";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: cleansimple/brownleather
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Brown Leather Coat";
|
||||
layerinfo redist_uniq = "cleansimple/brownleather";
|
||||
set body_bgcolor = "#d2b48c";
|
||||
set entry_bgcolor = "#ffebcd";
|
||||
set entry_fgcolor = "#8b4513";
|
||||
set meta_color = "#000000";
|
||||
set topbar_bgcolor = "#d48014";
|
||||
set topbar_fgcolor = "#ffffff";
|
||||
set navbar_bgcolor = "#ffe1a1";
|
||||
set navbar_fgcolor = "#000000";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#867a55";
|
||||
set alink_color = "#fffab3";
|
||||
set comment_bar_one_bgcolor = "#d48014";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#ffe1a1";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: cleansimple/bruise
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Bruise";
|
||||
layerinfo redist_uniq = "cleansimple/bruise";
|
||||
set body_bgcolor = "#000000";
|
||||
set entry_bgcolor = "#bcbcbc";
|
||||
set entry_fgcolor = "#000000";
|
||||
set meta_color = "#000000";
|
||||
set topbar_bgcolor = "#1114a0";
|
||||
set topbar_fgcolor = "#ffffff";
|
||||
set navbar_bgcolor = "#21c2f1";
|
||||
set navbar_fgcolor = "#0000ff";
|
||||
set link_color = "#0000cc";
|
||||
set vlink_color = "#000088";
|
||||
set alink_color = "#0000ff";
|
||||
set comment_bar_one_bgcolor = "#1114a0";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#21c2f1";
|
||||
set comment_bar_two_fgcolor = "#0000ff";
|
||||
|
||||
#NEWLAYER: cleansimple/ranchhand
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Ranch Hand";
|
||||
layerinfo redist_uniq = "cleansimple/ranchhand";
|
||||
set body_bgcolor = "#2999c2";
|
||||
set entry_bgcolor = "#cfe0ff";
|
||||
set entry_fgcolor = "#000000";
|
||||
set meta_color = "#060667";
|
||||
set topbar_bgcolor = "#54442c";
|
||||
set topbar_fgcolor = "#ffffff";
|
||||
set navbar_bgcolor = "#704400";
|
||||
set navbar_fgcolor = "#bababa";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#6a20ff";
|
||||
set comment_bar_one_bgcolor = "#54442c";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#704400";
|
||||
set comment_bar_two_fgcolor = "#bababa";
|
||||
|
||||
#NEWLAYER: cleansimple/victim
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Victim";
|
||||
layerinfo redist_uniq = "cleansimple/victim";
|
||||
set body_bgcolor = "#2cd0ff";
|
||||
set entry_bgcolor = "#505050";
|
||||
set entry_fgcolor = "#ffffff";
|
||||
set meta_color = "#000000";
|
||||
set topbar_bgcolor = "#166bac";
|
||||
set topbar_fgcolor = "#ffffff";
|
||||
set navbar_bgcolor = "#353535";
|
||||
set navbar_fgcolor = "#ffffff";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#166bac";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#353535";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: cleansimple/forest
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Forest";
|
||||
layerinfo redist_uniq = "cleansimple/forest";
|
||||
set body_bgcolor = "#778e64";
|
||||
set entry_bgcolor = "#9b9ba5";
|
||||
set entry_fgcolor = "#000000";
|
||||
set meta_color = "#ffffff";
|
||||
set topbar_bgcolor = "#72784c";
|
||||
set topbar_fgcolor = "#ffffff";
|
||||
set navbar_bgcolor = "#73777a";
|
||||
set navbar_fgcolor = "#000000";
|
||||
set link_color = "#3811e1";
|
||||
set vlink_color = "#310cbb";
|
||||
set alink_color = "#4e7bef";
|
||||
set comment_bar_one_bgcolor = "#72784c";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#73777a";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: cleansimple/drone
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Drone";
|
||||
layerinfo redist_uniq = "cleansimple/drone";
|
||||
set body_bgcolor = "#395f82";
|
||||
set entry_bgcolor = "#f9fcfe";
|
||||
set entry_fgcolor = "#000000";
|
||||
set meta_color = "#000000";
|
||||
set topbar_bgcolor = "#904094";
|
||||
set topbar_fgcolor = "#ffffff";
|
||||
set navbar_bgcolor = "#eeeeff";
|
||||
set navbar_fgcolor = "#000000";
|
||||
set link_color = "#395f82";
|
||||
set vlink_color = "#395f82";
|
||||
set alink_color = "#5266ce";
|
||||
set comment_bar_one_bgcolor = "#904094";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#eeeeff";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: cleansimple/lowercurtain
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Lower the Curtain";
|
||||
layerinfo redist_uniq = "cleansimple/lowercurtain";
|
||||
set body_bgcolor = "#000000";
|
||||
set entry_bgcolor = "#6b6b6b";
|
||||
set entry_fgcolor = "#ffffff";
|
||||
set meta_color = "#ffffff";
|
||||
set topbar_bgcolor = "#363636";
|
||||
set topbar_fgcolor = "#f0f5fb";
|
||||
set navbar_bgcolor = "#c5c8ca";
|
||||
set navbar_fgcolor = "#000000";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#3314ba";
|
||||
set comment_bar_one_bgcolor = "#363636";
|
||||
set comment_bar_one_fgcolor = "#f0f5fb";
|
||||
set comment_bar_two_bgcolor = "#c5c8ca";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: cleansimple/sunny
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Sunny Day";
|
||||
layerinfo redist_uniq = "cleansimple/sunny";
|
||||
set body_bgcolor = "#55e0f9";
|
||||
set entry_bgcolor = "#e38202";
|
||||
set entry_fgcolor = "#ffffff";
|
||||
set meta_color = "#000000";
|
||||
set topbar_bgcolor = "#ffba03";
|
||||
set topbar_fgcolor = "#ffffff";
|
||||
set navbar_bgcolor = "#ffba55";
|
||||
set navbar_fgcolor = "#ffffff";
|
||||
set link_color = "#df0d12";
|
||||
set vlink_color = "#ac1b25";
|
||||
set alink_color = "#fe3b3b";
|
||||
set comment_bar_one_bgcolor = "#ffba03";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#ffba55";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: cleansimple/valentine
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Be Mine";
|
||||
layerinfo redist_uniq = "cleansimple/valentine";
|
||||
set body_bgcolor = "#6f104a";
|
||||
set entry_bgcolor = "#f2bce9";
|
||||
set entry_fgcolor = "#000000";
|
||||
set meta_color = "#ff24ab";
|
||||
set topbar_bgcolor = "#ff37ff";
|
||||
set topbar_fgcolor = "#ffffff";
|
||||
set navbar_bgcolor = "#df2096";
|
||||
set navbar_fgcolor = "#000000";
|
||||
set link_color = "#ffffff";
|
||||
set vlink_color = "#a51014";
|
||||
set alink_color = "#ed8188";
|
||||
set comment_bar_one_bgcolor = "#ff37ff";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#df2096";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: cleansimple/stripes
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Stripes";
|
||||
layerinfo redist_uniq = "cleansimple/stripes";
|
||||
set body_bgcolor = "#ffffff";
|
||||
set entry_bgcolor = "#ffffff";
|
||||
set entry_fgcolor = "#000000";
|
||||
set meta_color = "#ff0000";
|
||||
set topbar_bgcolor = "#e7212a";
|
||||
set topbar_fgcolor = "#ffffff";
|
||||
set navbar_bgcolor = "#ffcfdc";
|
||||
set navbar_fgcolor = "#000000";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ffafc1";
|
||||
set comment_bar_one_bgcolor = "#e7212a";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#ffcfdc";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
2020
livejournal/bin/upgrading/s2layers/core1.s2
Executable file
BIN
livejournal/bin/upgrading/s2layers/digitalmultiplex/digitalmultiplex.jpg
Executable file
|
After Width: | Height: | Size: 26 KiB |
10
livejournal/bin/upgrading/s2layers/digitalmultiplex/en.s2
Executable file
@@ -0,0 +1,10 @@
|
||||
# -*-s2-*-
|
||||
|
||||
layerinfo type = "i18n";
|
||||
layerinfo name = "English";
|
||||
layerinfo redist_uniq = "digitalmultiplex/en";
|
||||
|
||||
set text_meta_music = "Music";
|
||||
set text_meta_mood = "Mood";
|
||||
|
||||
set text_sidebar_link_separator = " » ";
|
||||
1379
livejournal/bin/upgrading/s2layers/digitalmultiplex/layout.s2
Executable file
17
livejournal/bin/upgrading/s2layers/generator/en.s2
Executable file
@@ -0,0 +1,17 @@
|
||||
# -*-s2-*-
|
||||
|
||||
layerinfo type = "i18n";
|
||||
layerinfo name = "English";
|
||||
layerinfo redist_uniq = "generator/en";
|
||||
|
||||
set text_meta_music = "music";
|
||||
set text_meta_mood = "mood";
|
||||
|
||||
set text_permalink = "link";
|
||||
|
||||
set text_post_comment = "post comment";
|
||||
set text_post_comment_friends = "post comment";
|
||||
|
||||
set text_read_comments = "1 comment // # comments";
|
||||
set text_read_comments_friends = "1 comment // # comments";
|
||||
|
||||
BIN
livejournal/bin/upgrading/s2layers/generator/generator.jpg
Executable file
|
After Width: | Height: | Size: 9.9 KiB |
945
livejournal/bin/upgrading/s2layers/generator/layout.s2
Executable file
@@ -0,0 +1,945 @@
|
||||
# -*-s2-*-
|
||||
layerinfo type = "layout";
|
||||
layerinfo name = "Generator";
|
||||
layerinfo redist_uniq = "generator/layout";
|
||||
layerinfo previews = "generator/generator.jpg";
|
||||
|
||||
propgroup colors {
|
||||
property Color entry_back {
|
||||
des = "Entry background";
|
||||
s1color = "page_back";
|
||||
}
|
||||
property Color entry_text {
|
||||
des = "Entry text color";
|
||||
s1color = "page_text";
|
||||
}
|
||||
property Color page_link {
|
||||
des = "Link color";
|
||||
s1color = "page_link";
|
||||
}
|
||||
property Color page_vlink {
|
||||
des = "Visited link color";
|
||||
s1color = "page_vlink";
|
||||
}
|
||||
property Color page_alink {
|
||||
des = "Active link color";
|
||||
s1color = "page_alink";
|
||||
}
|
||||
property Color page_back {
|
||||
des = "Page background color (and around userpics)";
|
||||
s1color = "strong_back";
|
||||
}
|
||||
property Color stronger_back {
|
||||
des = "Background color for the bar above entries";
|
||||
s1color = "strong_back";
|
||||
}
|
||||
property Color stronger_text {
|
||||
des = "Text color for the bar above entries";
|
||||
s1color = "stronger_text";
|
||||
}
|
||||
property Color weak_back {
|
||||
des = "Background color for the bar below entries";
|
||||
s1color = "weak_back";
|
||||
}
|
||||
property Color weak_text {
|
||||
des = "Text color for the bar below entries";
|
||||
s1color = "weak_text";
|
||||
}
|
||||
property Color comment_bar_one_bgcolor {
|
||||
des = "Alternating background color for comment bars (one)";
|
||||
}
|
||||
property Color comment_bar_two_fgcolor {
|
||||
des = "Text color on alternating comment bars (one)";
|
||||
}
|
||||
property Color comment_bar_two_bgcolor {
|
||||
des = "Alternating background color for comment bars (two)";
|
||||
}
|
||||
property Color comment_bar_one_fgcolor {
|
||||
des = "Text color on alternating comment bars (two)";
|
||||
}
|
||||
property Color comment_bar_screened_bgcolor {
|
||||
des = "Background bar color for screened comments";
|
||||
}
|
||||
property Color comment_bar_screened_fgcolor {
|
||||
des = "Text color on background bar for screened comments";
|
||||
}
|
||||
}
|
||||
|
||||
propgroup fonts {
|
||||
property use font_base;
|
||||
property use font_fallback;
|
||||
}
|
||||
|
||||
propgroup presentation {
|
||||
property use page_recent_items;
|
||||
property use page_friends_items;
|
||||
|
||||
property int box_width {
|
||||
des = "Box width (pixels)";
|
||||
}
|
||||
|
||||
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;
|
||||
property use linklist_support;
|
||||
}
|
||||
|
||||
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_website {
|
||||
des = "The label for the 'website' field";
|
||||
noui = 1;
|
||||
}
|
||||
}
|
||||
|
||||
# Set default colors
|
||||
set entry_back = "#ffffff";
|
||||
set entry_text = "#000000";
|
||||
set page_link = "#0000ff";
|
||||
set page_vlink = "#0000ff";
|
||||
set page_alink = "#00ffff";
|
||||
set page_back = "#2d4f89";
|
||||
set stronger_back = "#000000";
|
||||
set stronger_text = "#ffffff";
|
||||
set weak_back = "#aaaaaa";
|
||||
set weak_text = "#000000";
|
||||
set comment_bar_one_bgcolor = "#aaaaaa";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#dddddd";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
set comment_bar_screened_bgcolor = "#5f6f99";
|
||||
set comment_bar_screened_fgcolor = "#000000";
|
||||
|
||||
set box_width = 600;
|
||||
set show_entrynav_icons = true;
|
||||
set page_background_image = "";
|
||||
|
||||
set font_base = "Verdana";
|
||||
set font_fallback = "sans-serif";
|
||||
|
||||
# Customize the view names to be short and lowercase
|
||||
# (Sorry translators, you'll have to do these again - keep them short!)
|
||||
set text_view_recent = "entries";
|
||||
set text_view_friends = "friends";
|
||||
set text_view_archive = "archive";
|
||||
set text_view_userinfo = "userinfo";
|
||||
|
||||
set tags_aware = true;
|
||||
|
||||
set text_website = "website";
|
||||
|
||||
function print_stylesheet () {
|
||||
print clean_url($*page_background_image) != "" ? "body { background-image: url($*page_background_image); }" : "";
|
||||
"""body, td {
|
||||
""";
|
||||
if ($*font_base != "" or $*font_fallback != "none") {
|
||||
"font-family: ";
|
||||
if ($*font_base != "") {
|
||||
"\"$*font_base\"";
|
||||
if ($*font_fallback != "none") {
|
||||
", ";
|
||||
}
|
||||
}
|
||||
if ($*font_fallback != "none") {
|
||||
print $*font_fallback;
|
||||
}
|
||||
";\n";
|
||||
}
|
||||
"""font-size: 10pt;
|
||||
}
|
||||
tt, pre {
|
||||
font-family: monospace;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.shadowed {
|
||||
font-size: 8pt;
|
||||
background: $*weak_back;
|
||||
}
|
||||
.meta {
|
||||
font-size: 8pt;
|
||||
}
|
||||
.index {
|
||||
font-size: 8pt;
|
||||
}
|
||||
.caption, .index {
|
||||
color: $*stronger_text;
|
||||
}
|
||||
.comments {
|
||||
font-size: 8pt;
|
||||
}
|
||||
|
||||
""";
|
||||
}
|
||||
|
||||
function Page::lay_top_userpic () {
|
||||
var Image up_img = $.journal.default_pic;
|
||||
if (defined $up_img) {
|
||||
"""<td><table cellpadding="2" bgcolor="$*entry_back" cellspacing="0" border="0" summary="">
|
||||
<tr><td bgcolor="$*stronger_back" align="center"><img border="0" src="$up_img.url" height="$up_img.height" width="$up_img.width" alt=""></td></tr>
|
||||
</table></td>
|
||||
""";
|
||||
}
|
||||
}
|
||||
function FriendsPage::lay_top_userpic () { }
|
||||
|
||||
function Page::print_linklist() {
|
||||
if (size $.linklist <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
println """
|
||||
<p>
|
||||
<table width='$*box_width' cellpadding='2' cellspacing='0'
|
||||
border='0'
|
||||
summary=''>
|
||||
<tr><td bgcolor='$*stronger_back' align='center'>
|
||||
<table width='100%' cellpadding='3' cellspacing='0'
|
||||
border='0'
|
||||
summary=''>
|
||||
<tr class='caption'>
|
||||
<td class='caption' align='left'><b>Links</b></td>
|
||||
</tr></table>
|
||||
<table width='100%' cellpadding='3' cellspacing='0'
|
||||
border='0'
|
||||
summary=''>
|
||||
<tr class='shadowed'>
|
||||
<td align='center'>
|
||||
<table cellspacing='5'
|
||||
cellpadding='0'
|
||||
border='0'
|
||||
summary=''>
|
||||
""";
|
||||
var bool section_open = false;
|
||||
if (not $.linklist[0].is_heading) {
|
||||
println """<tr><td class="meta">[</td><td class="meta" align="right"><b>Links:</b></td><td class="meta" align="center">|</td><td class="meta">""";
|
||||
$section_open = true;
|
||||
}
|
||||
foreach var UserLink l ($.linklist) {
|
||||
if ($l.title) {
|
||||
if ($l.is_heading) {
|
||||
if ($section_open) {
|
||||
println """</td><td class="meta">]</td></tr>""";
|
||||
}
|
||||
println """<tr><td class="meta">[</td><td class="meta" align="right"><b>$l.title</b></td><td class="meta" align="center">|</td><td class="meta">""";
|
||||
$section_open = true;
|
||||
} else {
|
||||
println """<a href="$l.url">$l.title</a> """;
|
||||
}
|
||||
}
|
||||
}
|
||||
println """</td><td class="meta">]</td></tr>""";
|
||||
|
||||
"</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr></table>
|
||||
</p>
|
||||
";
|
||||
}
|
||||
|
||||
function Page::print ()
|
||||
{
|
||||
var string title = $this->title();
|
||||
|
||||
var string website_name = $.journal.website_name ? $.journal.website_name : $*text_website_default_name;
|
||||
var string website;
|
||||
if ($.journal.website_url != "") {
|
||||
$website = """<tr><td class="meta">[</td>
|
||||
<td class="meta" align="right"><b>$*text_website</b></td>
|
||||
<td class="meta" align="center">|</td>
|
||||
<td class="meta" align="left"><a href="$.journal.website_url">$website_name</a></td>
|
||||
<td class="meta">]</td></tr>""";
|
||||
}
|
||||
|
||||
var string links;
|
||||
var bool firstlink = true;
|
||||
foreach var string v ($.views_order) {
|
||||
if ($firstlink == false) {
|
||||
$links = "$links|";
|
||||
}
|
||||
else {
|
||||
$firstlink = false;
|
||||
}
|
||||
$links = $links + ($.view == $v ?
|
||||
"<b>"+lang_viewname($v)+"</b>" :
|
||||
"<a class='index' 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">
|
||||
<div align="center">
|
||||
<table width="$*box_width" cellpadding="2" cellspacing="0"
|
||||
border="0"
|
||||
summary="">
|
||||
<tr><td bgcolor="$*stronger_back" align="center">
|
||||
<table width="100%" cellpadding="3" cellspacing="0"
|
||||
border="0"
|
||||
summary="">
|
||||
<tr class="caption">
|
||||
<td class="caption" align="left"><b>$title</b></td>
|
||||
<td class="index" align="right">[$links]</td>
|
||||
</tr></table>
|
||||
<table width="100%" cellpadding="3" cellspacing="0"
|
||||
border="0"
|
||||
summary="">
|
||||
<tr>
|
||||
<td class="shadowed" align="center">
|
||||
<table cellspacing="5"
|
||||
cellpadding="0"
|
||||
border="0"
|
||||
summary="" style="margin-left: auto; margin-right: auto;">
|
||||
<tr>""";
|
||||
$this->lay_top_userpic();
|
||||
|
||||
var string sitename_lc = $*SITENAMESHORT->lower();
|
||||
|
||||
"""<td>
|
||||
<div align="center"><b>$.journal.name</b></div><p>
|
||||
<table cellspacing="0"
|
||||
cellpadding="0"
|
||||
border="0"
|
||||
summary="">
|
||||
$website
|
||||
<tr>
|
||||
<td class="meta">[</td>
|
||||
<td class="meta" align="right"><b>"""+lang_viewname("userinfo")+"""</b></td>
|
||||
<td class="meta" align="center">|</td>
|
||||
<td class="meta" align="left"><a href="$.view_url{"userinfo"}">$sitename_lc userinfo</a></td>
|
||||
<td class="meta">]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="meta">[</td>
|
||||
<td class="meta" align="right"><b>"""+lang_viewname("archive")+"""</b></td>
|
||||
<td class="meta" align="center">|</td>
|
||||
<td class="meta" align="left"><a href="$.view_url{"archive"}">journal archive</a></td>
|
||||
<td class="meta">]</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr></table>
|
||||
</td></tr>
|
||||
</table>
|
||||
|
||||
""";
|
||||
if (size $.linklist > 0 and $*linklist_support) {
|
||||
$this->print_linklist();
|
||||
}
|
||||
"""
|
||||
|
||||
<p>
|
||||
""";
|
||||
$this->print_body();
|
||||
|
||||
"""
|
||||
</div>
|
||||
<p>
|
||||
</body>
|
||||
</html>
|
||||
""";
|
||||
}
|
||||
|
||||
function print_entry (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text)
|
||||
{
|
||||
var string datetime;
|
||||
$datetime = $e.time->date_format("med")+"|<b>"
|
||||
+ $e.time->time_format() + "</b>";
|
||||
|
||||
"""
|
||||
<table width="$*box_width" cellpadding="2" cellspacing="0" border="0" summary="" class="entrybox">
|
||||
<tr align='left'>
|
||||
<td bgcolor="$*stronger_back" align="center">
|
||||
<table width="100%" cellpadding="5" cellspacing="0" border="0" summary="">
|
||||
<tr align='left'>
|
||||
<td class="caption">""";
|
||||
|
||||
if ($e.security != "") {
|
||||
$e.security_icon->print();
|
||||
}
|
||||
|
||||
""" $e.subject</td>
|
||||
<td align="right" class="index">[$datetime]</td>
|
||||
</tr>
|
||||
<tr align='left'>
|
||||
<td colspan="2" bgcolor="$*entry_back">
|
||||
""";
|
||||
|
||||
if ($p.view == "entry" and $*show_entrynav_icons)
|
||||
{
|
||||
print "<div style='text-align: center'>";
|
||||
$e->print_linkbar();
|
||||
print "</div>";
|
||||
}
|
||||
|
||||
if ($p.view == "friends" or
|
||||
$p.journal_type == "C" or
|
||||
$e.poster.username != $e.journal.username)
|
||||
{
|
||||
var UserLite linkto;
|
||||
var bool showposter;
|
||||
if ($p.view == "recent" and $p.journal_type == "C") {
|
||||
$linkto = $e.poster;
|
||||
$showposter = false;
|
||||
} else {
|
||||
$linkto = $e.journal;
|
||||
$showposter = true;
|
||||
}
|
||||
|
||||
"""<table cellpadding="1" align="right" cellspacing="0" border="0" summary=""><tr align='left'><td bgcolor="$*stronger_back">""";
|
||||
"""<table cellpadding="2" align="center" cellspacing="0" border="0" summary="">""";
|
||||
"""<tr align='left'><td bgcolor="$bgcolor" align="center"><a class="index" href=\"""" + $linkto->base_url() + "\">";
|
||||
if (defined $e.userpic) {
|
||||
"""<img border="0" src="$e.userpic.url" width="$e.userpic.width" height="$e.userpic.height" alt=""><br>""";
|
||||
}
|
||||
|
||||
"<font color=\"$fgcolor\">$linkto.username</font></a>";
|
||||
if ($e.poster.username != $e.journal.username and $showposter) {
|
||||
"<br>[<a class=\"index\" href=\"" +
|
||||
$e.poster->base_url() + "/\"><font color=\"$fgcolor\">$e.poster.username</font></a>]";
|
||||
}
|
||||
"</td></tr></table></td></tr></table>";
|
||||
}
|
||||
|
||||
var string metadata;
|
||||
if ($e.metadata) {
|
||||
$metadata = """<table cellspacing="0" cellpadding="0" border="0" summary="">""";
|
||||
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='absmiddle'> $val";
|
||||
}
|
||||
$metadata = """$metadata\n<tr><td class="meta">[</td><td class="meta" align="right"><b>$text</b></td>
|
||||
<td class="meta" align="center">|</td><td class="meta">$val</td><td class="meta">]</td></tr>""";
|
||||
}
|
||||
$metadata = """$metadata</table>""";
|
||||
}
|
||||
|
||||
var string tags;
|
||||
if ($e.tags) {
|
||||
var int tcount = 0;
|
||||
$tags = """<table cellspacing="0" cellpadding="0" border="0" summary=""><tr><td class="meta" align="right">[<b>Tags</b></td>""";
|
||||
$tags = """$tags<td class="meta" align="center">|</td><td class="meta">""";
|
||||
foreach var Tag t ($e.tags) {
|
||||
$tags = """$tags<a rel="tag" href="$t.url">$t.name</a>""";
|
||||
$tcount++;
|
||||
if ($tcount != size $e.tags) { $tags = """$tags, """; }
|
||||
}
|
||||
$tags = """$tags</td><td class="meta">]</td></tr></table>""";
|
||||
}
|
||||
|
||||
if (not $hide_text) {
|
||||
if ($tags or $metadata) {
|
||||
print $tags;
|
||||
print $metadata;
|
||||
print "<br />";
|
||||
}
|
||||
print $e.text;
|
||||
}
|
||||
"""</td></tr>
|
||||
<tr bgcolor="$*weak_back"><td align='left' class='comments'>
|
||||
<a href="$e.permalink_url">$*text_permalink</a></td>""";
|
||||
if ($p.view != "entry" and $p.view != "reply") {
|
||||
"<td align='right' class='comments'>"; $e.comments->print(); "</td>";
|
||||
} elseif ($e.comments.enabled) {
|
||||
"<td align='right' class='comments'>"; $e.comments->print_postlink(); "</td>";
|
||||
} else {
|
||||
"<td></td>";
|
||||
}
|
||||
"""</tr></table></td></tr></table><p>""";
|
||||
|
||||
} # print_entry(Page,Entry,Color,Color,bool)
|
||||
|
||||
function Page::print_entry (Entry e) {
|
||||
print_entry($this, $e, null Color, null Color, false);
|
||||
}
|
||||
|
||||
function FriendsPage::print_entry (Entry e) {
|
||||
var Friend f = $.friends{$e.journal.username};
|
||||
print_entry($this, $e, $f.bgcolor, $f.fgcolor, false);
|
||||
}
|
||||
|
||||
function RecentPage::print_body ()
|
||||
{
|
||||
foreach var Entry e ($.entries) {
|
||||
$this->print_entry($e);
|
||||
}
|
||||
|
||||
var string range = "most recent entries";
|
||||
if ($.nav.skip > 0) {
|
||||
$range = "$.nav.skip entries back";
|
||||
}
|
||||
|
||||
"""
|
||||
<table cellpadding="2" cellspacing="0"
|
||||
border="0"
|
||||
summary="">
|
||||
<tr><td bgcolor="$*stronger_back">
|
||||
<table cellpadding="3" cellspacing="0"
|
||||
border="0"
|
||||
summary="">
|
||||
<tr>
|
||||
<td align="center" class="index">navigation</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="$*entry_back" align="center">
|
||||
<table cellspacing="0"
|
||||
cellpadding="0"
|
||||
border="0"
|
||||
summary="">
|
||||
<tr>
|
||||
<td class="meta">[</td>
|
||||
<td class="meta" align="right"><b>viewing</b></td>
|
||||
<td class="meta" align="center">|</td>
|
||||
<td class="meta">$range</td>
|
||||
<td class="meta">]</td>
|
||||
</tr>
|
||||
""";
|
||||
|
||||
# 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">earlier</a>""";
|
||||
}
|
||||
if ($.nav.forward_url != "") {
|
||||
$forward = """<a href="$.nav.forward_url">later</a>""";
|
||||
}
|
||||
if ($back != "" and $forward != "") { $sep = "/"; }
|
||||
"""<tr>
|
||||
<td class="meta">[</td>
|
||||
<td class="meta" align="right"><b>go</b></td>
|
||||
<td class="meta" align="center">|</td>
|
||||
<td class="meta">$back$sep$forward</td>
|
||||
<td class="meta">]</td>
|
||||
</tr>""";
|
||||
}
|
||||
|
||||
"</table></td></tr></table></table>";
|
||||
}
|
||||
|
||||
function CommentInfo::print ()
|
||||
{
|
||||
if (not $.enabled) { return; }
|
||||
if ($.count > 0 or $.screened) {
|
||||
"<b>"; $this->print_readlink(); "</b>";
|
||||
"|";
|
||||
}
|
||||
$this->print_postlink();
|
||||
}
|
||||
|
||||
function YearPage::print_year_links ()
|
||||
{
|
||||
"""<table cellpadding="2" cellspacing="0" border="0" summary="">
|
||||
<tr><td bgcolor="$*stronger_back" align="center">
|
||||
<table cellpadding="5" cellspacing="0" border="0" summary="">
|
||||
<tr><td class="caption">Years</td></tr><tr>
|
||||
<td colspan="2" bgcolor="$*entry_back">""";
|
||||
foreach var YearYear y ($.years) {
|
||||
if ($y.displayed) {
|
||||
"<b>$y.year</b> ";
|
||||
} else {
|
||||
"<a href=\"$y.url\">$y.year</a> ";
|
||||
}
|
||||
}
|
||||
"""</td></tr></table></td></tr></table><p>""";
|
||||
|
||||
}
|
||||
|
||||
function YearPage::print_month (YearMonth m)
|
||||
{
|
||||
if (not $m.has_entries) { return; }
|
||||
"""<table cellpadding="2" cellspacing="0" border="0" summary="">
|
||||
<tr><td bgcolor="$*stronger_back" align="center">
|
||||
<table cellpadding="5" cellspacing="0" border="0" summary="">
|
||||
<tr>
|
||||
<td class="caption">""";
|
||||
print $m->month_format();
|
||||
"""</td>
|
||||
<td class="caption" align="right">[<a href="$m.url" class="index">subjects</a>]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" bgcolor="$*entry_back">
|
||||
<!-- now the headings for the week -->
|
||||
<table width="100%" cellpadding="5" cellspacing="0" border="0" summary="">
|
||||
<tr align="center">
|
||||
""";
|
||||
foreach var int d (weekdays()) {
|
||||
"<td>"+$*lang_dayname_short[$d]+"</td>\n";
|
||||
}
|
||||
|
||||
"</tr>";
|
||||
|
||||
foreach var YearWeek w ($m.weeks) {
|
||||
$w->print();
|
||||
}
|
||||
|
||||
"""</table></td></tr></table></td></tr></table><p>""";
|
||||
}
|
||||
|
||||
function YearWeek::print () {
|
||||
"<tr valign='top'>";
|
||||
if ($.pre_empty) { "<td colspan='$.pre_empty'></td>"; }
|
||||
foreach var YearDay d ($.days) {
|
||||
"""<td><div class="meta">$d.day</div>""";
|
||||
if ($d.num_entries) {
|
||||
"""<div align="center"><a href="$d.url">$d.num_entries</a></div>""";
|
||||
} else {
|
||||
" ";
|
||||
}
|
||||
"</td>";
|
||||
}
|
||||
if ($.post_empty) { "<td colspan='$.post_empty'></td>"; }
|
||||
"</tr>";
|
||||
}
|
||||
|
||||
function DayPage::print_body() {
|
||||
|
||||
"""<table cellpadding="2" cellspacing="0" border="0" summary="">
|
||||
<tr><td bgcolor="$*stronger_back" align="center">
|
||||
<table cellpadding="5" cellspacing="0" border="0" summary="">
|
||||
<tr><td bgcolor="$*entry_back">""";
|
||||
|
||||
if ($.has_entries) {
|
||||
print $.date->date_format("long");
|
||||
} else {
|
||||
print ehtml($*text_noentries_day);
|
||||
}
|
||||
|
||||
"""</td></tr></table></td></tr></table><p>""";
|
||||
|
||||
foreach var Entry e ($.entries) {
|
||||
$this->print_entry($e);
|
||||
}
|
||||
|
||||
var string tprev = ehtml($*text_day_prev);
|
||||
var string tnext = ehtml($*text_day_next);
|
||||
var string daylong = $.date->date_format("long");
|
||||
|
||||
"""<table cellpadding="2" cellspacing="0" border="0" summary="">
|
||||
<tr><td bgcolor="$*stronger_back">
|
||||
<table cellpadding="3" cellspacing="0" border="0" summary="">
|
||||
<tr>
|
||||
<td align="center" class="index">navigation</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor="$*entry_back" align="center">
|
||||
<table cellspacing="0" cellpadding="0" border="0" summary="">
|
||||
<tr>
|
||||
<td class="meta">[</td>
|
||||
<td class="meta" align="right"><b>viewing</b></td>
|
||||
<td class="meta" align="center">|</td>
|
||||
<td class="meta">$daylong</td>
|
||||
<td class="meta">]</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="meta">[</td>
|
||||
<td class="meta" align="right"><b>go</b></td>
|
||||
<td class="meta" align="center">|</td>
|
||||
<td class="meta"><a href="$.prev_url">$tprev</a>|<a href="$.next_url">$tnext</a></td>
|
||||
<td class="meta">]</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</table>""";
|
||||
|
||||
}
|
||||
|
||||
function MonthPage::print_body () {
|
||||
"""<table width="$*box_width" cellpadding="2" cellspacing="0" border="0" summary="" class="entrybox">
|
||||
<tr align='left'>
|
||||
<td bgcolor="$*stronger_back" align="center">
|
||||
<table width="100%" cellpadding="5" cellspacing="0" border="0" summary="">
|
||||
<tr align='left'>
|
||||
<td class="caption" colspan='2'>""";
|
||||
|
||||
print $.date->date_format($*lang_fmt_month_long);
|
||||
|
||||
"""</td></tr>
|
||||
<tr align='left'>
|
||||
<td colspan="2" bgcolor="$*entry_back">""";
|
||||
|
||||
#Lifted from core, looks decent:
|
||||
"<form method='post' action='$.redir.url'><center>";
|
||||
$.redir->print_hiddens();
|
||||
if ($.prev_url != "") { "[<a href='$.prev_url'><<<</a>]\n"; }
|
||||
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 != "") { "\n[<a href='$.next_url'>>>></a>]\n"; }
|
||||
"</center></form>\n<dl>";
|
||||
foreach var MonthDay d ($.days) {
|
||||
if ($d.has_entries) {
|
||||
"<dt><a href=\"$d.url\"><b>";
|
||||
print lang_ordinal($d.day);
|
||||
"</b></a></dt>\n<dd>";
|
||||
$d->print_subjectlist();
|
||||
"</dd>\n";
|
||||
}
|
||||
}
|
||||
"</dl>\n";
|
||||
"""</td></tr></table>
|
||||
</td></tr></table><p>""";
|
||||
}
|
||||
|
||||
function EntryPage::print_body () {
|
||||
|
||||
print_entry($this, $.entry, null Color, null Color, $.viewing_thread);
|
||||
|
||||
if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0)
|
||||
{
|
||||
$this->print_multiform_start();
|
||||
"""<table width="$*box_width" cellpadding="2" cellspacing="0" border="0" summary="" class="entrybox">
|
||||
<tr align='left'>
|
||||
<td bgcolor="$*stronger_back" align="center">
|
||||
<table width="100%" cellpadding="5" cellspacing="0" border="0" summary="">
|
||||
<tr align='left'>
|
||||
<td class="caption" colspan='2'>Comments:</td></tr>""";
|
||||
|
||||
"""<tr align='left'><td colspan="2" bgcolor="$*entry_back">""";
|
||||
|
||||
$.comment_pages->print();
|
||||
|
||||
set_handler("unscreen_comment_#", [
|
||||
[ "style_bgcolor", "cmtbar#", "$*comment_bar_one_bgcolor", ],
|
||||
[ "style_color", "cmtbar#", "$*comment_bar_one_fgcolor", ],
|
||||
]);
|
||||
set_handler("screen_comment_#", [
|
||||
[ "style_bgcolor", "cmtbar#", "$*comment_bar_screened_bgcolor", ],
|
||||
[ "style_color", "cmtbar#", "$*comment_bar_screened_fgcolor", ],
|
||||
]);
|
||||
|
||||
$this->print_comments($.comments);
|
||||
$.comment_pages->print();
|
||||
"""</td></tr></table></td></tr></table><p>""";
|
||||
|
||||
if ($this.multiform_on) {
|
||||
"""<table width="$*box_width" cellpadding="2" cellspacing="0" border="0" summary="" class="entrybox">
|
||||
<tr align='left'>
|
||||
<td bgcolor="$*stronger_back" align="center">
|
||||
<table width="100%" cellpadding="5" cellspacing="0" border="0" summary="">
|
||||
<tr align='left'>
|
||||
<td class="caption" colspan='2'>Mass Action:</td></tr>""";
|
||||
|
||||
"""<tr align='left'><td colspan="2" bgcolor="$*entry_back">""";
|
||||
$this->print_multiform_actionline();
|
||||
"""</td></tr></table></td></tr></table><p>""";
|
||||
$this->print_multiform_end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function EntryPage::print_comment (Comment c) {
|
||||
var Color background; var Color color;
|
||||
if ($c.screened) {
|
||||
$background = $*comment_bar_screened_bgcolor;
|
||||
$color = $*comment_bar_screened_fgcolor;
|
||||
} elseif ($c.depth % 2) {
|
||||
$background = $*comment_bar_one_bgcolor;
|
||||
$color = $*comment_bar_one_fgcolor;
|
||||
} else {
|
||||
$background = $*comment_bar_two_bgcolor;
|
||||
$color = $*comment_bar_two_fgcolor;
|
||||
}
|
||||
var string poster = defined $c.poster ? $c.poster->as_string() : "<i>(Anonymous)</i>";
|
||||
var string sub_icon;
|
||||
if (defined $c.subject_icon) {
|
||||
$sub_icon = $c.subject_icon->as_string();
|
||||
}
|
||||
"<a name='$c.anchor'></a><div id='cmtbar$c.talkid' style='background-color: $background; color: $color; margin-top: 10px; width: 100%;'>";
|
||||
"<table cellpadding='2' cellspacing='0' summary='0' style='width: 100%'><tr valign='top'>";
|
||||
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;
|
||||
}
|
||||
print "<td style='width: 102px'><img src='$c.userpic.url' width='$w' height='$h' alt='[User Picture]' /></td>";
|
||||
}
|
||||
|
||||
"<td style='width: 100%'><table style='width: 100%'><tr>";
|
||||
|
||||
### From, date, etc
|
||||
"<td align='left' style='width: 50%'>";
|
||||
print "<table>";
|
||||
print "<tr><th align='right' style='white-space: nowrap'>From:</th><td style='white-space: nowrap'>$poster</td></tr>\n";
|
||||
print "<tr><th align='right' style='white-space: nowrap'>Date:</th><td style='white-space: nowrap'>";
|
||||
print $c.time->date_format("long") + " - " + $c.time->time_format() + "</td></tr>";
|
||||
if ($c.metadata{"poster_ip"}) { print "<tr><th align='right' style='white-space: nowrap'>IP Address:</th><td>(" + $c.metadata{"poster_ip"} + ")</td></tr>"; }
|
||||
"</table></td>";
|
||||
|
||||
### Gadgets
|
||||
"<td align='right' style='width: 50%'>";
|
||||
if ($this.multiform_on) {
|
||||
" <label for='ljcomsel_$c.talkid'>$*text_multiform_check</label>";
|
||||
$c->print_multiform_check();
|
||||
}
|
||||
$c->print_linkbar();
|
||||
"</td></tr>";
|
||||
|
||||
### Subject / icon
|
||||
print "<tr valign='top'><td style='width: 50%'>";
|
||||
print (defined $c.subject_icon or $c.subject != "") ? "<h3>$c.subject_icon $c.subject</h3>" : "";
|
||||
print "</td>";
|
||||
|
||||
### Permalink
|
||||
print "<td style='width: 50%' align='right'><strong>(<a href='$c.permalink_url'>Link</a>)</strong></td></tr>";
|
||||
|
||||
print "</table></td></tr></table></div>";
|
||||
print "<div style='margin-left: 5px'>$c.text</div>";
|
||||
print "<div style='margin-top: 3px; font-size: smaller'>";
|
||||
|
||||
"<span class='commentlinks'>";
|
||||
if ($c.frozen) {
|
||||
"(Replies frozen) ";
|
||||
} else {
|
||||
"(<a href='$c.reply_url'>Reply to this</a>) ";
|
||||
}
|
||||
"</span>";
|
||||
|
||||
if ($c.parent_url != "") { "(<a href='$c.parent_url'>Parent</a>) "; }
|
||||
if ($c.thread_url != "") { "(<a href='$c.thread_url'>Thread</a>) "; }
|
||||
"</div>";
|
||||
}
|
||||
|
||||
function ReplyPage::print_body () {
|
||||
if (not $.entry.comments.enabled) {
|
||||
"""<table width="$*box_width" cellpadding="2" cellspacing="0" border="0" summary="" class="entrybox">
|
||||
<tr align='left'>
|
||||
<td bgcolor="$*stronger_back" align="center">
|
||||
<table width="100%" cellpadding="5" cellspacing="0" border="0" summary="">
|
||||
<tr align='left'>
|
||||
<td class="caption" colspan='2'>$*text_reply_nocomments_header</td></tr>
|
||||
<tr align='left'>
|
||||
<td colspan="2" bgcolor="$*entry_back">""";
|
||||
|
||||
print "<p>$*text_reply_nocomments</p>";
|
||||
"""</td></tr></table></td></tr></table><p>""";
|
||||
return;
|
||||
}
|
||||
var string datetime;
|
||||
$datetime = $.replyto.time->date_format("med")+"|<b>" + $.replyto.time->time_format() + "</b>";
|
||||
"""<table width="$*box_width" cellpadding="2" cellspacing="0" border="0" summary="" class="entrybox">
|
||||
<tr align='left'>
|
||||
<td bgcolor="$*stronger_back" align="center">
|
||||
<table width="100%" cellpadding="5" cellspacing="0" border="0" summary="">
|
||||
<tr align='left'>
|
||||
<td class="caption">$.replyto.subject</td>
|
||||
<td class="index" align="right">$datetime</td></tr>
|
||||
<tr align='left'>
|
||||
<td colspan="2" bgcolor="$*entry_back">
|
||||
<table cellpadding="1" align="right" cellspacing="0" border="0" summary="">
|
||||
<tr align='left'><td bgcolor="$*stronger_back">
|
||||
<table cellpadding="2" align="center" cellspacing="0" border="0" summary="">
|
||||
<tr align='left'><td align="center" style="color: $*stronger_text">""";
|
||||
|
||||
if (defined $.replyto.poster) {
|
||||
"<a href='" + $.replyto.poster->base_url() + "/'>";
|
||||
if (defined $.replyto.userpic) {
|
||||
"""<img border="0" src="$.replyto.userpic.url" width="$.replyto.userpic.width" """;
|
||||
"""height="$.replyto.userpic.height" alt=""><br />""";
|
||||
}
|
||||
"$.replyto.poster.username</a>";
|
||||
} else {
|
||||
print "<i>Anonymous</i>";
|
||||
}
|
||||
|
||||
"""</td></tr></table></td></tr></table>$.replyto.text</td></tr>
|
||||
<tr bgcolor="$*weak_back"><td align='left' class='comments'>
|
||||
<a href="$.replyto.permalink_url">$*text_permalink</a></td>
|
||||
<td align='right' class='comments'><a href='$.entry.comments.read_url'>Read Comments</a></td>
|
||||
</tr></table></td></tr></table><p>""";
|
||||
|
||||
"""<table width="$*box_width" cellpadding="2" cellspacing="0" border="0" summary="" class="entrybox">
|
||||
<tr align='left'>
|
||||
<td bgcolor="$*stronger_back" align="center">
|
||||
<table width="100%" cellpadding="5" cellspacing="0" border="0" summary="">
|
||||
<tr align='left'>
|
||||
<td class="caption" colspan='2'>Reply:</td></tr>
|
||||
<tr align='left'>
|
||||
<td colspan="2" bgcolor="$*entry_back">""";
|
||||
|
||||
$.form->print();
|
||||
|
||||
"""</td></tr></table></td></tr></table><p>""";
|
||||
}
|
||||
|
||||
function print_theme_preview () {
|
||||
"""<table width='100%' bgcolor='$*page_back' cellpadding=10><tr><td align='center'>
|
||||
|
||||
<table width='400' cellpadding='2' cellspacing='2'>
|
||||
<tr align='left'><td bgcolor="$*stronger_back" align="center">
|
||||
|
||||
<table width="100%" cellpadding="5" cellspacing="0" border="0" summary="">
|
||||
<tr align='left'><td style="color: $*stronger_text">Preview Subject</td><td align="right" style="font-size: 8pt; color: $*stronger_text">[Feb. 5th, 2002|<b>8:46 pm</b>]</td></tr>
|
||||
<tr align='left'>
|
||||
<td colspan="2" bgcolor="$*entry_back" style='color: $*entry_text'>
|
||||
Preview text, preview text, etc, etc..... words, words and more words.
|
||||
|
||||
</td></tr>
|
||||
|
||||
<tr bgcolor="$*weak_back"><td align='left' class='style: font-size: 8pt'>
|
||||
<a style='text-decoration:none;color: $*page_link' href="#">$*text_permalink</a>
|
||||
</td><td align='right' style='font-size: 8pt'>
|
||||
<a href='#' style='text-decoration:none;color:$*page_vlink'><b>1 comment</b></a>|<a href='#' style='text-decoration:none;color:$*page_link'>post comment</a>
|
||||
|
||||
</td></tr></table>
|
||||
</td></tr></table>
|
||||
</td></tr></table>
|
||||
""";
|
||||
}
|
||||
369
livejournal/bin/upgrading/s2layers/generator/themes.s2
Executable file
@@ -0,0 +1,369 @@
|
||||
#NEWLAYER: generator/mintchoc
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Mint Chocolate Chip";
|
||||
layerinfo "redist_uniq" = "generator/mintchoc";
|
||||
layerinfo "author_name" = "Andrea Hartmann";
|
||||
layerinfo "author_email" = "mullenkamp@livejournal.com";
|
||||
set entry_back = "#ddffee";
|
||||
set entry_text = "#330000";
|
||||
set page_link = "#993333";
|
||||
set page_vlink = "#663333";
|
||||
set page_alink = "#000000";
|
||||
set page_back = "#ccffdd";
|
||||
set stronger_back = "#663333";
|
||||
set stronger_text = "#ccffdd";
|
||||
set weak_back = "#88ffdd";
|
||||
set weak_text = "#663333";
|
||||
set comment_bar_one_bgcolor = "#88ffdd";
|
||||
set comment_bar_one_fgcolor = "#663333";
|
||||
set comment_bar_two_fgcolor = "#663333";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: generator/purple
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Purple";
|
||||
layerinfo "redist_uniq" = "generator/purple";
|
||||
layerinfo "author_name" = "Andrea Hartmann";
|
||||
layerinfo "author_email" = "mullenkamp@livejournal.com";
|
||||
set entry_back = "#9933cc";
|
||||
set entry_text = "#ddccff";
|
||||
set page_link = "#ffffff";
|
||||
set page_vlink = "#330033";
|
||||
set page_alink = "#ffccff";
|
||||
set page_back = "#bb55ee";
|
||||
set stronger_back = "#660099";
|
||||
set stronger_text = "#f5eeff";
|
||||
set weak_back = "#bb88dd";
|
||||
set weak_text = "#ddccff";
|
||||
set comment_bar_one_bgcolor = "#660099";
|
||||
set comment_bar_one_fgcolor = "#f5eeff";
|
||||
set comment_bar_two_bgcolor = "#bb88dd";
|
||||
set comment_bar_two_fgcolor = "#ddccff";
|
||||
|
||||
#NEWLAYER: generator/ocean
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Deep Blue Xenogears Ocean";
|
||||
layerinfo "redist_uniq" = "generator/ocean";
|
||||
layerinfo "author_name" = "Andrea Hartmann";
|
||||
layerinfo "author_email" = "mullenkamp@livejournal.com";
|
||||
set entry_back = "#1100dd";
|
||||
set entry_text = "#ccccff";
|
||||
set page_link = "#ffffff";
|
||||
set page_vlink = "#ddddff";
|
||||
set page_alink = "#ffffff";
|
||||
set page_back = "#3333ff";
|
||||
set stronger_back = "#aabbff";
|
||||
set stronger_text = "#0033cc";
|
||||
set weak_back = "#3399ff";
|
||||
set weak_text = "#0033cc";
|
||||
set comment_bar_one_bgcolor = "#aabbff";
|
||||
set comment_bar_one_fgcolor = "#0033cc";
|
||||
set comment_bar_two_bgcolor = "#3399ff";
|
||||
set comment_bar_two_fgcolor = "#0033cc";
|
||||
|
||||
#NEWLAYER: generator/harvest
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Harvest";
|
||||
layerinfo "redist_uniq" = "generator/harvest";
|
||||
layerinfo "author_name" = "Andrea Hartmann";
|
||||
layerinfo "author_email" = "mullenkamp@livejournal.com";
|
||||
set entry_back = "#ff9900";
|
||||
set entry_text = "#663333";
|
||||
set page_link = "#ffeeaa";
|
||||
set page_vlink = "#993300";
|
||||
set page_alink = "#ffcc88";
|
||||
set page_back = "#ffaa11";
|
||||
set stronger_back = "#ffcc33";
|
||||
set stronger_text = "#663333";
|
||||
set weak_back = "#cc6600";
|
||||
set weak_text = "#ffcc88";
|
||||
set comment_bar_one_bgcolor = "#ffcc33";
|
||||
set comment_bar_one_fgcolor = "#663333";
|
||||
set comment_bar_two_bgcolor = "#cc6600";
|
||||
set comment_bar_two_fgcolor = "#ffcc88";
|
||||
|
||||
#NEWLAYER: generator/jeweled
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Jeweled";
|
||||
layerinfo "redist_uniq" = "generator/jeweled";
|
||||
layerinfo "author_name" = "Andrea Hartmann";
|
||||
layerinfo "author_email" = "mullenkamp@livejournal.com";
|
||||
set entry_back = "#aa6699";
|
||||
set entry_text = "#330066";
|
||||
set page_link = "#ccddee";
|
||||
set page_vlink = "#cc99cc";
|
||||
set page_alink = "#cceecc";
|
||||
set page_back = "#881188";
|
||||
set stronger_back = "#006699";
|
||||
set stronger_text = "#ceecc";
|
||||
set weak_back = "#008888";
|
||||
set weak_text = "#002222";
|
||||
set comment_bar_one_bgcolor = "#006699";
|
||||
set comment_bar_one_fgcolor = "#ceecc";
|
||||
set comment_bar_two_bgcolor = "#008888";
|
||||
set comment_bar_two_fgcolor = "#002222";
|
||||
|
||||
#NEWLAYER: generator/darkgreens
|
||||
layerinfo type = "theme";
|
||||
layerinfo name = "Dark Greens";
|
||||
layerinfo redist_uniq = "generator/darkgreens";
|
||||
layerinfo author_name = "Ryan Fitzpatrick";
|
||||
set entry_back = "#020202";
|
||||
set entry_text = "#fbfbfb";
|
||||
set page_link = "#9aff8d";
|
||||
set page_vlink = "#e3ee39";
|
||||
set page_alink = "#ff0220";
|
||||
set page_back = "#117218";
|
||||
set stronger_back = "#38e616";
|
||||
set stronger_text = "#020100";
|
||||
set weak_back = "#020100";
|
||||
set weak_text = "#000000";
|
||||
set comment_bar_one_bgcolor = "#38e616";
|
||||
set comment_bar_one_fgcolor = "#020100";
|
||||
set comment_bar_two_bgcolor = "#117218";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: generator/satin
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Satin Handshake";
|
||||
layerinfo redist_uniq = "generator/satin";
|
||||
set entry_back = "#d06464";
|
||||
set entry_text = "#000000";
|
||||
set page_link = "#ffffff";
|
||||
set page_vlink = "#6f2222";
|
||||
set page_alink = "#333333";
|
||||
set page_back = "#480c0c";
|
||||
set stronger_back = "#9d0404";
|
||||
set stronger_text = "#ffffff";
|
||||
set weak_back = "#d06464";
|
||||
set weak_text = "#ffffff";
|
||||
set comment_bar_one_bgcolor = "#9d0404";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#d06464";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: generator/sunset
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Sunset";
|
||||
layerinfo redist_uniq = "generator/sunset";
|
||||
set entry_back = "#ff7301";
|
||||
set entry_text = "#fdb54f";
|
||||
set page_link = "#ffe65e";
|
||||
set page_vlink = "#ff9879";
|
||||
set page_alink = "#ffb866";
|
||||
set page_back = "#070494";
|
||||
set stronger_back = "#f8a402";
|
||||
set stronger_text = "#ffd510";
|
||||
set weak_back = "#f51700";
|
||||
set weak_text = "#f77603";
|
||||
set comment_bar_one_bgcolor = "#f8a402";
|
||||
set comment_bar_one_fgcolor = "#ffd510";
|
||||
set comment_bar_two_bgcolor = "#f51700";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: generator/redbliss
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Red Bliss";
|
||||
layerinfo redist_uniq = "generator/redbliss";
|
||||
set entry_back = "#ffcccc";
|
||||
set entry_text = "#000000";
|
||||
set page_link = "#ffffff";
|
||||
set page_vlink = "#ffcccc";
|
||||
set page_alink = "#00ffff";
|
||||
set page_back = "#ff3300";
|
||||
set stronger_back = "#cc3333";
|
||||
set stronger_text = "#ffffff";
|
||||
set weak_back = "#cc3333";
|
||||
set weak_text = "#fafafa";
|
||||
set comment_bar_one_bgcolor = "#cc3333";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#ff3333";
|
||||
set comment_bar_two_fgcolor = "#fafafa";
|
||||
|
||||
#NEWLAYER: generator/pastelneons
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Pastel Neons";
|
||||
layerinfo redist_uniq = "generator/pastelneons";
|
||||
set entry_back = "#ffffff";
|
||||
set entry_text = "#1a6b6a";
|
||||
set page_link = "#330f42";
|
||||
set page_vlink = "#033339";
|
||||
set page_alink = "#9923ca";
|
||||
set page_back = "#00ffff";
|
||||
set stronger_back = "#60d2cb";
|
||||
set stronger_text = "#000000";
|
||||
set weak_back = "#d385f3";
|
||||
set weak_text = "#000000";
|
||||
set comment_bar_one_bgcolor = "#60d2cb";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#d385f3";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: generator/classdesk
|
||||
layerinfo type = "theme";
|
||||
layerinfo name = "Classic Desktop";
|
||||
layerinfo redist_uniq = "generator/classdesk";
|
||||
set page_link = "#ff7b05";
|
||||
set page_vlink = "#ce4900";
|
||||
set page_alink = "#ff9e2b";
|
||||
set page_back = "#007782";
|
||||
set stronger_back = "#00545c";
|
||||
set stronger_text = "#ffffff";
|
||||
set weak_back = "#ffeddd";
|
||||
set weak_text = "#ffffff";
|
||||
set comment_bar_one_bgcolor = "#00545c";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#ffeddd";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: generator/everwhite
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Everwhite";
|
||||
layerinfo redist_uniq = "generator/everwhite";
|
||||
set entry_back = "#ffffff";
|
||||
set entry_text = "#000000";
|
||||
set page_link = "#ff0000";
|
||||
set page_vlink = "#ff0000";
|
||||
set page_alink = "#ffffff";
|
||||
set page_back = "#ffffff";
|
||||
set stronger_back = "#ffffff";
|
||||
set stronger_text = "#ff0000";
|
||||
set weak_back = "#ffffff";
|
||||
set weak_text = "#ffffff";
|
||||
set comment_bar_one_bgcolor = "#dddddd";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#aaaaaa";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: generator/everblue
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Everblue with Grey";
|
||||
layerinfo redist_uniq = "generator/everblue";
|
||||
set entry_back = "#ffffff";
|
||||
set entry_text = "#000000";
|
||||
set page_link = "#0000ff";
|
||||
set page_vlink = "#060667";
|
||||
set page_alink = "#ffffff";
|
||||
set page_back = "#0f0c6d";
|
||||
set stronger_back = "#000000";
|
||||
set stronger_text = "#ffffff";
|
||||
set weak_back = "#aaaaaa";
|
||||
set weak_text = "#000000";
|
||||
set comment_bar_one_bgcolor = "#000000";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#aaaaaa";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: generator/purplesky
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Purple Sky";
|
||||
layerinfo redist_uniq = "generator/purplesky";
|
||||
set entry_back = "#24d8df";
|
||||
set entry_text = "#0424e4";
|
||||
set page_link = "#a917c4";
|
||||
set page_vlink = "#9911e8";
|
||||
set page_alink = "#ea09ff";
|
||||
set page_back = "#99e3e2";
|
||||
set stronger_back = "#8802fa";
|
||||
set stronger_text = "#ffffff";
|
||||
set weak_back = "#89e5e9";
|
||||
set weak_text = "#000000";
|
||||
set comment_bar_one_bgcolor = "#8802fa";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#89e5e9";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: generator/bruise
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Bruise";
|
||||
layerinfo redist_uniq = "generator/bruise";
|
||||
set entry_back = "#bcbcbc";
|
||||
set entry_text = "#000000";
|
||||
set page_link = "#0000ff";
|
||||
set page_vlink = "#0000ff";
|
||||
set page_alink = "#0000ff";
|
||||
set page_back = "#000000";
|
||||
set stronger_back = "#1114a0";
|
||||
set stronger_text = "#ffffff";
|
||||
set weak_back = "#21c2f1";
|
||||
set weak_text = "#000000";
|
||||
set comment_bar_one_bgcolor = "#1114a0";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#21c2f1";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: generator/elegant
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Elegant";
|
||||
layerinfo redist_uniq = "generator/elegant";
|
||||
set entry_back = "#ffffff";
|
||||
set entry_text = "#000000";
|
||||
set page_link = "#e91822";
|
||||
set page_vlink = "#bf1418";
|
||||
set page_alink = "#f71e28";
|
||||
set page_back = "#ffffff";
|
||||
set stronger_back = "#777777";
|
||||
set stronger_text = "#000000";
|
||||
set weak_back = "#e6e6e6";
|
||||
set weak_text = "#000000";
|
||||
set comment_bar_one_bgcolor = "#777777";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#e6e6e6";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: generator/bananapeel
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Banana Peel";
|
||||
layerinfo redist_uniq = "generator/bananapeel";
|
||||
set entry_back = "#f2f688";
|
||||
set entry_text = "#ee2914";
|
||||
set page_link = "#db9129";
|
||||
set page_vlink = "#c58f1b";
|
||||
set page_alink = "#ffc518";
|
||||
set page_back = "#ffffff";
|
||||
set stronger_back = "#f0f905";
|
||||
set stronger_text = "#000000";
|
||||
set weak_back = "#dcdf02";
|
||||
set weak_text = "#000000";
|
||||
set comment_bar_one_bgcolor = "#f0f905";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#dcdf02";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: generator/melodrama
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Deep MeloDrama";
|
||||
layerinfo redist_uniq = "generator/melodrama";
|
||||
set entry_back = "#719cff";
|
||||
set entry_text = "#9348a1";
|
||||
set page_link = "#f5d3ff";
|
||||
set page_vlink = "#e2ffe3";
|
||||
set page_alink = "#e2ffe3";
|
||||
set page_back = "#872d89";
|
||||
set stronger_back = "#3794b3";
|
||||
set stronger_text = "#a4b8ff";
|
||||
set weak_back = "#65b2c1";
|
||||
set weak_text = "#98bac5";
|
||||
set comment_bar_one_bgcolor = "#3794b3";
|
||||
set comment_bar_one_fgcolor = "#a4b8ff";
|
||||
set comment_bar_two_bgcolor = "#65b2c1";
|
||||
set comment_bar_two_fgcolor = "#872d89";
|
||||
|
||||
#NEWLAYER: generator/iceburg
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Iceburg";
|
||||
layerinfo redist_uniq = "generator/iceburg";
|
||||
set entry_back = "#ffffff";
|
||||
set entry_text = "#000000";
|
||||
set page_link = "#0000ff";
|
||||
set page_vlink = "#0000ff";
|
||||
set page_alink = "#387bf7";
|
||||
set page_back = "#c6c2f5";
|
||||
set stronger_back = "#7c6ccd";
|
||||
set stronger_text = "#ffffff";
|
||||
set weak_back = "#eef0fd";
|
||||
set weak_text = "#000000";
|
||||
set comment_bar_one_bgcolor = "#7c6ccd";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#eef0fd";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
BIN
livejournal/bin/upgrading/s2layers/haven/haven.png
Executable file
|
After Width: | Height: | Size: 16 KiB |
1655
livejournal/bin/upgrading/s2layers/haven/layout.s2
Executable file
392
livejournal/bin/upgrading/s2layers/haven/themes.s2
Executable file
@@ -0,0 +1,392 @@
|
||||
#NEWLAYER: haven/bluemonochromatic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Adaywien";
|
||||
layerinfo "redist_uniq" = "haven/bluemonochromatic";
|
||||
|
||||
set color_scheme_base = "#1575C7";
|
||||
set color_scheme = "monochromatic";
|
||||
|
||||
#NEWLAYER: haven/blueanalogous
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Gwirasien";
|
||||
layerinfo "redist_uniq" = "haven/blueanalogous";
|
||||
|
||||
set color_scheme_base = "#1575C7";
|
||||
set color_scheme = "analogous";
|
||||
|
||||
#NEWLAYER: haven/bluecomplementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Etaella";
|
||||
layerinfo "redist_uniq" = "haven/bluecomplementary";
|
||||
|
||||
set color_scheme_base = "#1575C7";
|
||||
set color_scheme = "complementary";
|
||||
|
||||
#NEWLAYER: haven/bluesplit_complementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Sevaeviel";
|
||||
layerinfo "redist_uniq" = "haven/bluesplit_complementary";
|
||||
|
||||
set color_scheme_base = "#1575C7";
|
||||
set color_scheme = "split_complementary";
|
||||
|
||||
#NEWLAYER: haven/bluedouble_complementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Glirewen";
|
||||
layerinfo "redist_uniq" = "haven/bluedouble_complementary";
|
||||
|
||||
set color_scheme_base = "#1575C7";
|
||||
set color_scheme = "double_complementary";
|
||||
|
||||
#NEWLAYER: haven/bluetriadic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Uloewiel";
|
||||
layerinfo "redist_uniq" = "haven/bluetriadic";
|
||||
|
||||
set color_scheme_base = "#1575C7";
|
||||
set color_scheme = "triadic";
|
||||
|
||||
#NEWLAYER: haven/bluetetradic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Yberawen";
|
||||
layerinfo "redist_uniq" = "haven/bluetetradic";
|
||||
|
||||
set color_scheme_base = "#1575C7";
|
||||
set color_scheme = "tetradic";
|
||||
|
||||
#NEWLAYER: haven/orangemonochromatic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Olerassa";
|
||||
layerinfo "redist_uniq" = "haven/orangemonochromatic";
|
||||
|
||||
set color_scheme_base = "#F3904E";
|
||||
set color_scheme = "monochromatic";
|
||||
|
||||
#NEWLAYER: haven/orangeanalogous
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Vardothiel";
|
||||
layerinfo "redist_uniq" = "haven/orangeanalogous";
|
||||
|
||||
set color_scheme_base = "#F3904E";
|
||||
set color_scheme = "analogous";
|
||||
|
||||
#NEWLAYER: haven/orangecomplementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Cadelaviel";
|
||||
layerinfo "redist_uniq" = "haven/orangecomplementary";
|
||||
|
||||
set color_scheme_base = "#F3904E";
|
||||
set color_scheme = "complementary";
|
||||
|
||||
#NEWLAYER: haven/orangesplit_complementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Eriralle";
|
||||
layerinfo "redist_uniq" = "haven/orangesplit_complementary";
|
||||
|
||||
set color_scheme_base = "#F3904E";
|
||||
set color_scheme = "split_complementary";
|
||||
|
||||
#NEWLAYER: haven/orangedouble_complementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Bemeth";
|
||||
layerinfo "redist_uniq" = "haven/orangedouble_complementary";
|
||||
|
||||
set color_scheme_base = "#F3904E";
|
||||
set color_scheme = "double_complementary";
|
||||
|
||||
#NEWLAYER: haven/orangetriadic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Welamma";
|
||||
layerinfo "redist_uniq" = "haven/orangetriadic";
|
||||
|
||||
set color_scheme_base = "#F3904E";
|
||||
set color_scheme = "triadic";
|
||||
|
||||
#NEWLAYER: haven/orangetetradic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Jerodia";
|
||||
layerinfo "redist_uniq" = "haven/orangetetradic";
|
||||
|
||||
set color_scheme_base = "#F3904E";
|
||||
set color_scheme = "tetradic";
|
||||
|
||||
#NEWLAYER: haven/greenmonochromatic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Cendarien";
|
||||
layerinfo "redist_uniq" = "haven/greenmonochromatic";
|
||||
|
||||
set color_scheme_base = "#48C754";
|
||||
set color_scheme = "monochromatic";
|
||||
|
||||
#NEWLAYER: haven/greenanalogous
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Wicarede";
|
||||
layerinfo "redist_uniq" = "haven/greenanalogous";
|
||||
|
||||
set color_scheme_base = "#48C754";
|
||||
set color_scheme = "analogous";
|
||||
|
||||
#NEWLAYER: haven/greencomplementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Laylla";
|
||||
layerinfo "redist_uniq" = "haven/greencomplementary";
|
||||
|
||||
set color_scheme_base = "#48C754";
|
||||
set color_scheme = "complementary";
|
||||
|
||||
#NEWLAYER: haven/greensplit_complementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Dwiama";
|
||||
layerinfo "redist_uniq" = "haven/greensplit_complementary";
|
||||
|
||||
set color_scheme_base = "#48C754";
|
||||
set color_scheme = "split_complementary";
|
||||
|
||||
#NEWLAYER: haven/greendouble_complementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Missi";
|
||||
layerinfo "redist_uniq" = "haven/greendouble_complementary";
|
||||
|
||||
set color_scheme_base = "#48C754";
|
||||
set color_scheme = "double_complementary";
|
||||
|
||||
#NEWLAYER: haven/greentriadic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Gwuwien";
|
||||
layerinfo "redist_uniq" = "haven/greentriadic";
|
||||
|
||||
set color_scheme_base = "#48C754";
|
||||
set color_scheme = "triadic";
|
||||
|
||||
#NEWLAYER: haven/greentetradic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Gerrathien";
|
||||
layerinfo "redist_uniq" = "haven/greentetradic";
|
||||
|
||||
set color_scheme_base = "#48C754";
|
||||
set color_scheme = "tetradic";
|
||||
|
||||
#NEWLAYER: haven/violetmonochromatic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Erudith";
|
||||
layerinfo "redist_uniq" = "haven/violetmonochromatic";
|
||||
|
||||
set color_scheme_base = "#9D1EC7";
|
||||
set color_scheme = "monochromatic";
|
||||
|
||||
#NEWLAYER: haven/violetanalogous
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Narwen";
|
||||
layerinfo "redist_uniq" = "haven/violetanalogous";
|
||||
|
||||
set color_scheme_base = "#9D1EC7";
|
||||
set color_scheme = "analogous";
|
||||
|
||||
#NEWLAYER: haven/violetcomplementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Yballan";
|
||||
layerinfo "redist_uniq" = "haven/violetcomplementary";
|
||||
|
||||
set color_scheme_base = "#9D1EC7";
|
||||
set color_scheme = "complementary";
|
||||
|
||||
#NEWLAYER: haven/violetsplit_complementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Araymwen";
|
||||
layerinfo "redist_uniq" = "haven/violetsplit_complementary";
|
||||
|
||||
set color_scheme_base = "#9D1EC7";
|
||||
set color_scheme = "split_complementary";
|
||||
|
||||
#NEWLAYER: haven/violetdouble_complementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Cydia";
|
||||
layerinfo "redist_uniq" = "haven/violetdouble_complementary";
|
||||
|
||||
set color_scheme_base = "#9D1EC7";
|
||||
set color_scheme = "double_complementary";
|
||||
|
||||
#NEWLAYER: haven/violettriadic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Eowiresa";
|
||||
layerinfo "redist_uniq" = "haven/violettriadic";
|
||||
|
||||
set color_scheme_base = "#9D1EC7";
|
||||
set color_scheme = "triadic";
|
||||
|
||||
#NEWLAYER: haven/violettetradic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Waedith";
|
||||
layerinfo "redist_uniq" = "haven/violettetradic";
|
||||
|
||||
set color_scheme_base = "#9D1EC7";
|
||||
set color_scheme = "tetradic";
|
||||
|
||||
#NEWLAYER: haven/yellowmonochromatic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Vauwen";
|
||||
layerinfo "redist_uniq" = "haven/yellowmonochromatic";
|
||||
|
||||
set color_scheme_base = "#F3EAA0";
|
||||
set color_scheme = "monochromatic";
|
||||
|
||||
#NEWLAYER: haven/yellowanalogous
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Praressi";
|
||||
layerinfo "redist_uniq" = "haven/yellowanalogous";
|
||||
|
||||
set color_scheme_base = "#F3EAA0";
|
||||
set color_scheme = "analogous";
|
||||
|
||||
#NEWLAYER: haven/yellowcomplementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Lelivia";
|
||||
layerinfo "redist_uniq" = "haven/yellowcomplementary";
|
||||
|
||||
set color_scheme_base = "#F3EAA0";
|
||||
set color_scheme = "complementary";
|
||||
|
||||
#NEWLAYER: haven/yellowsplit_complementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Afalewen";
|
||||
layerinfo "redist_uniq" = "haven/yellowsplit_complementary";
|
||||
|
||||
set color_scheme_base = "#F3EAA0";
|
||||
set color_scheme = "split_complementary";
|
||||
|
||||
#NEWLAYER: haven/yellowdouble_complementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Umoenna";
|
||||
layerinfo "redist_uniq" = "haven/yellowdouble_complementary";
|
||||
|
||||
set color_scheme_base = "#F3EAA0";
|
||||
set color_scheme = "double_complementary";
|
||||
|
||||
#NEWLAYER: haven/yellowtriadic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Trirwen";
|
||||
layerinfo "redist_uniq" = "haven/yellowtriadic";
|
||||
|
||||
set color_scheme_base = "#F3EAA0";
|
||||
set color_scheme = "triadic";
|
||||
|
||||
#NEWLAYER: haven/yellowtetradic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Jerilisien";
|
||||
layerinfo "redist_uniq" = "haven/yellowtetradic";
|
||||
|
||||
set color_scheme_base = "#F3EAA0";
|
||||
set color_scheme = "tetradic";
|
||||
|
||||
#NEWLAYER: haven/redmonochromatic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Ethowiel";
|
||||
layerinfo "redist_uniq" = "haven/redmonochromatic";
|
||||
|
||||
set color_scheme_base = "#F35951";
|
||||
set color_scheme = "monochromatic";
|
||||
|
||||
#NEWLAYER: haven/redanalogous
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Dwyweth";
|
||||
layerinfo "redist_uniq" = "haven/redanalogous";
|
||||
|
||||
set color_scheme_base = "#F35951";
|
||||
set color_scheme = "analogous";
|
||||
|
||||
#NEWLAYER: haven/redcomplementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Bylind";
|
||||
layerinfo "redist_uniq" = "haven/redcomplementary";
|
||||
|
||||
set color_scheme_base = "#F35951";
|
||||
set color_scheme = "complementary";
|
||||
|
||||
#NEWLAYER: haven/redsplit_complementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Qiradia";
|
||||
layerinfo "redist_uniq" = "haven/redsplit_complementary";
|
||||
|
||||
set color_scheme_base = "#F35951";
|
||||
set color_scheme = "split_complementary";
|
||||
|
||||
#NEWLAYER: haven/reddouble_complementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Kairawen";
|
||||
layerinfo "redist_uniq" = "haven/reddouble_complementary";
|
||||
|
||||
set color_scheme_base = "#F35951";
|
||||
set color_scheme = "double_complementary";
|
||||
|
||||
#NEWLAYER: haven/redtriadic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Piliwien";
|
||||
layerinfo "redist_uniq" = "haven/redtriadic";
|
||||
|
||||
set color_scheme_base = "#F35951";
|
||||
set color_scheme = "triadic";
|
||||
|
||||
#NEWLAYER: haven/redtetradic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Gwiradia";
|
||||
layerinfo "redist_uniq" = "haven/redtetradic";
|
||||
|
||||
set color_scheme_base = "#F35951";
|
||||
set color_scheme = "tetradic";
|
||||
|
||||
#NEWLAYER: haven/indigomonochromatic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Elirethiel";
|
||||
layerinfo "redist_uniq" = "haven/indigomonochromatic";
|
||||
|
||||
set color_scheme_base = "#6F60C7";
|
||||
set color_scheme = "monochromatic";
|
||||
|
||||
#NEWLAYER: haven/indigoanalogous
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Oneawia";
|
||||
layerinfo "redist_uniq" = "haven/indigoanalogous";
|
||||
|
||||
set color_scheme_base = "#6F60C7";
|
||||
set color_scheme = "analogous";
|
||||
|
||||
#NEWLAYER: haven/indigocomplementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Gwicia";
|
||||
layerinfo "redist_uniq" = "haven/indigocomplementary";
|
||||
|
||||
set color_scheme_base = "#6F60C7";
|
||||
set color_scheme = "complementary";
|
||||
|
||||
#NEWLAYER: haven/indigosplit_complementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Grabeth";
|
||||
layerinfo "redist_uniq" = "haven/indigosplit_complementary";
|
||||
|
||||
set color_scheme_base = "#6F60C7";
|
||||
set color_scheme = "split_complementary";
|
||||
|
||||
#NEWLAYER: haven/indigodouble_complementary
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Alalicien";
|
||||
layerinfo "redist_uniq" = "haven/indigodouble_complementary";
|
||||
|
||||
set color_scheme_base = "#6F60C7";
|
||||
set color_scheme = "double_complementary";
|
||||
|
||||
#NEWLAYER: haven/indigotriadic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Legeinia";
|
||||
layerinfo "redist_uniq" = "haven/indigotriadic";
|
||||
|
||||
set color_scheme_base = "#6F60C7";
|
||||
set color_scheme = "triadic";
|
||||
|
||||
#NEWLAYER: haven/indigotetradic
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Olowen";
|
||||
layerinfo "redist_uniq" = "haven/indigotetradic";
|
||||
|
||||
set color_scheme_base = "#6F60C7";
|
||||
set color_scheme = "tetradic";
|
||||
|
||||
161
livejournal/bin/upgrading/s2layers/i18nc/da1.s2
Executable file
@@ -0,0 +1,161 @@
|
||||
#-*-s2-*- ;; -*- coding: utf-8 -*-
|
||||
|
||||
layerinfo "type" = "i18nc";
|
||||
layerinfo "redist_uniq" = "i18nc/da1";
|
||||
layerinfo "name" = "Danish";
|
||||
layerinfo "langcode" = "da";
|
||||
layerinfo "author_name" = "LiveJournal Danish Translation Team";
|
||||
layerinfo "author_email" = "lj_dansk@livejournal.com";
|
||||
|
||||
layerinfo "source_viewable" = 1;
|
||||
|
||||
set lang_current = "da";
|
||||
|
||||
#[[ date and time l12n ]]
|
||||
|
||||
# Kort datoformat
|
||||
set lang_fmt_date_short = "%%d%%/%%m%%/%%yy%%";
|
||||
# Mellem dato
|
||||
set lang_fmt_date_med = "%%dayord%% %%mon%%., %%yyyy%%";
|
||||
# Mellem dato med forkortet ugedag
|
||||
set lang_fmt_date_med_day = "%%da%%, d. %%dayord%% %%mon%%., %%yyyy%%";
|
||||
# Lang dato
|
||||
set lang_fmt_date_long = "%%dayord%% %%month%%, %%yyyy%%";
|
||||
# Lang dato med ugedag
|
||||
set lang_fmt_date_long_day = "%%day%%, d. %%dayord%% %%month%%, %%yyyy%%";
|
||||
# Tidsformat
|
||||
set lang_fmt_time_short = "%%HH%%:%%min%%";
|
||||
# Kort månedsformat (samme som engelsk)
|
||||
set lang_fmt_month_short = "%%m%%/%%yy%%";
|
||||
# Mellem måned (samme som engelsk)
|
||||
set lang_fmt_month_med = "%%mon%% %%yyyy%%";
|
||||
# Lang måned (samme som engelsk)
|
||||
set lang_fmt_month_long = "%%month%% %%yyyy%%";
|
||||
# Årets måneder, lang
|
||||
set lang_monthname_long = [ "", "Januar", "Februar", "Marts",
|
||||
"April", "Maj", "Juni",
|
||||
"Juli", "August", "September",
|
||||
"Oktober", "November", "December" ];
|
||||
# Årets måneder, kort
|
||||
set lang_monthname_short = [ "", "Jan", "Feb", "Mar",
|
||||
"Apr", "Maj", "Jun",
|
||||
"Jul", "Aug", "Sep",
|
||||
"Okt", "Nov", "Dec" ];
|
||||
# Ugens dage, lang
|
||||
set lang_dayname_long = [ "", "Søndag", "Mandag", "Tirsdag", "Onsdag",
|
||||
"Torsdag", "Fredag", "Lørdag" ];
|
||||
# Ugens dage, kort
|
||||
set lang_dayname_short = [ "", "Søn", "Man", "Tirs", "Ons",
|
||||
"Tors", "Fre", "Lør" ];
|
||||
set reg_firstdayofweek = "monday";
|
||||
|
||||
#[[ texttranslation ]]
|
||||
|
||||
# Currents
|
||||
set text_meta_music = "Nuværende musik";
|
||||
set text_meta_mood = "Nuværende humør";
|
||||
# Comments
|
||||
set text_post_comment = "Skriv kommentar";
|
||||
set text_read_comments = "1 kommentar // # kommentarer";
|
||||
set text_post_comment_friends = "Skriv kommentar";
|
||||
set text_read_comments_friends = "1 kommentar // # kommentarer";
|
||||
# Skiplinks
|
||||
set text_skiplinks_back="Forrige #";
|
||||
set text_skiplinks_forward="Næste #";
|
||||
# Views
|
||||
set text_view_recent = "Seneste poster";
|
||||
set text_view_friends = "Venner";
|
||||
set text_view_archive = "Arkiv";
|
||||
set text_view_userinfo = "Brugerinfo";
|
||||
set text_view_month = "Vis emner"; # "Vis overskrifter"?
|
||||
# Misc. texts
|
||||
set text_nosubject = "(intet emne)";
|
||||
set text_noentries_recent = "Der er ingen poster at vise.";
|
||||
set text_noentries_day = "Der blev ikke skrevet nogle poster denne dag.";
|
||||
set text_permalink = "Link";
|
||||
set text_month_screened_comments = "m. skærmede";
|
||||
set text_multiform_check = "Vælg:";
|
||||
set text_multiform_des = "Massehandling på valgte kommentarer:";
|
||||
set text_multiform_btn = "Udfør handling";
|
||||
set text_multiform_opt_unscreen = "Afskærm";
|
||||
set text_multiform_opt_screen = "Skærm";
|
||||
set text_multiform_opt_delete = "Slet";
|
||||
set text_multiform_conf_delete = "Slet valgte kommentarer?";
|
||||
set text_day_prev = "Forrige dag";
|
||||
set text_day_next = "Næste dag";
|
||||
set text_comment_from = "Fra:";
|
||||
set text_comment_date = "Dato:";
|
||||
set text_comment_ipaddr = "IP adresse:";
|
||||
set text_comment_reply = "Svar";
|
||||
set text_comment_parent = "Forælder";
|
||||
set text_comment_thread = "Tråd";
|
||||
set text_reply_back = "Læs kommentarer";
|
||||
set text_reply_nocomments_header = "Kommentarer slået fra:";
|
||||
set text_reply_nocomments = "Kommentarer til denne post er blevet slået fra.";
|
||||
set text_poster_anonymous = "(Anonym)";
|
||||
set text_website_default_name = "Mit websted";
|
||||
|
||||
#[[ function translations ]]
|
||||
|
||||
# Samme som engelsk:
|
||||
#function lang_map_plural (int n) : int {
|
||||
# if ($n == 1) { return 0; } # singular
|
||||
# return 1; # plural
|
||||
#}
|
||||
|
||||
function lang_page_of_pages (int pg, int pgs) [notags] : string {
|
||||
return "Side $pg af $pgs";
|
||||
}
|
||||
|
||||
function lang_ordinal(int num) [notags] : string {
|
||||
return $num+".";
|
||||
}
|
||||
|
||||
function lang_user_wrote(UserLite u) : string
|
||||
"Returns text describing that the user wrote something. i18nc layers should override this."
|
||||
{
|
||||
if (defined $u) {
|
||||
return $u->as_string()+" skrev";
|
||||
}
|
||||
else {
|
||||
return "En anonym bruger skrev";
|
||||
}
|
||||
}
|
||||
|
||||
function lang_at_datetime(DateTime d) : string
|
||||
"Returns a string saying \"at {the data and time given}\". Used in the core implementation of EntryPage and ReplyPage. i18nc layers should override this."
|
||||
{
|
||||
# return "d. 1. Januar, 2004, kl. 23:01";
|
||||
return "d. " + $d->date_format("long") + ", kl. " + $d->time_format();
|
||||
}
|
||||
### Ovenstående skal testes i brug ASAP. ###
|
||||
|
||||
function lang_viewname(string viewid) [notags] : string
|
||||
"Get some words representing a view"
|
||||
{
|
||||
if ($viewid == "recent") { return $*text_view_recent; }
|
||||
if ($viewid == "archive") { return $*text_view_archive; }
|
||||
if ($viewid == "friends") { return $*text_view_friends; }
|
||||
if ($viewid == "day") { return "Dag"; }
|
||||
if ($viewid == "month") { return "Måned"; }
|
||||
if ($viewid == "userinfo") { return $*text_view_userinfo; }
|
||||
if ($viewid == "entry") { return "Læs kommentarer"; }
|
||||
if ($viewid == "reply") { return "Skriv kommentar"; }
|
||||
return "Ukendt visningstype";
|
||||
}
|
||||
|
||||
function server_sig() {
|
||||
"""Kørt af <a href="$*SITEROOT/">$*SITENAME</a>""";
|
||||
}
|
||||
|
||||
function ReplyPage::view_title() : string {
|
||||
return "Skriv kommentar";
|
||||
}
|
||||
|
||||
function Page::print_entry_poster(Entry e) {
|
||||
$e.poster->print();
|
||||
if ($.view == "friends" and $e.poster.username != $e.journal.username) {
|
||||
" skrev i ";
|
||||
$e.journal->print();
|
||||
}
|
||||
}
|
||||
147
livejournal/bin/upgrading/s2layers/i18nc/de1.s2
Executable file
@@ -0,0 +1,147 @@
|
||||
#-*-s2-*- ;; -*- coding: utf-8 -*-
|
||||
|
||||
layerinfo "type" = "i18nc";
|
||||
layerinfo "redist_uniq" = "i18nc/de1";
|
||||
layerinfo "name" = "German";
|
||||
layerinfo "langcode" = "de";
|
||||
layerinfo "author_name" = "Timwi";
|
||||
layerinfo "author_email" = "timwi@livejournal.com";
|
||||
|
||||
layerinfo "source_viewable" = 1;
|
||||
|
||||
set lang_current = "de";
|
||||
|
||||
# Kurzes Datumsformat
|
||||
set lang_fmt_date_short = "%%d%%.%%m%%.%%yy%%";
|
||||
# Mittellanges Datumsformat
|
||||
set lang_fmt_date_med = "%%dayord%% %%mon%% %%yyyy%%";
|
||||
# Mittellanges Datumsformat mit Wochentag
|
||||
set lang_fmt_date_med_day = "%%da%%, %%dayord%% %%mon%% %%yyyy%%";
|
||||
# Langes Datumsformat
|
||||
set lang_fmt_date_long = "%%dayord%% %%month%% %%yyyy%%";
|
||||
# Langes Datumsformat mit Wochentag
|
||||
set lang_fmt_date_long_day = "%%day%%, %%dayord%% %%month%% %%yyyy%%";
|
||||
# Zeitformat
|
||||
set lang_fmt_time_short = "%%HH%%:%%min%%";
|
||||
# Kurzes Monatsformat
|
||||
#set lang_fmt_month_short = "%%mon%% %%yy%%";
|
||||
# Mittleres Monatsformat
|
||||
#set lang_fmt_month_med = "%%mon%% %%yyyy%%";
|
||||
# Langes Monatsformat
|
||||
#set lang_fmt_month_long = "%%month%% %%yyyy%%";
|
||||
# Monatsnamen
|
||||
set lang_monthname_long = [ "", "Januar", "Februar", "März",
|
||||
"April", "Mai", "Juni",
|
||||
"Juli", "August", "September",
|
||||
"Oktober", "November", "Dezember" ];
|
||||
# Monatsabkürzungen
|
||||
set lang_monthname_short = [ "", "Jan", "Feb", "Mär",
|
||||
"Apr", "Mai", "Jun",
|
||||
"Jul", "Aug", "Sep",
|
||||
"Okt", "Nov", "Dez" ];
|
||||
# Wochentagnamen
|
||||
set lang_dayname_long = [ "", "Sonntag", "Montag", "Dienstag", "Mittwoch",
|
||||
"Donnerstag", "Freitag", "Samstag" ];
|
||||
# Wochentagabkürzungen
|
||||
set lang_dayname_short = [ "", "So", "Mo", "Di", "Mi",
|
||||
"Do", "Fr", "Sa" ];
|
||||
set reg_firstdayofweek = "monday";
|
||||
|
||||
#[[ texttranslation ]]
|
||||
|
||||
# Currents
|
||||
set text_meta_music = "Aktuelle Musik";
|
||||
set text_meta_mood = "Aktuelle Stimmung";
|
||||
# Comments
|
||||
set text_post_comment = "Kommentar hinterlassen";
|
||||
set text_read_comments = "1 Kommentar // # Kommentare";
|
||||
set text_post_comment_friends = "Kommentar hinterlassen";
|
||||
set text_read_comments_friends = "1 Kommentar // # Kommentare";
|
||||
# Skiplinks
|
||||
set text_skiplinks_back="Vorherige #";
|
||||
set text_skiplinks_forward="Nächste #";
|
||||
# Views
|
||||
set text_view_recent = "Neueste Einträge";
|
||||
set text_view_friends = "Freunde";
|
||||
set text_view_archive = "Archiv";
|
||||
set text_view_userinfo = "Benutzerprofil";
|
||||
set text_view_month = "Monatsansicht"; # "Vis overskrifter"?
|
||||
# Misc. texts
|
||||
set text_nosubject = "(kein Betreff)";
|
||||
set text_noentries_recent = "Keine Einträge.";
|
||||
set text_noentries_day = "An diesem Tag wurden keine Einträge gemacht.";
|
||||
set text_permalink = "Link";
|
||||
set text_month_screened_comments = "zzgl. verdeckte";
|
||||
set text_multiform_check = "Auswählen:";
|
||||
set text_multiform_des = "Alle ausgewählten Kommentare:";
|
||||
set text_multiform_btn = "Ausführen";
|
||||
set text_multiform_opt_unscreen = "Aufdecken";
|
||||
set text_multiform_opt_screen = "Verdecken";
|
||||
set text_multiform_opt_delete = "Löschen";
|
||||
set text_multiform_conf_delete = "Bist du dir sicher, dass du die ausgewählten Kommentare löschen möchtest?";
|
||||
set text_day_prev = "Vorheriger Tag";
|
||||
set text_day_next = "Nächster Tag";
|
||||
set text_comment_from = "Von:";
|
||||
set text_comment_date = "Datum:";
|
||||
set text_comment_ipaddr = "IP-Adresse:";
|
||||
set text_comment_reply = "Darauf antworten";
|
||||
set text_comment_parent = "Kommentar davor";
|
||||
set text_comment_thread = "Nachfolgende Kommentare";
|
||||
set text_reply_back = "Kommentare lesen";
|
||||
set text_reply_nocomments_header = "Kommentarfunktion deaktiviert:";
|
||||
set text_reply_nocomments = "Für diesen Eintrag wurde die Kommentarfunktion deaktiviert.";
|
||||
set text_website_default_name = "Meine Webseite";
|
||||
set text_poster_anonymous = "(Anonym)";
|
||||
|
||||
#[[ function translations ]]
|
||||
|
||||
function lang_page_of_pages (int pg, int pgs) [notags] : string {
|
||||
return "Seite $pg von $pgs";
|
||||
}
|
||||
|
||||
function lang_ordinal(int num) [notags] : string {
|
||||
return $num+".";
|
||||
}
|
||||
|
||||
function lang_viewname(string viewid) [notags] : string
|
||||
"Get some words representing a view"
|
||||
{
|
||||
if ($viewid == "recent") { return $*text_view_recent; }
|
||||
if ($viewid == "archive") { return $*text_view_archive; }
|
||||
if ($viewid == "friends") { return $*text_view_friends; }
|
||||
if ($viewid == "day") { return "Tag"; }
|
||||
if ($viewid == "month") { return "Monat"; }
|
||||
if ($viewid == "userinfo") { return $*text_view_userinfo; }
|
||||
if ($viewid == "entry") { return "Kommentare lesen"; }
|
||||
if ($viewid == "reply") { return "Kommentar hinterlassen"; }
|
||||
return "Unbekannte Ansicht";
|
||||
}
|
||||
|
||||
function ReplyPage::view_title() : string {
|
||||
return "Kommentar hinterlassen";
|
||||
}
|
||||
|
||||
function server_sig() {
|
||||
"""Gehostet von <a href="$*SITEROOT/">$*SITENAME</a>""";
|
||||
}
|
||||
|
||||
function Page::print_entry_poster(Entry e) {
|
||||
$e.poster->print();
|
||||
if ($.view == "friends" and $e.poster.username != $e.journal.username) {
|
||||
" schrieb in ";
|
||||
$e.journal->print();
|
||||
}
|
||||
}
|
||||
|
||||
function lang_user_wrote(UserLite u) : string "Returns text describing that the user wrote something. i18nc layers should override this." {
|
||||
if (defined $u) {
|
||||
return $u->as_string()+" schrieb";
|
||||
}
|
||||
else {
|
||||
return "Ein anonymer Benutzer schrieb";
|
||||
}
|
||||
}
|
||||
|
||||
function lang_at_datetime(DateTime d) : string "Returns a string saying \"at {the date and time given}\". Used in the core implementation of EntryPage and ReplyPage. i18nc layers should override this." {
|
||||
return "am " + $d->date_format("long") + " um " + $d->time_format();
|
||||
}
|
||||
9
livejournal/bin/upgrading/s2layers/i18nc/en1.s2
Executable file
@@ -0,0 +1,9 @@
|
||||
#-*-s2-*-
|
||||
|
||||
layerinfo "type" = "i18nc";
|
||||
layerinfo "redist_uniq" = "i18nc/en1";
|
||||
layerinfo "name" = "English";
|
||||
layerinfo "langcode" = "en";
|
||||
|
||||
# Note: this file doesn't actually override anything, since the core
|
||||
# is in English
|
||||
139
livejournal/bin/upgrading/s2layers/i18nc/eo1.s2
Executable file
@@ -0,0 +1,139 @@
|
||||
#-*-s2-*- ;; -*- coding: utf-8 -*-
|
||||
|
||||
layerinfo "type" = "i18nc";
|
||||
layerinfo "redist_uniq" = "i18nc/eo1";
|
||||
layerinfo "name" = "Esperanto";
|
||||
layerinfo "langcode" = "eo";
|
||||
layerinfo "author_name" = "Timwi, Amuzulo";
|
||||
layerinfo "author_email" = "timwi@livejournal.com, amuzulo@livejournal.com";
|
||||
|
||||
layerinfo "source_viewable" = 1;
|
||||
|
||||
set lang_current = "eo";
|
||||
|
||||
set lang_fmt_date_short = "%%yyyy%%-%%mm%%-%%dd%%";
|
||||
set lang_fmt_date_med = "%%dayord%% de %%mon%% %%yyyy%%";
|
||||
set lang_fmt_date_med_day = "%%da%%, la %%dayord%% de %%mon%% %%yyyy%%";
|
||||
set lang_fmt_date_long = "la %%dayord%% de %%month%% %%yyyy%%";
|
||||
set lang_fmt_date_long_day = "%%day%%, la %%dayord%% de %%month%% %%yyyy%%";
|
||||
|
||||
set lang_fmt_time_short = "%%HH%%:%%min%%";
|
||||
set lang_fmt_month_short = "%%mon%% %%yy%%";
|
||||
set lang_fmt_month_med = "%%mon%% %%yyyy%%";
|
||||
set lang_fmt_month_long = "%%month%% %%yyyy%%";
|
||||
|
||||
set lang_monthname_long = [ "", "januaro", "februaro", "marto",
|
||||
"aprilo", "majo", "junio",
|
||||
"julio", "aŭgusto", "septembro",
|
||||
"oktobro", "novembro", "decembro" ];
|
||||
|
||||
set lang_monthname_short = [ "", "jan", "feb", "mar",
|
||||
"apr", "maj", "jun",
|
||||
"jul", "aŭg", "sep",
|
||||
"okt", "nov", "dec" ];
|
||||
|
||||
set lang_dayname_long = [ "", "dimanĉo", "lundo", "mardo", "merkredo",
|
||||
"ĵaŭdo", "vendredo", "sabato" ];
|
||||
|
||||
set lang_dayname_short = [ "", "di", "lu", "ma", "me",
|
||||
"ĵa", "ve", "sa" ];
|
||||
set reg_firstdayofweek = "monday";
|
||||
|
||||
#[[ texttranslation ]]
|
||||
|
||||
# Currents
|
||||
set text_meta_music = "Nuna muziko";
|
||||
set text_meta_mood = "Nuna humoro";
|
||||
# Comments
|
||||
set text_post_comment = "Afiŝu novan komenton";
|
||||
set text_read_comments = "1 komento // # komentoj";
|
||||
set text_post_comment_friends = "Afiŝu novan komenton";
|
||||
set text_read_comments_friends = "1 komento // # komentoj";
|
||||
# Skiplinks
|
||||
set text_skiplinks_back="# antaŭaj komentoj";
|
||||
set text_skiplinks_forward="# sekvontaj komentoj";
|
||||
# Views
|
||||
set text_view_recent = "Lastatempaj enskribojn";
|
||||
set text_view_friends = "Geamikoj";
|
||||
set text_view_archive = "Arĥivo";
|
||||
set text_view_userinfo = "Uzantinformoj";
|
||||
set text_view_month = "Monataj temoj";
|
||||
# Misc. texts
|
||||
set text_nosubject = "(neniu temo)";
|
||||
set text_noentries_recent = "Neniuj enskriboj.";
|
||||
set text_noentries_day = "Ekzistas neniuj enskriboj en tiu tago.";
|
||||
set text_permalink = "Ligilo";
|
||||
set text_month_screened_comments = "+ kaŝitoj";
|
||||
set text_multiform_check = "Elektu:";
|
||||
set text_multiform_des = "Amasagado por elektitaj komentoj:";
|
||||
set text_multiform_btn = "Agu";
|
||||
set text_multiform_opt_unscreen = "Malkaŝu";
|
||||
set text_multiform_opt_screen = "Kaŝu";
|
||||
set text_multiform_opt_delete = "Forigu";
|
||||
set text_multiform_conf_delete = "Ĉu vi certas ke vi viŝas forigi la elektitajn komentojn?";
|
||||
set text_day_prev = "Antaŭa tago";
|
||||
set text_day_next = "Sekvonta tago";
|
||||
set text_comment_from = "De:";
|
||||
set text_comment_date = "Dato:";
|
||||
set text_comment_ipaddr = "IP-adreso:";
|
||||
set text_comment_reply = "Respondu al ĉi tiu";
|
||||
set text_comment_parent = "Patro";
|
||||
set text_comment_thread = "Fadeno";
|
||||
set text_reply_back = "Legu komentojn";
|
||||
set text_reply_nocomments_header = "Komentoj malebligitaj:";
|
||||
set text_reply_nocomments = "La uzanto malebligis komentojn por ĉi tiu enskribo.";
|
||||
set text_website_default_name = "Mia TTT-ejo";
|
||||
set text_poster_anonymous = "(sennoma)";
|
||||
|
||||
#[[ function translations ]]
|
||||
|
||||
function lang_page_of_pages (int pg, int pgs) [notags] : string {
|
||||
return "Paĝo $pg da $pgs";
|
||||
}
|
||||
|
||||
function lang_ordinal(int num) [notags] : string {
|
||||
return $num + "-a";
|
||||
}
|
||||
|
||||
function lang_viewname(string viewid) [notags] : string
|
||||
"Get some words representing a view"
|
||||
{
|
||||
if ($viewid == "recent") { return $*text_view_recent; }
|
||||
if ($viewid == "archive") { return $*text_view_archive; }
|
||||
if ($viewid == "friends") { return $*text_view_friends; }
|
||||
if ($viewid == "day") { return "Tago"; }
|
||||
if ($viewid == "month") { return "Monato"; }
|
||||
if ($viewid == "userinfo") { return $*text_view_userinfo; }
|
||||
if ($viewid == "entry") { return "Legu komentojn"; }
|
||||
if ($viewid == "reply") { return "Afiŝu komenton"; }
|
||||
return "Nekonata vido";
|
||||
}
|
||||
|
||||
function ReplyPage::view_title() : string {
|
||||
return "Afiŝu komenton";
|
||||
}
|
||||
|
||||
function server_sig() {
|
||||
"""Funkciigita de <a href="$*SITEROOT/">$*SITENAME</a>""";
|
||||
}
|
||||
|
||||
function Page::print_entry_poster(Entry e) {
|
||||
$e.poster->print();
|
||||
if ($.view == "friends" and $e.poster.username != $e.journal.username) {
|
||||
" skribis en ";
|
||||
$e.journal->print();
|
||||
}
|
||||
}
|
||||
|
||||
function lang_user_wrote(UserLite u) : string "Returns text describing that the user wrote something. i18nc layers should override this." {
|
||||
if (defined $u) {
|
||||
return $u->as_string()+" skribis";
|
||||
}
|
||||
else {
|
||||
return "Sennoma uzanto skribis";
|
||||
}
|
||||
}
|
||||
|
||||
function lang_at_datetime(DateTime d) : string "Returns a string saying \"at {the date and time given}\". Used in the core implementation of EntryPage and ReplyPage. i18nc layers should override this." {
|
||||
return "je " + $d->date_format("long") + " je " + $d->time_format();
|
||||
}
|
||||
171
livejournal/bin/upgrading/s2layers/i18nc/fi1.s2
Executable file
@@ -0,0 +1,171 @@
|
||||
#-*-s2-*- ;; -*- coding: utf-8 -*-
|
||||
|
||||
layerinfo "type" = "i18nc";
|
||||
layerinfo "redist_uniq" = "i18nc/fi1";
|
||||
layerinfo "name" = "Finnish";
|
||||
layerinfo "langcode" = "fi";
|
||||
layerinfo "author_name" = "shiningkianna, zell_d";
|
||||
|
||||
layerinfo "source_viewable" = 1;
|
||||
|
||||
set lang_current = "fi";
|
||||
|
||||
# Ajat ja päiväykset
|
||||
|
||||
# Viikonpäivät
|
||||
set lang_dayname_long = [ "", "sunnuntai", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai" ];
|
||||
set lang_dayname_short = [ "", "su", "ma", "ti", "ke", "to", "pe", "la" ];
|
||||
|
||||
# Pitkä päiväys
|
||||
set lang_fmt_date_long = "%%dayord%% %%month%%ta %%yyyy%%";
|
||||
# Pitkä päiväys viikonpäivällä
|
||||
set lang_fmt_date_long_day = "%%day%%, %%dayord%% %%month%%ta %%yyyy%%";
|
||||
# Keskipitkä päiväys
|
||||
set lang_fmt_date_med = "%%d%%. %%mon%%. %%yyyy%%";
|
||||
# Keskipitkä päiväys viikonpäivällä
|
||||
set lang_fmt_date_med_day = "%%da%%, %%dayord%% %%mon%%. %%yyyy%%";
|
||||
# Lyhyt päiväys
|
||||
set lang_fmt_date_short = "%%d%%.%%m%%.%%yyyy%%";
|
||||
# Pitkä kuukausipäiväys
|
||||
set lang_fmt_month_long = "%%month%% %%yyyy%%";
|
||||
# Keskipitkä kuukausipäiväys
|
||||
set lang_fmt_month_med = "%%mon%% %%yyyy%%";
|
||||
# Lyhyt kuukausipäiväys
|
||||
set lang_fmt_month_short = "%%m%%/%%yyyy%%";
|
||||
# Aika
|
||||
set lang_fmt_time_short ="%%HH%%:%%min%%";
|
||||
|
||||
# Kuukaudet
|
||||
set lang_monthname_long = [ "", "tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu" ];
|
||||
set lang_monthname_short = [ "", "tammik", "helmik", "maalisk", "huhtik", "toukok", "kesäk", "heinäk", "elok", "syysk", "lokak", "marrask", "jouluk" ];
|
||||
|
||||
# Viikko alkaa maanantaista
|
||||
set reg_firstdayofweek = "monday";
|
||||
|
||||
|
||||
# Tekstit
|
||||
|
||||
# Tämänhetkinen musiikki ja mieliala
|
||||
set text_meta_mood = "Mieliala";
|
||||
set text_meta_music = "Musiikki";
|
||||
# Kommentit
|
||||
set text_post_comment = "Jätä vastaus tähän";
|
||||
set text_post_comment_friends = "Jätä vastaus tähän";
|
||||
set text_read_comments = "1 kommentti // # kommenttia";
|
||||
set text_read_comments_friends = "1 kommentti // # kommenttia";
|
||||
# Linkit, joilla hypätään viestien yli
|
||||
set text_skiplinks_back = "Edelliset #";
|
||||
set text_skiplinks_forward = "Seuraavat #";
|
||||
# Näkymät
|
||||
set text_view_archive = "Arkisto";
|
||||
set text_view_friends = "Kaverit";
|
||||
set text_view_friends_comm = "Jäsenet";
|
||||
set text_view_friends_filter = "Kaverit (mukautettu suodatin)";
|
||||
set text_view_friendsfriends = "Kavereiden kaverit";
|
||||
set text_view_friendsfriends_filter = "Kavereiden kaverit (mukautettu suodatin)";
|
||||
set text_view_month = "Otsikot";
|
||||
set text_view_recent = "Merkinnät";
|
||||
set text_view_userinfo = "Käyttäjätiedot";
|
||||
# Sekalaisia tekstejä
|
||||
set text_comment_date = "Päiväys:";
|
||||
set text_comment_from = "Lähettäjä:";
|
||||
set text_comment_frozen = "Jäädytetty";
|
||||
set text_comment_ipaddr = "IP-osoite:";
|
||||
set text_comment_parent = "Ylempi";
|
||||
set text_comment_reply = "Vastaa";
|
||||
set text_comment_thread = "Viestiketju";
|
||||
set text_day_next = "Seuraava päivä";
|
||||
set text_day_prev = "Edellinen päivä";
|
||||
set text_max_comments = "Maksimimäärä kommentteja saatu";
|
||||
set text_month_screened_comments = "ja peitettyjä kommentteja";
|
||||
set text_multiform_btn = "Muokkaa";
|
||||
set text_multiform_check = "Valitse:";
|
||||
set text_multiform_conf_delete = "Poista valitut kommentit?";
|
||||
set text_multiform_des = "Muokkaa kaikkia valittuja kommentteja:";
|
||||
set text_multiform_opt_delete = "Poista";
|
||||
set text_multiform_opt_freeze = "Jäädytä";
|
||||
set text_multiform_opt_screen = "Peitä";
|
||||
set text_multiform_opt_unfreeze = "Poista jäädytys";
|
||||
set text_multiform_opt_unscreen = "Poista peitto";
|
||||
set text_noentries_day = "Kyseisenä päivänä ei tehty merkintöjä";
|
||||
set text_noentries_recent = "Ei merkintöjä";
|
||||
set text_nosubject = "(ei otsikkoa)";
|
||||
set text_permalink = "Linkki";
|
||||
set text_poster_anonymous = "(tuntematon)";
|
||||
set text_reply_back = "Lue kommentteja";
|
||||
set text_reply_nocomments = "Kommentointi on estetty tämän merkinnän kohdalla";
|
||||
set text_reply_nocomments_header = "Kommentointi estetty:";
|
||||
set text_website_default_name = "Kotisivut";
|
||||
|
||||
|
||||
# Funktiot
|
||||
|
||||
|
||||
# Antaa eri tuloksen riippuen siitä tuleeko tekstiä käsitellä yksikkönä vai monikkona
|
||||
function lang_map_plural (int n) : int {
|
||||
if ($n == 1) { return 0; } # singular
|
||||
return 1; # plural
|
||||
}
|
||||
|
||||
# Palauttaa tekstin "Sivu X/Y", esim. Sivu 3/5
|
||||
function lang_page_of_pages (int pg, int pgs) [notags] : string {
|
||||
return "Sivu $pg/$pgs";
|
||||
}
|
||||
|
||||
# Tekee numerosta järjestysnumeron, eli laittaa numeron perään pisteen
|
||||
function lang_ordinal(int num) : string {
|
||||
return $num+".";
|
||||
}
|
||||
|
||||
# Palauttaa tekstin joka kertoo millainen näkymä on kyseessä
|
||||
function lang_viewname(string viewid) [notags] : string "Get some words representing a view" {
|
||||
if ($viewid == "recent") { return $*text_view_recent; }
|
||||
if ($viewid == "archive") { return $*text_view_archive; }
|
||||
if ($viewid == "friends") { return $*text_view_friends; }
|
||||
if ($viewid == "day") { return "Päivä"; }
|
||||
if ($viewid == "month") { return "Kuukausi"; }
|
||||
if ($viewid == "userinfo") { return $*text_view_userinfo; }
|
||||
if ($viewid == "entry") { return "Lue kommentteja"; }
|
||||
if ($viewid == "reply") { return "Jätä kommentti"; }
|
||||
return "Tuntematon näkymä";
|
||||
}
|
||||
|
||||
# Vastaussivun otsikko
|
||||
function ReplyPage::view_title() : string {
|
||||
return "Jätä kommentti";
|
||||
}
|
||||
|
||||
# Kirjoittaa palvelimen allekirjoituksen,
|
||||
# Esim. "Sivun tarjoaa LiveJournal.com"
|
||||
function server_sig() {
|
||||
"""Sivun tarjoaa <a href="$*SITEROOT/">$*SITENAME</a>""";
|
||||
}
|
||||
|
||||
# Kirjoittaa kaverisivulla tekstin, joka kertoo missä yhteisössä joku kirjoitti jotakin,
|
||||
# Esim. "Esimerkkilähettäjä kirjoitti yhteisössä esimerkkiyhteisö"
|
||||
function Page::print_entry_poster(Entry e) {
|
||||
$e.poster->print();
|
||||
if ($.view == "friends" and $e.poster.username != $e.journal.username) {
|
||||
" kirjoitti yhteisössä ";
|
||||
$e.journal->print();
|
||||
}
|
||||
}
|
||||
|
||||
# Palauttaa tekstin joka kertoo että joku kirjoitti,
|
||||
# Esim. "Esimerkkikäyttäjä kirjoitti" tai "Tuntematon käyttäjä kirjoitti"
|
||||
function lang_user_wrote(UserLite u) : string "Returns text describing that the user wrote something. i18nc layers should override this." {
|
||||
if (defined $u) {
|
||||
return $u->as_string()+" kirjoitti";
|
||||
}
|
||||
else {
|
||||
return "Tuntematon käyttäjä kirjoitti";
|
||||
}
|
||||
}
|
||||
|
||||
# Palauttaa tekstin joka ilmoittaa päiväyksen ja kellonajan,
|
||||
# Esim. "3. lokakuuta 2004 kello 14:45"
|
||||
function lang_at_datetime(DateTime d) : string "Returns a string saying \"at {the date and time given}\". Used in the core implementation of EntryPage and ReplyPage. i18nc layers should override this." {
|
||||
return $d->date_format("long") + " kello " + $d->time_format();
|
||||
}
|
||||
|
||||
|
||||
144
livejournal/bin/upgrading/s2layers/i18nc/fr1.s2
Executable file
@@ -0,0 +1,144 @@
|
||||
#-*-s2-*- ;; -*- coding: utf-8 -*-
|
||||
|
||||
layerinfo "type" = "i18nc";
|
||||
layerinfo "redist_uniq" = "i18nc/fr1";
|
||||
layerinfo "name" = "French";
|
||||
layerinfo "langcode" = "fr";
|
||||
layerinfo "author_name" = "Timwi, Diziet Sma, Eclips1st";
|
||||
layerinfo "author_email" = "timwi@livejournal.com, dizietsma@livejournal.com, eclips1st@livejournal.com";
|
||||
|
||||
layerinfo "source_viewable" = 1;
|
||||
|
||||
set lang_current = "fr";
|
||||
|
||||
set lang_fmt_date_short = "%%d%% %%mon%% %%yy%%";
|
||||
set lang_fmt_date_med = "%%dd%% %%mon%% %%yyyy%%";
|
||||
set lang_fmt_date_med_day = "%%da%%, le %%dd%% %%mon%% %%yyyy%%";
|
||||
set lang_fmt_date_long = "le %%dd%% %%month%% %%yyyy%%";
|
||||
set lang_fmt_date_long_day = "%%day%%, le %%dd%% %%month%% %%yyyy%%";
|
||||
set lang_fmt_time_short = "%%HH%%:%%min%%";
|
||||
set lang_fmt_month_short = "%%mon%% %%yy%%";
|
||||
set lang_fmt_month_med = "%%mon%% %%yyyy%%";
|
||||
set lang_fmt_month_long = "%%month%% %%yyyy%%";
|
||||
|
||||
set lang_monthname_long = [ "", "janvier", "février", "mars",
|
||||
"avril", "mai", "juin",
|
||||
"juillet", "août", "septembre",
|
||||
"octobre", "novembre", "décembre" ];
|
||||
|
||||
set lang_monthname_short = [ "", "jan", "fév", "mar",
|
||||
"avr", "mai", "juin",
|
||||
"juil", "aoû", "sep",
|
||||
"oct", "nov", "déc" ];
|
||||
|
||||
set lang_dayname_long = [ "", "dimanche", "lundi", "mardi", "mercredi",
|
||||
"jeudi", "vendredi", "samedi" ];
|
||||
|
||||
set lang_dayname_short = [ "", "dim", "lun", "mar", "mer",
|
||||
"jeu", "ven", "sam" ];
|
||||
set reg_firstdayofweek = "monday";
|
||||
|
||||
#[[ texttranslation ]]
|
||||
|
||||
# Currents
|
||||
set text_meta_music = "Musique actuelle";
|
||||
set text_meta_mood = "Humeur actuelle";
|
||||
# Comments
|
||||
set text_post_comment = "Envoyez un commentaire";
|
||||
set text_read_comments = "1 commentaire // # commentaires";
|
||||
set text_post_comment_friends = "Envoyez un commentaire";
|
||||
set text_read_comments_friends = "1 commentaire // # commentaires";
|
||||
# Skiplinks
|
||||
set text_skiplinks_back="# entrées précédentes";
|
||||
set text_skiplinks_forward="# entrées suivantes";
|
||||
# Views
|
||||
set text_view_recent = "Entrées récentes";
|
||||
set text_view_friends = "Amis";
|
||||
set text_view_archive = "Archives";
|
||||
set text_view_userinfo = "Profil";
|
||||
set text_view_month = "Sujets du mois";
|
||||
# Misc. texts
|
||||
set text_nosubject = "(pas de sujets)";
|
||||
set text_noentries_recent = "Pas d'entrées.";
|
||||
set text_noentries_day = "Il n'y a aucune entrée cette journée.";
|
||||
set text_permalink = "Lien";
|
||||
set text_month_screened_comments = "+ filtrée(s)";
|
||||
set text_multiform_check = "Cocher :";
|
||||
set text_multiform_des = "Modifier les commentaires cochés :";
|
||||
set text_multiform_btn = "Modifier";
|
||||
set text_multiform_opt_unscreen = "Rendre public";
|
||||
set text_multiform_opt_screen = "Filtrer";
|
||||
set text_multiform_opt_delete = "Effacer";
|
||||
set text_multiform_conf_delete = "Êtes-vous sûr de vouloir supprimer les commentaires sélectionnés?";
|
||||
set text_day_prev = "Journée précédente";
|
||||
set text_day_next = "Journée suivante";
|
||||
set text_comment_from = "De :";
|
||||
set text_comment_date = "Date :";
|
||||
set text_comment_ipaddr = "Adresse IP :";
|
||||
set text_comment_reply = "Répondre";
|
||||
set text_comment_parent = "Précédent";
|
||||
set text_comment_thread = "Fil";
|
||||
set text_reply_back = "Lire les commentaires";
|
||||
set text_reply_nocomments_header = "Commentaires désactivés :";
|
||||
set text_reply_nocomments = "L'utilisateur a désactivé les commentaires pour cette entrée.";
|
||||
set text_website_default_name = "Mon site";
|
||||
set text_poster_anonymous = "(anonyme)";
|
||||
|
||||
#[[ function translations ]]
|
||||
|
||||
function lang_page_of_pages (int pg, int pgs) [notags] : string {
|
||||
return "Page $pg de $pgs";
|
||||
}
|
||||
|
||||
function lang_ordinal(int num) [notags] : string {
|
||||
if ($num == 1) { return $num+"er"; }
|
||||
return $num+"e";
|
||||
}
|
||||
|
||||
function lang_map_plural (int n) : int {
|
||||
if ($n > 1) { return 1; } # plural
|
||||
return 0; # singular
|
||||
}
|
||||
|
||||
function lang_viewname(string viewid) [notags] : string
|
||||
"Get some words representing a view"
|
||||
{
|
||||
if ($viewid == "recent") { return $*text_view_recent; }
|
||||
if ($viewid == "archive") { return $*text_view_archive; }
|
||||
if ($viewid == "friends") { return $*text_view_friends; }
|
||||
if ($viewid == "day") { return "Journée"; }
|
||||
if ($viewid == "month") { return "Mois"; }
|
||||
if ($viewid == "userinfo") { return $*text_view_userinfo; }
|
||||
if ($viewid == "entry") { return "Lire les commentaires"; }
|
||||
if ($viewid == "reply") { return "Envoyer un commentaire"; }
|
||||
return "Affichage inconnue";
|
||||
}
|
||||
|
||||
function ReplyPage::view_title() : string {
|
||||
return "Envoyer un commentaire";
|
||||
}
|
||||
|
||||
function server_sig() {
|
||||
"""Actionné par <a href="$*SITEROOT/">$*SITENAME</a>""";
|
||||
}
|
||||
|
||||
function Page::print_entry_poster(Entry e) {
|
||||
$e.poster->print();
|
||||
if ($.view == "friends" and $e.poster.username != $e.journal.username) {
|
||||
" a écrit dans ";
|
||||
$e.journal->print();
|
||||
}
|
||||
}
|
||||
|
||||
function lang_user_wrote(UserLite u) : string "Returns text describing that the user wrote something. i18nc layers should override this." {
|
||||
if (defined $u) {
|
||||
return $u->as_string()+" a écrit";
|
||||
}
|
||||
else {
|
||||
return "Un utilisateur anonyme a écrit";
|
||||
}
|
||||
}
|
||||
|
||||
function lang_at_datetime(DateTime d) : string "Returns a string saying \"at {the date and time given}\". Used in the core implementation of EntryPage and ReplyPage. i18nc layers should override this." {
|
||||
return $d->date_format("long") + " à " + $d->time_format();
|
||||
}
|
||||
16
livejournal/bin/upgrading/s2layers/i18nc/ja1.s2
Executable file
@@ -0,0 +1,16 @@
|
||||
#-*-s2-*- ;; -*- coding: utf-8 -*-
|
||||
|
||||
layerinfo "type" = "i18nc";
|
||||
layerinfo "redist_uniq" = "i18nc/ja1";
|
||||
layerinfo "name" = "Japanese";
|
||||
layerinfo "langcode" = "ja";
|
||||
set lang_current = "ja";
|
||||
|
||||
# One form (the number is inflected)
|
||||
function lang_map_plural (int n) : int {
|
||||
return 0;
|
||||
}
|
||||
set text_read_comments = "# コメント";
|
||||
set text_post_comment = "コメントの送信";
|
||||
set text_read_comments_friends = "# コメント";
|
||||
set text_post_comment_friends = "コメントの送信";
|
||||
21
livejournal/bin/upgrading/s2layers/i18nc/ru1.s2
Executable file
@@ -0,0 +1,21 @@
|
||||
#-*-s2-*- ;; -*- coding: utf-8 -*-
|
||||
|
||||
layerinfo "type" = "i18nc";
|
||||
layerinfo "redist_uniq" = "i18nc/ru1";
|
||||
layerinfo "name" = "Russian";
|
||||
layerinfo "langcode" = "ru";
|
||||
set lang_current = "ru";
|
||||
|
||||
# Three forms, special cases for numbers ending in 1 and 2, 3, 4, except those ending in 1[1-4]
|
||||
function lang_map_plural (int n) : int {
|
||||
if ($n%10 == 1 and $n%100 != 11) { return 0; }
|
||||
if ($n%10 >= 2 and $n%10 <= 4 and ($n%100 < 10 or $n%100>=20)) { return 1; }
|
||||
return 2;
|
||||
}
|
||||
|
||||
set text_post_comment="Оставить комментарий";
|
||||
set text_read_comments="# комментарий // # комментария // # комментариев";
|
||||
set text_post_comment_friends="Оставить комментарий";
|
||||
set text_read_comments_friends="# комментарий // # комментария // # комментариев";
|
||||
|
||||
|
||||
14
livejournal/bin/upgrading/s2layers/magazine/en.s2
Executable file
@@ -0,0 +1,14 @@
|
||||
# -*-s2-*-
|
||||
|
||||
layerinfo type = "i18n";
|
||||
layerinfo name = "English";
|
||||
layerinfo redist_uniq = "magazine/en";
|
||||
|
||||
set text_meta_music = "Music";
|
||||
set text_meta_mood = "Mood";
|
||||
|
||||
set text_post_comment = "comment on this";
|
||||
set text_read_comments = "# comments";
|
||||
|
||||
set text_post_comment_friends = "comment on this";
|
||||
set text_read_comments_friends = "# comments";
|
||||
699
livejournal/bin/upgrading/s2layers/magazine/layout.s2
Executable file
@@ -0,0 +1,699 @@
|
||||
# -*-s2-*-
|
||||
|
||||
layerinfo type = "layout";
|
||||
layerinfo name = "Magazine";
|
||||
layerinfo redist_uniq = "magazine/layout";
|
||||
layerinfo previews = "magazine/magazine.jpg";
|
||||
|
||||
propgroup colors {
|
||||
property Color main_bgcolor {
|
||||
des = "Main Background color";
|
||||
s1color = "page_back";
|
||||
}
|
||||
property Color main_fgcolor {
|
||||
des = "Main text color";
|
||||
s1color = "page_text";
|
||||
}
|
||||
property Color sidebar_color {
|
||||
des = "Sidebar color";
|
||||
s1color = "stronger_back";
|
||||
}
|
||||
property Color headerbar_bgcolor {
|
||||
des = "Headerbar background color";
|
||||
s1color = "strong_back";
|
||||
}
|
||||
property Color headerbar_fgcolor {
|
||||
des = "Text color on headerbar";
|
||||
s1color = "strong_text";
|
||||
}
|
||||
property Color headerbar_bevel_color {
|
||||
des = "Accent line color for headerbar";
|
||||
s1color = "stronger_back";
|
||||
}
|
||||
property Color highlight_bgcolor {
|
||||
des = "Highlighting color for accented text";
|
||||
s1color = "weak_back";
|
||||
}
|
||||
property Color highlight_fgcolor {
|
||||
des = "Highlighted text color";
|
||||
s1color = "weak_text";
|
||||
}
|
||||
property Color border_color {
|
||||
des = "Color of borders";
|
||||
s1color = "weak_text";
|
||||
}
|
||||
property Color title_color {
|
||||
des = "Text color of top title";
|
||||
s1color = "page_text_title";
|
||||
}
|
||||
property Color meta_color {
|
||||
des = "Text color of meta descriptions";
|
||||
s1color = "page_text_em";
|
||||
}
|
||||
property Color link_color {
|
||||
des = "Text color of links";
|
||||
s1color = "page_link";
|
||||
}
|
||||
property Color vlink_color {
|
||||
des = "Text color of visited links";
|
||||
s1color = "page_vlink";
|
||||
}
|
||||
property Color alink_color {
|
||||
des = "Text color of active links";
|
||||
s1color = "page_alink";
|
||||
}
|
||||
property Color comment_bar_one_bgcolor {
|
||||
des = "Alternating background color for comment bars (one)";
|
||||
}
|
||||
property Color comment_bar_two_fgcolor {
|
||||
des = "Text color on alternating comment bars (one)";
|
||||
}
|
||||
property Color comment_bar_two_bgcolor {
|
||||
des = "Alternating background color for comment bars (two)";
|
||||
}
|
||||
property Color comment_bar_one_fgcolor {
|
||||
des = "Text color on alternating comment bars (two)";
|
||||
}
|
||||
property Color comment_bar_screened_bgcolor {
|
||||
des = "Background bar color for screened comments";
|
||||
}
|
||||
property Color comment_bar_screened_fgcolor {
|
||||
des = "Text color on background bar for screened comments";
|
||||
}
|
||||
}
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set sidebar_color = "#6666cc";
|
||||
set headerbar_bgcolor = "#c0c0ff";
|
||||
set headerbar_fgcolor = "#000000";
|
||||
set headerbar_bevel_color = "#6666cc";
|
||||
set highlight_bgcolor = "#eeeeff";
|
||||
set highlight_fgcolor = "#000000";
|
||||
set border_color = "#000000";
|
||||
set title_color = "#8b1a1";
|
||||
set meta_color = "#c00000";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#c0c0ff";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#eeeeff";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
set comment_bar_screened_bgcolor = "#dddddd";
|
||||
set comment_bar_screened_fgcolor = "#000000";
|
||||
|
||||
propgroup presentation {
|
||||
property bool show_entry_userpic {
|
||||
des = "Show the userpic on the journal entries? [Excludes friends page]";
|
||||
}
|
||||
property use page_recent_items;
|
||||
property use page_friends_items;
|
||||
property use use_shared_pic;
|
||||
property use view_entry_disabled;
|
||||
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;
|
||||
}
|
||||
set show_entry_userpic = false;
|
||||
set view_entry_disabled = false;
|
||||
set show_entrynav_icons = true;
|
||||
set page_background_image = "";
|
||||
|
||||
propgroup text {
|
||||
property use text_post_comment;
|
||||
property use text_read_comments;
|
||||
property use text_post_comment_friends;
|
||||
property use text_read_comments_friends;
|
||||
}
|
||||
|
||||
set tags_aware = true;
|
||||
|
||||
function Page::lay_skip_navigation() {}
|
||||
|
||||
function Page::lay_bottom_navigation() {}
|
||||
|
||||
function print_stylesheet ()
|
||||
{
|
||||
print clean_url($*page_background_image) != "" ? "body { background-image: url($*page_background_image); }" : "";
|
||||
"""HTML {
|
||||
border-left: 1cm solid $*sidebar_color;
|
||||
padding: 1cm;
|
||||
}
|
||||
BODY {
|
||||
line-height: 1.3;
|
||||
margin: 0;
|
||||
background-color: $*main_bgcolor;
|
||||
color: $*main_fgcolor;
|
||||
}
|
||||
P {
|
||||
margin-top: 0;
|
||||
text-align: justify;
|
||||
}
|
||||
H1 {
|
||||
font: x-large Verdana, sans-serif; text-align: center;
|
||||
letter-spacing: -0.09em;
|
||||
color: $*title_color;
|
||||
}
|
||||
H2 {
|
||||
background-color: $*headerbar_bgcolor;
|
||||
color: $*headerbar_fgcolor;
|
||||
border-bottom: thin solid $*headerbar_bevel_color;
|
||||
font: normal 1.3em Georgia, serif;
|
||||
}
|
||||
H3 {
|
||||
color: $*highlight_fgcolor;
|
||||
font: medium sans-serif;
|
||||
}
|
||||
H3 SPAN {
|
||||
background-color: $*highlight_bgcolor;
|
||||
border-right: thin solid $*border_color;
|
||||
border-bottom: thin solid $*border_color;
|
||||
padding-right: 0.5ex;
|
||||
}
|
||||
H3 EM {
|
||||
color: $*meta_color;
|
||||
font-style: normal;
|
||||
}
|
||||
.H3Holder {
|
||||
clear: both;
|
||||
padding-left: 2ex;
|
||||
border-left: thin solid $*border_color;
|
||||
border-bottom: thin solid $*border_color;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
A:link {
|
||||
color: $*link_color;
|
||||
}
|
||||
A:visited {
|
||||
color: $*vlink_color;
|
||||
}
|
||||
A:active {
|
||||
color: $*alink_color;
|
||||
}
|
||||
.Navigation {
|
||||
text-align: center;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
.Comment {
|
||||
font-size: 0.7em;
|
||||
margin-top: -1em;
|
||||
text-align: right;
|
||||
}
|
||||
.Comment, .Current {
|
||||
margin-bottom: 1em;
|
||||
clear: right;
|
||||
}
|
||||
.Picture {
|
||||
border-left: thin solid $*border_color;
|
||||
border-top: thin solid $*border_color;
|
||||
float: right;
|
||||
margin: 0 0 0.5em 0.5em;
|
||||
padding: 0.2em;
|
||||
}
|
||||
.Picture DIV {
|
||||
text-align: center;
|
||||
}
|
||||
.Active {
|
||||
background-color: $*highlight_bgcolor;
|
||||
}
|
||||
ACRONYM {
|
||||
border-bottom: thin dashed $*border_color;
|
||||
cursor: help;
|
||||
}
|
||||
.Bottom {
|
||||
border-top: thin solid $*border_color;
|
||||
text-align: center;
|
||||
}
|
||||
.Empty {
|
||||
background-color: $*highlight_bgcolor;
|
||||
}
|
||||
.Month {
|
||||
margin-top: 1em;
|
||||
}
|
||||
.MonthHeader {
|
||||
color: $*headerbar_fgcolor;
|
||||
background-color: $*headerbar_bgcolor ! important;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.Month TD {
|
||||
color: $*highlight_fgcolor;
|
||||
width: 14%;
|
||||
border: thin outset;
|
||||
}
|
||||
.Month TH {
|
||||
background-color: $*highlight_bgcolor;
|
||||
font-family: Verdana, sans-serif;
|
||||
border: thin outset;
|
||||
}""";
|
||||
}
|
||||
|
||||
function Page::print () {
|
||||
var string title = $this->title();
|
||||
|
||||
"""<!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>
|
||||
<h1>$title</h1>""";
|
||||
|
||||
var string website_name = $.journal.website_name ? $.journal.website_name : $*text_website_default_name;
|
||||
var string website = ($.journal.website_url != "" ? "(<a href='$.journal.website_url'>$website_name</a>)" : "");
|
||||
|
||||
var string links;
|
||||
foreach var string v ($.views_order) {
|
||||
$links = "$links(<span style='white-space: nowrap;'>" + ($.view == $v ?
|
||||
"<span class='Active'>"+lang_viewname($v)+"</span>" :
|
||||
"<a href='$.view_url{$v}'>"+lang_viewname($v)+"</a>") + ")</span>\n";
|
||||
}
|
||||
|
||||
"""<p class="Navigation">$links $website<br />""";
|
||||
$this->lay_skip_navigation();
|
||||
"</p>";
|
||||
|
||||
$this->print_body();
|
||||
|
||||
$this->lay_bottom_navigation();
|
||||
|
||||
"</body></html>";
|
||||
}
|
||||
|
||||
function print_entry (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text)
|
||||
{
|
||||
var string time = $e.time->time_format();
|
||||
var string userpic = (defined $e.userpic ? "<img src='$e.userpic.url' />" : "");
|
||||
if (($p.view != "entry" and $e.new_day) or $p.view == "entry")
|
||||
{
|
||||
"<h2>" + $e.time->date_format("med") + "</h2>";
|
||||
}
|
||||
"<div class='H3Holder'>";
|
||||
|
||||
# Altposter / friends / lastn userpic
|
||||
if ($p.view == "friends" or
|
||||
$p.view == "entry" or
|
||||
$*show_entry_userpic == true or
|
||||
$e.journal.username != $e.poster.username)
|
||||
{
|
||||
"<div class='Picture' style='background-color: $bgcolor;'>";
|
||||
if ($p.view == "friends")
|
||||
{
|
||||
"<div><a href='";
|
||||
print $e.journal->base_url() + "/";
|
||||
"' style='color: $fgcolor;'><small>$e.journal.username</small></a></div>";
|
||||
}
|
||||
if ($*show_entry_userpic == true or $p.view == "friends" or $p.view == "entry")
|
||||
{
|
||||
if (defined $e.userpic) { "<div><img src='$e.userpic.url' /></div>"; }
|
||||
}
|
||||
if ($e.journal.username != $e.poster.username)
|
||||
{
|
||||
"<div><a href='";
|
||||
print $e.poster->base_url() + "/";
|
||||
"'>$e.poster.username</a></div>";
|
||||
}
|
||||
"</div>";
|
||||
}
|
||||
# Time / Subject / Security
|
||||
var string subject = ($e.subject != "" ? " - <em>$e.subject</em>" : "");
|
||||
"<h3><span>$time$subject</span> $e.security_icon</h3>";
|
||||
|
||||
if ($p.view == "entry" and $*show_entrynav_icons)
|
||||
{
|
||||
print "<div style='text-align: center'>";
|
||||
$e->print_linkbar();
|
||||
print "</div>";
|
||||
}
|
||||
|
||||
if (not $hide_text)
|
||||
{
|
||||
# Entry
|
||||
"<p>$e.text</p>";
|
||||
|
||||
# Tags
|
||||
if ($e.tags) {
|
||||
var int tcount = 0;
|
||||
"<div class='ljtags'><strong>Tags:</strong> ";
|
||||
foreach var Tag t ($e.tags) {
|
||||
"""<a rel="tag" href="$t.url">$t.name</a>""";
|
||||
$tcount++;
|
||||
if ($tcount != size $e.tags) { ", "; }
|
||||
}
|
||||
"</div>";
|
||||
}
|
||||
|
||||
# Metadata
|
||||
if (size $e.metadata) {
|
||||
foreach var string k ($e.metadata) {
|
||||
"<div class='Currents'>";
|
||||
var string key = $k;
|
||||
var string val = $e.metadata{$k};
|
||||
if ($k == "mood") {
|
||||
$key = $*text_meta_mood;
|
||||
} elseif ( $k == "music" ) {
|
||||
$key = $*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='absmiddle' alt='[mood icon]' /> $val";
|
||||
}
|
||||
"<div><strong>$key:</strong> $val</div>";
|
||||
"</div>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Comments
|
||||
$e.comments->print();
|
||||
"</div>";
|
||||
}
|
||||
|
||||
function CommentInfo::print()
|
||||
{
|
||||
if (not $.enabled) { return; }
|
||||
"<div class='Comment'>(";
|
||||
if ($.count > 0 or $.screened) {
|
||||
$this->print_readlink(); " | ";
|
||||
}
|
||||
$this->print_postlink();
|
||||
")</div>";
|
||||
}
|
||||
|
||||
function Page::print_entry (Entry e)
|
||||
{
|
||||
print_entry($this, $e, null Color, null Color, false);
|
||||
}
|
||||
|
||||
function RecentPage::lay_skip_navigation()
|
||||
{
|
||||
var int total = size $.entries;
|
||||
var string nav = "";
|
||||
if ($.nav.backward_url != "") {
|
||||
$nav = """<a href="$.nav.backward_url">Previous $total Entries</a>""";
|
||||
}
|
||||
if ($.nav.forward_url != "" and $.nav.backward_url != "") {
|
||||
$nav = "$nav | ";
|
||||
}
|
||||
if ($.nav.forward_url != "") {
|
||||
$nav = """$nav<a href="$.nav.forward_url">Next $total Entries</a>""";
|
||||
}
|
||||
if ($nav != "") { print "Navigate: ($nav)"; }
|
||||
}
|
||||
|
||||
function RecentPage::lay_bottom_navigation()
|
||||
{
|
||||
"<p class='Bottom'>"; $this->lay_skip_navigation(); "</p>";
|
||||
}
|
||||
|
||||
function RecentPage::print_body
|
||||
{
|
||||
foreach var Entry e ($.entries) {
|
||||
$this->print_entry($e);
|
||||
}
|
||||
}
|
||||
|
||||
function FriendsPage::lay_skip_navigation()
|
||||
{
|
||||
var int total = size $.entries;
|
||||
var string nav = "";
|
||||
if ($.nav.backward_url != "") {
|
||||
$nav = """<a href="$.nav.backward_url">Previous $total Friends</a>""";
|
||||
}
|
||||
if ($.nav.forward_url != "" and $.nav.backward_url != "") {
|
||||
$nav = "$nav | ";
|
||||
}
|
||||
if ($.nav.forward_url != "") {
|
||||
$nav = """$nav<a href="$.nav.forward_url">Next $total Friends</a>""";
|
||||
}
|
||||
if ($nav != "") { print "Navigate: ($nav)"; }
|
||||
}
|
||||
|
||||
function FriendsPage::print_entry (Entry e)
|
||||
{
|
||||
var Friend f = $.friends{$e.journal.username};
|
||||
print_entry($this, $e, $f.bgcolor, $f.fgcolor, false);
|
||||
}
|
||||
|
||||
function FriendsPage::print_body
|
||||
{
|
||||
foreach var Entry e ($.entries) {
|
||||
$this->print_entry($e);
|
||||
}
|
||||
}
|
||||
|
||||
function YearPage::lay_skip_navigation ()
|
||||
{
|
||||
$this->print_year_links();
|
||||
}
|
||||
|
||||
function YearPage::lay_bottom_navigation() { }
|
||||
|
||||
function YearPage::print_body() {
|
||||
"<h2>$.year</h2>";
|
||||
foreach var YearMonth m ($.months) {
|
||||
$this->print_month($m);
|
||||
}
|
||||
}
|
||||
|
||||
function YearPage::print_year_links ()
|
||||
{
|
||||
"Navigate: ";
|
||||
foreach var YearYear y ($.years) {
|
||||
if ($y.displayed) {
|
||||
" (<span class='Active'>$y.year</span>) ";
|
||||
} else {
|
||||
" (<a href='$y.url'>$y.year</a>) ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function YearPage::print_month(YearMonth m)
|
||||
{
|
||||
if (not $m.has_entries) { return; }
|
||||
"<table class='Month'>";
|
||||
"<tr><th class='MonthHeader' colspan='7'>";
|
||||
"<a href='$m.url'>"; print $m->month_format(); "</a></th></tr>\n";
|
||||
"<tr>";
|
||||
foreach var int d (weekdays())
|
||||
{
|
||||
"<th>"+$*lang_dayname_short[$d]+ "</th>\n";
|
||||
}
|
||||
"</tr>";
|
||||
foreach var YearWeek w ($m.weeks)
|
||||
{
|
||||
$w->print();
|
||||
}
|
||||
"</table>\n";
|
||||
}
|
||||
|
||||
function YearWeek::print() {
|
||||
"<tr valign='top'>";
|
||||
if ($.pre_empty) { "<td class='empty' colspan='$.pre_empty'></td></td>"; }
|
||||
foreach var YearDay d ($.days)
|
||||
{
|
||||
"<td>$d.day";
|
||||
if ($d.num_entries)
|
||||
{
|
||||
"<div align='center'><a href='$d.url'><strong>$d.num_entries</strong></a></div>";
|
||||
} else {
|
||||
"<br /><br />";
|
||||
}
|
||||
"</td>";
|
||||
}
|
||||
if ($.post_empty) { "<td class='empty' colspan='$.post_empty'></td></td>"; }
|
||||
"</tr>";
|
||||
}
|
||||
|
||||
function DayPage::lay_skip_navigation()
|
||||
{
|
||||
"Navigate: (<a href='$.prev_url'>Previous Day</a> | <a href='$.next_url'>Next Day</a>)";
|
||||
}
|
||||
|
||||
function DayPage::lay_bottom_navigation()
|
||||
{
|
||||
"""
|
||||
<table style="border-top: thin solid $*headerbar_bevel_color;" width="100%">
|
||||
<tr>
|
||||
<td width="33%">← <a href="$.prev_url">Previous day</a></td>
|
||||
<td width="34%" align="center">(<a href="$.base_url/calendar">Calendar</a>)</td>
|
||||
<td width="33%" align="right"><a href="$.next_url">Next day</a> →</td>
|
||||
</tr>
|
||||
</table>
|
||||
""";
|
||||
}
|
||||
|
||||
function DayPage::print_body ()
|
||||
{
|
||||
if (not $.has_entries) {
|
||||
"<h2>"; print $.date->date_format("med"); "</h2>";
|
||||
print "<p>(No journal entries for this day.)</p>";
|
||||
} else {
|
||||
foreach var Entry e ($.entries) {
|
||||
$this->print_entry($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function EntryPage::print_body ()
|
||||
{
|
||||
set_handler("unscreen_comment_#", [
|
||||
[ "style_bgcolor", "cmtbar#", "$*comment_bar_one_bgcolor", ],
|
||||
[ "style_color", "cmtbar#", "$*comment_bar_one_fgcolor", ],
|
||||
]);
|
||||
set_handler("screen_comment_#", [
|
||||
[ "style_bgcolor", "cmtbar#", "$*comment_bar_screened_bgcolor", ],
|
||||
[ "style_color", "cmtbar#", "$*comment_bar_screened_fgcolor", ],
|
||||
]);
|
||||
|
||||
|
||||
print_entry($this, $.entry, null Color, null Color, $.viewing_thread);
|
||||
if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0)
|
||||
{
|
||||
$this->print_multiform_start();
|
||||
print "<h2>Comments:</h2><div style='margin-left: 30px;'>";
|
||||
if ($.comment_pages.total_subitems > 0) {
|
||||
$.comment_pages->print();
|
||||
$this->print_comments($.comments);
|
||||
}
|
||||
"</div>";
|
||||
if ($this.multiform_on) {
|
||||
"<h2>Mass Action</h2><div style='margin-left: 30px;'>";
|
||||
$this->print_multiform_actionline();
|
||||
$this->print_multiform_end();
|
||||
"</div>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function EntryPage::print_comment (Comment c) {
|
||||
var Color background; var Color color;
|
||||
if ($c.screened) {
|
||||
$background = $*comment_bar_screened_bgcolor;
|
||||
$color = $*comment_bar_screened_fgcolor;
|
||||
} elseif ($c.depth % 2) {
|
||||
$background = $*comment_bar_one_bgcolor;
|
||||
$color = $*comment_bar_one_fgcolor;
|
||||
} else {
|
||||
$background = $*comment_bar_two_bgcolor;
|
||||
$color = $*comment_bar_two_fgcolor;
|
||||
}
|
||||
var string poster = defined $c.poster ? $c.poster->as_string() : "<i>(Anonymous)</i>";
|
||||
var string sub_icon;
|
||||
if (defined $c.subject_icon) {
|
||||
$sub_icon = $c.subject_icon->as_string();
|
||||
}
|
||||
"<a name='$c.anchor'></a><div id='cmtbar$c.talkid' style='background-color: $background; color: $color; margin-top: 10px; width: 100%'>";
|
||||
"<table cellpadding='2' cellspacing='0' summary='0' style='width: 100%'><tr valign='top'>";
|
||||
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;
|
||||
}
|
||||
print "<td style='width: 102px'><img src='$c.userpic.url' width='$w' height='$h' alt='[User Picture]' /></td>";
|
||||
}
|
||||
|
||||
"<td style='width: 100%'><table style='width: 100%'><tr>";
|
||||
|
||||
### From, date, etc
|
||||
"<td align='left' style='width: 50%'>";
|
||||
print "<table>";
|
||||
print "<tr><th align='right'>From:</th><td>$poster</td></tr>\n";
|
||||
print "<tr><th align='right'>Date:</th><td style='white-space: nowrap'>";
|
||||
print $c.time->date_format("long") + " - " + $c.time->time_format() + "</td></tr>";
|
||||
if ($c.metadata{"poster_ip"}) { print "<tr><th align='right'>IP Address:</th><td>(" + $c.metadata{"poster_ip"} + ")</td></tr>"; }
|
||||
"</table></td>";
|
||||
|
||||
### Gadgets
|
||||
"<td align='right' style='width: 50%'>";
|
||||
if ($this.multiform_on) {
|
||||
" <label for='ljcomsel_$c.talkid'>$*text_multiform_check</label>";
|
||||
$c->print_multiform_check();
|
||||
}
|
||||
$c->print_linkbar();
|
||||
"</td></tr>";
|
||||
|
||||
### Subject / icon
|
||||
print "<tr valign='top'><td style='width: 50%'>";
|
||||
print (defined $c.subject_icon or $c.subject != "") ? "<h3>$c.subject_icon $c.subject</h3>" : "";
|
||||
print "</td>";
|
||||
|
||||
### Permalink
|
||||
print "<td style='width: 50%' align='right'><strong>(<a href='$c.permalink_url'>Link</a>)</strong></td></tr>";
|
||||
|
||||
print "</table></td></tr></table></div>";
|
||||
print "<div style='margin-left: 5px'>$c.text</div>";
|
||||
print "<div style='margin-top: 3px; font-size: smaller'>";
|
||||
if ($c.frozen) {
|
||||
print """(Replies frozen) """;
|
||||
} else {
|
||||
print """(<a href='$c.reply_url'>Reply to this</a>) """;
|
||||
}
|
||||
if ($c.parent_url != "") { "(<a href='$c.parent_url'>Parent</a>) "; }
|
||||
if ($c.thread_url != "") { "(<a href='$c.thread_url'>Thread</a>) "; }
|
||||
"</div>";
|
||||
}
|
||||
|
||||
function ReplyPage::print_body ()
|
||||
{
|
||||
var string time = $.replyto.time->time_format();
|
||||
|
||||
if (not $.entry.comments.enabled)
|
||||
{
|
||||
print "<h2>$*text_reply_nocomments_header</h2><p>$*text_reply_nocomments</p>";
|
||||
return;
|
||||
}
|
||||
|
||||
"<h2>" + $.replyto.time->date_format("med") + "</h2>";
|
||||
|
||||
"<div class='H3Holder'>";
|
||||
|
||||
"<div class='Picture'>";
|
||||
print defined $.replyto.poster ? $.replyto.poster->as_string() : "<i>(Anonymous)</i>";
|
||||
if (defined $.replyto.userpic) { "<div><img src='$.replyto.userpic.url' /></div>"; }
|
||||
"</div>";
|
||||
|
||||
# Time / Subject / Security
|
||||
var string subject = ($.replyto.subject ? " - <em>$.replyto.subject</em>" : "");
|
||||
"<h3><span>$time$subject</span></h3>";
|
||||
|
||||
"<p>$.replyto.text</p>";
|
||||
|
||||
"<div class='Comment'><a href='$.entry.comments.read_url'>Read Comments</a></div>";
|
||||
"</div>";
|
||||
print "<h2>Reply:</h2>";
|
||||
$.form->print();
|
||||
}
|
||||
|
||||
|
||||
function print_theme_preview ()
|
||||
{
|
||||
"""<table width='100%' bgcolor='$*main_bgcolor' cellpadding='3' border='0'><tr valign='top'>
|
||||
<td width='30' bgcolor='$*sidebar_color'> </td>
|
||||
<td width='30'> </td>
|
||||
<td>
|
||||
<h2 style='background-color: $*headerbar_bgcolor; color: $*headerbar_fgcolor; border-bottom: thin solid $*headerbar_bevel_color; font: normal 1.3em Georgia, serif; line-height: 1.3;'>Dec. 22nd, 2002</h2>
|
||||
<div style='clear: both; padding-left: 2ex; border-left: thin solid $*border_color; border-bottom: thin solid $*border_color; margin-bottom: 1em; '>
|
||||
<h3 style='color: $*highlight_fgcolor; font: medium sans-serif'><span style='background-color: $*highlight_bgcolor; border-right: thin solid $*border_color; border-bottom: thin solid $*border_color; padding-right: 0.5ex;'>08:46 pm - <em style='color: $*meta_color; font-style: normal;'>subject</em></span></h3>
|
||||
<p style='margin-top: 0; text-align: justify; font-family: serif; font-size: 12pt; color: $*main_fgcolor;'>Words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words words</p>
|
||||
|
||||
<div style='font-size: 0.7em; margin-top: -1em; text-align: right; font-size: 8pt; color: $*main_fgcolor;'>(<a style='color: $*link_color;' href='#'>1 comment</a> | <a style='color: $*link_color;' href='#'>Leave a comment</a>)</div>
|
||||
</div>
|
||||
|
||||
</td></tr>
|
||||
</table>""";
|
||||
}
|
||||
BIN
livejournal/bin/upgrading/s2layers/magazine/magazine.jpg
Executable file
|
After Width: | Height: | Size: 17 KiB |
459
livejournal/bin/upgrading/s2layers/magazine/themes.s2
Executable file
@@ -0,0 +1,459 @@
|
||||
#NEWLAYER: magazine/wonb
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "White on Black";
|
||||
layerinfo "redist_uniq" = "magazine/wonb";
|
||||
set title_color = "#ffffff";
|
||||
set main_bgcolor = "#000000";
|
||||
set main_fgcolor = "#ffffff";
|
||||
set sidebar_color = "#555555";
|
||||
set headerbar_bgcolor = "#777777";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set headerbar_bevel_color = "#777777";
|
||||
set link_color = "#eeeeee";
|
||||
set alink_color = "#ffffff";
|
||||
set vlink_color = "#dddddd";
|
||||
set meta_color = "#ffffff";
|
||||
set highlight_bgcolor = "#666666";
|
||||
set highlight_fgcolor = "#dddddd";
|
||||
set border_color = "#ffffff";
|
||||
set comment_bar_one_bgcolor = "#777777";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#666666";
|
||||
set comment_bar_two_fgcolor = "#dddddd";
|
||||
|
||||
#NEWLAYER: magazine/shrinkvio
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Shrinking Violet";
|
||||
layerinfo redist_uniq = "magazine/shrinkvio";
|
||||
set sidebar_color = "#ad22e7";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#381a45";
|
||||
set headerbar_bgcolor = "#5d0383";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set title_color = "#5d0383";
|
||||
set meta_color = "#ffffff";
|
||||
set headerbar_bevel_color = "#d9a1f1";
|
||||
set highlight_bgcolor = "#d9a1f1";
|
||||
set highlight_fgcolor = "#000000";
|
||||
set link_color = "#2e053f";
|
||||
set vlink_color = "#611627";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#5d0383";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#d9a1f1";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: magazine/pistmint
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Pistachio Mint";
|
||||
layerinfo redist_uniq = "magazine/pistmint";
|
||||
set sidebar_color = "#133422";
|
||||
set main_bgcolor = "#a7c4b4";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#096d36";
|
||||
set headerbar_bgcolor = "#096d36";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set title_color = "#096d36";
|
||||
set meta_color = "#ffffff";
|
||||
set headerbar_bevel_color = "#096d36";
|
||||
set highlight_bgcolor = "#096d36";
|
||||
set highlight_fgcolor = "#000000";
|
||||
set link_color = "#8afabc";
|
||||
set vlink_color = "#1da65a";
|
||||
set alink_color = "#f9f5f5";
|
||||
set comment_bar_one_bgcolor = "#096d36";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#093d36";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: magazine/mexicanfood
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Mexican Food";
|
||||
layerinfo redist_uniq = "magazine/mexicanfood";
|
||||
set sidebar_color = "#ff0000";
|
||||
set main_bgcolor = "#f8ff3e";
|
||||
set main_fgcolor = "#f15601";
|
||||
set border_color = "#f50701";
|
||||
set headerbar_bgcolor = "#bdbf3e";
|
||||
set headerbar_fgcolor = "#ff0000";
|
||||
set title_color = "#ffc664";
|
||||
set meta_color = "#000000";
|
||||
set headerbar_bevel_color = "#f9ff9d";
|
||||
set highlight_bgcolor = "#e15a18";
|
||||
set highlight_fgcolor = "#ffffff";
|
||||
set link_color = "#f49e08";
|
||||
set vlink_color = "#b05403";
|
||||
set alink_color = "#ff7405";
|
||||
set comment_bar_one_bgcolor = "#bdbf3e";
|
||||
set comment_bar_one_fgcolor = "#ff0000";
|
||||
set comment_bar_two_bgcolor = "#e15a18";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: magazine/ashfire
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Ash and Fire";
|
||||
layerinfo redist_uniq = "magazine/ashfire";
|
||||
set sidebar_color = "#b5b5b5";
|
||||
set main_bgcolor = "#ffb6af";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#d90308";
|
||||
set headerbar_bgcolor = "#e75454";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set title_color = "#ff9696";
|
||||
set meta_color = "#ffffff";
|
||||
set headerbar_bevel_color = "#ff1106";
|
||||
set highlight_bgcolor = "#f06c88";
|
||||
set highlight_fgcolor = "#000000";
|
||||
set link_color = "#f70208";
|
||||
set vlink_color = "#b0161d";
|
||||
set alink_color = "#d70106";
|
||||
set comment_bar_one_bgcolor = "#e75454";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#f06c88";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: magazine/desktop
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Classic Desktop";
|
||||
layerinfo redist_uniq = "magazine/desktop";
|
||||
set sidebar_color = "#00545c";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#000000";
|
||||
set headerbar_bgcolor = "#ff7b05";
|
||||
set headerbar_fgcolor = "#ffeddd";
|
||||
set title_color = "#ffffff";
|
||||
set meta_color = "#000000";
|
||||
set headerbar_bevel_color = "#ff7b05";
|
||||
set highlight_bgcolor = "#ffeddd";
|
||||
set highlight_fgcolor = "#000000";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#5a76ff";
|
||||
set comment_bar_one_bgcolor = "#ff7b05";
|
||||
set comment_bar_one_fgcolor = "#ffeddd";
|
||||
set comment_bar_two_bgcolor = "#ffeddd";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: magazine/satinhandshake
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Satin Handshake";
|
||||
layerinfo redist_uniq = "magazine/satinhandshake";
|
||||
set sidebar_color = "#480c0c";
|
||||
set main_bgcolor = "#d06464";
|
||||
set main_fgcolor = "#00001d";
|
||||
set border_color = "#000000";
|
||||
set headerbar_bgcolor = "#aaaaaa";
|
||||
set headerbar_fgcolor = "#000000";
|
||||
set title_color = "#aaaaaa";
|
||||
set meta_color = "#000000";
|
||||
set headerbar_bevel_color = "#9d0404";
|
||||
set highlight_bgcolor = "#9d0404";
|
||||
set highlight_fgcolor = "#ffffff";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#aaaaaa";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#9d0404";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: magazine/deepmelodrama
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Deep MeloDrama";
|
||||
layerinfo redist_uniq = "magazine/deepmelodrama";
|
||||
set sidebar_color = "#872d89";
|
||||
set main_bgcolor = "#719cff";
|
||||
set main_fgcolor = "#8e48b2";
|
||||
set border_color = "#8e48b2";
|
||||
set headerbar_bgcolor = "#3794b3";
|
||||
set headerbar_fgcolor = "#84b8e7";
|
||||
set title_color = "#65b2c1";
|
||||
set meta_color = "#f5d3ff";
|
||||
set headerbar_bevel_color = "#8e48b2";
|
||||
set highlight_bgcolor = "#65b2c1";
|
||||
set highlight_fgcolor = "#f5d3ff";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#dfd3ff";
|
||||
set comment_bar_one_bgcolor = "#3794b3";
|
||||
set comment_bar_one_fgcolor = "#84b8e7";
|
||||
set comment_bar_two_bgcolor = "#65b2c1";
|
||||
set comment_bar_two_fgcolor = "#f5d3ff";
|
||||
|
||||
#NEWLAYER: magazine/everwhite
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Everwhite";
|
||||
layerinfo redist_uniq = "magazine/everwhite";
|
||||
set sidebar_color = "#ffffff";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#000000";
|
||||
set headerbar_bgcolor = "#ffffff";
|
||||
set headerbar_fgcolor = "#000000";
|
||||
set title_color = "#ffffff";
|
||||
set meta_color = "#000000";
|
||||
set headerbar_bevel_color = "#ffffff";
|
||||
set highlight_bgcolor = "#ffffff";
|
||||
set highlight_fgcolor = "#000000";
|
||||
set link_color = "#e60000";
|
||||
set vlink_color = "#c10602";
|
||||
set alink_color = "#ff0600";
|
||||
set comment_bar_one_bgcolor = "#dddddd";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#aaaaaa";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: magazine/everblue
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Everblue with Greys";
|
||||
layerinfo redist_uniq = "magazine/everblue";
|
||||
set sidebar_color = "#0f0c6d";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#000000";
|
||||
set headerbar_bgcolor = "#000000";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set title_color = "#aaaaaa";
|
||||
set meta_color = "#000000";
|
||||
set headerbar_bevel_color = "#000000";
|
||||
set highlight_bgcolor = "#aaaaaa";
|
||||
set highlight_fgcolor = "#000000";
|
||||
set link_color = "#2f00f2";
|
||||
set vlink_color = "#060667";
|
||||
set alink_color = "#6691ff";
|
||||
set comment_bar_one_bgcolor = "#000000";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#aaaaaa";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: magazine/brownleather
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Brown Leather Coat";
|
||||
layerinfo redist_uniq = "magazine/brownleather";
|
||||
set sidebar_color = "#d2b48c";
|
||||
set main_bgcolor = "#ffebcd";
|
||||
set main_fgcolor = "#8b4513";
|
||||
set border_color = "#000000";
|
||||
set headerbar_bgcolor = "#d48014";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set title_color = "#d48014";
|
||||
set meta_color = "#d48014";
|
||||
set headerbar_bevel_color = "#d48014";
|
||||
set highlight_bgcolor = "#ffe1a1";
|
||||
set highlight_fgcolor = "#000000";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#867a55";
|
||||
set alink_color = "#fffab3";
|
||||
set comment_bar_one_bgcolor = "#d48014";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#ffe1a1";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: magazine/bruise
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Bruise";
|
||||
layerinfo redist_uniq = "magazine/bruise";
|
||||
set sidebar_color = "#000000";
|
||||
set main_bgcolor = "#bcbcbc";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#000000";
|
||||
set headerbar_bgcolor = "#1114a0";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set title_color = "#21c2f1";
|
||||
set meta_color = "#ffffff";
|
||||
set headerbar_bevel_color = "#1114a0";
|
||||
set highlight_bgcolor = "#21c2f1";
|
||||
set highlight_fgcolor = "#0000ff";
|
||||
set link_color = "#0000cc";
|
||||
set vlink_color = "#000088";
|
||||
set alink_color = "#0000ff";
|
||||
set comment_bar_one_bgcolor = "#1114a0";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#21c2f1";
|
||||
set comment_bar_two_fgcolor = "#0000ff";
|
||||
|
||||
#NEWLAYER: magazine/ranchhand
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Ranch Hand";
|
||||
layerinfo redist_uniq = "magazine/ranchhand";
|
||||
set sidebar_color = "#2999c2";
|
||||
set main_bgcolor = "#cfe0ff";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#060667";
|
||||
set headerbar_bgcolor = "#54442c";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set title_color = "#bababa";
|
||||
set meta_color = "#000000";
|
||||
set headerbar_bevel_color = "#9d995d";
|
||||
set highlight_bgcolor = "#704400";
|
||||
set highlight_fgcolor = "#bababa";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#6a20ff";
|
||||
set comment_bar_one_bgcolor = "#54442c";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#704400";
|
||||
set comment_bar_two_fgcolor = "#bababa";
|
||||
|
||||
#NEWLAYER: magazine/victim
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Victim";
|
||||
layerinfo redist_uniq = "magazine/victim";
|
||||
set sidebar_color = "#2cd0ff";
|
||||
set main_bgcolor = "#505050";
|
||||
set main_fgcolor = "#ffffff";
|
||||
set border_color = "#000000";
|
||||
set headerbar_bgcolor = "#166bac";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set title_color = "#2098f3";
|
||||
set meta_color = "#ffffff";
|
||||
set headerbar_bevel_color = "#26b6ff";
|
||||
set highlight_bgcolor = "#353535";
|
||||
set highlight_fgcolor = "#ffffff";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#166bac";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#353535";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: magazine/forest
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Forest";
|
||||
layerinfo redist_uniq = "magazine/forest";
|
||||
set sidebar_color = "#778e64";
|
||||
set main_bgcolor = "#9b9ba5";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#ffffff";
|
||||
set headerbar_bgcolor = "#72784c";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set title_color = "#72784c";
|
||||
set meta_color = "#ffffff";
|
||||
set headerbar_bevel_color = "#a0ac62";
|
||||
set highlight_bgcolor = "#73777a";
|
||||
set highlight_fgcolor = "#000000";
|
||||
set link_color = "#3811e1";
|
||||
set vlink_color = "#310cbb";
|
||||
set alink_color = "#4e7bef";
|
||||
set comment_bar_one_bgcolor = "#72784c";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#73777a";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: magazine/drone
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Drone";
|
||||
layerinfo redist_uniq = "magazine/drone";
|
||||
set sidebar_color = "#395f82";
|
||||
set main_bgcolor = "#f9fcfe";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#000000";
|
||||
set headerbar_bgcolor = "#904094";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set title_color = "#f56efc";
|
||||
set meta_color = "#ffffff";
|
||||
set headerbar_bevel_color = "#ff93ff";
|
||||
set highlight_bgcolor = "#eeeeff";
|
||||
set highlight_fgcolor = "#000000";
|
||||
set link_color = "#395f82";
|
||||
set vlink_color = "#395f82";
|
||||
set alink_color = "#5266ce";
|
||||
set comment_bar_one_bgcolor = "#904094";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#eeeeff";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: magazine/lowercurtain
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Lower the Curtain";
|
||||
layerinfo redist_uniq = "magazine/lowercurtain";
|
||||
set sidebar_color = "#000000";
|
||||
set main_bgcolor = "#6b6b6b";
|
||||
set main_fgcolor = "#ffffff";
|
||||
set border_color = "#ffffff";
|
||||
set headerbar_bgcolor = "#363636";
|
||||
set headerbar_fgcolor = "#f0f5fb";
|
||||
set title_color = "#c6c6c6";
|
||||
set meta_color = "#222222";
|
||||
set headerbar_bevel_color = "#363636";
|
||||
set highlight_bgcolor = "#c5c8ca";
|
||||
set highlight_fgcolor = "#000000";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#3314ba";
|
||||
set comment_bar_one_bgcolor = "#363636";
|
||||
set comment_bar_one_fgcolor = "#f0f5fb";
|
||||
set comment_bar_two_bgcolor = "#c5c8ca";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: magazine/sunny
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Sunny Day";
|
||||
layerinfo redist_uniq = "magazine/sunny";
|
||||
set sidebar_color = "#55e0f9";
|
||||
set main_bgcolor = "#e38202";
|
||||
set main_fgcolor = "#ffffff";
|
||||
set border_color = "#000000";
|
||||
set headerbar_bgcolor = "#e38202";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set title_color = "#fff505";
|
||||
set meta_color = "#ffffff";
|
||||
set headerbar_bevel_color = "#efe052";
|
||||
set highlight_bgcolor = "#ffba03";
|
||||
set highlight_fgcolor = "#ffffff";
|
||||
set link_color = "#df0d12";
|
||||
set vlink_color = "#ac1b25";
|
||||
set alink_color = "#fe3b3b";
|
||||
set comment_bar_one_bgcolor = "#e38202";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#ffba03";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: magazine/valentine
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Be Mine";
|
||||
layerinfo redist_uniq = "magazine/valentine";
|
||||
set sidebar_color = "#6f104a";
|
||||
set main_bgcolor = "#f2bce9";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#ff24ab";
|
||||
set headerbar_bgcolor = "#ff37ff";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set title_color = "#df2096";
|
||||
set meta_color = "#ffffff";
|
||||
set headerbar_bevel_color = "#ae1774";
|
||||
set highlight_bgcolor = "#df2096";
|
||||
set highlight_fgcolor = "#000000";
|
||||
set link_color = "#ffffff";
|
||||
set vlink_color = "#a51014";
|
||||
set alink_color = "#ed8188";
|
||||
set comment_bar_one_bgcolor = "#ff37ff";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#df2096";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: magazine/stripes
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Stripes";
|
||||
layerinfo redist_uniq = "magazine/stripes";
|
||||
set sidebar_color = "#ffffff";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#ff0000";
|
||||
set headerbar_bgcolor = "#e7212a";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set title_color = "#ffffff";
|
||||
set meta_color = "#000000";
|
||||
set headerbar_bevel_color = "#ffffff";
|
||||
set highlight_bgcolor = "#ffcfdc";
|
||||
set highlight_fgcolor = "#000000";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ffafc1";
|
||||
set comment_bar_one_bgcolor = "#e7212a";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#ffcfdc";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
14
livejournal/bin/upgrading/s2layers/notepad/en.s2
Executable file
@@ -0,0 +1,14 @@
|
||||
# -*-s2-*-
|
||||
|
||||
layerinfo type = "i18n";
|
||||
layerinfo name = "English";
|
||||
layerinfo redist_uniq = "notepad/en";
|
||||
|
||||
set text_meta_music = "Music";
|
||||
set text_meta_mood = "Mood";
|
||||
|
||||
set text_post_comment = "Make Notes";
|
||||
set text_read_comments = "Read # Notes";
|
||||
|
||||
set text_post_comment_friends = "Make Notes";
|
||||
set text_read_comments_friends = "Read # Notes";
|
||||
605
livejournal/bin/upgrading/s2layers/notepad/layout.s2
Executable file
@@ -0,0 +1,605 @@
|
||||
# -*-s2-*-
|
||||
|
||||
layerinfo type = "layout";
|
||||
layerinfo name = "Notepad";
|
||||
layerinfo redist_uniq = "notepad/layout";
|
||||
layerinfo previews = "notepad/notepad.jpg";
|
||||
|
||||
propgroup colors {
|
||||
property Color body_bgcolor {
|
||||
des = "Body background color";
|
||||
}
|
||||
property Color text_color {
|
||||
des = "Text color";
|
||||
}
|
||||
property Color subject_color {
|
||||
des = "Text color of subjects";
|
||||
}
|
||||
property Color link_color {
|
||||
des = "Link color";
|
||||
}
|
||||
property Color vlink_color {
|
||||
des = "Visited link color";
|
||||
}
|
||||
property Color alink_color {
|
||||
des = "Active link color";
|
||||
}
|
||||
property Color comment_bar_one_bgcolor {
|
||||
des = "Alternating background color for comment bars (one)";
|
||||
}
|
||||
property Color comment_bar_two_fgcolor {
|
||||
des = "Text color on alternating comment bars (one)";
|
||||
}
|
||||
property Color comment_bar_two_bgcolor {
|
||||
des = "Alternating background color for comment bars (two)";
|
||||
}
|
||||
property Color comment_bar_one_fgcolor {
|
||||
des = "Text color on alternating comment bars (two)";
|
||||
}
|
||||
property Color comment_bar_screened_bgcolor {
|
||||
des = "Background bar color for screened comments";
|
||||
}
|
||||
property Color comment_bar_screened_fgcolor {
|
||||
des = "Text color on background bar for screened comments";
|
||||
}
|
||||
}
|
||||
set body_bgcolor = "#8cd5fe";
|
||||
set text_color = "#000000";
|
||||
set subject_color = "#ff0000";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#c0c0ff";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#eeeeff";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
set comment_bar_screened_bgcolor = "#dddddd";
|
||||
set comment_bar_screened_fgcolor = "#000000";
|
||||
|
||||
propgroup presentation {
|
||||
property bool show_entry_userpic {
|
||||
des = "Show the userpic on the journal entries?";
|
||||
}
|
||||
property use page_recent_items;
|
||||
property use page_friends_items;
|
||||
property use use_shared_pic;
|
||||
property use view_entry_disabled;
|
||||
property string page_background_image {
|
||||
des = "URL to an image to be used for the page background";
|
||||
}
|
||||
property bool show_entrynav_icons {
|
||||
des = "Toggle to show the next, memory, edit, etc icons on the entry view page";
|
||||
}
|
||||
property use external_stylesheet;
|
||||
}
|
||||
set show_entry_userpic = false;
|
||||
set view_entry_disabled = false;
|
||||
set page_background_image = "";
|
||||
set show_entrynav_icons = true;
|
||||
|
||||
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 string imguri {
|
||||
noui = 1;
|
||||
des = "URI to notepad images (no trailing slash)";
|
||||
}
|
||||
set imguri = "";
|
||||
|
||||
function prop_init()
|
||||
{
|
||||
if ($*imguri == "") { $*imguri = "$*SITEROOT/img/style/notepad"; }
|
||||
}
|
||||
|
||||
function Page::lay_bottom_navigation() { }
|
||||
|
||||
function print_stylesheet ()
|
||||
{
|
||||
var string backgroundurl = clean_url($*page_background_image) != "" ? "background-image: url($*page_background_image);" : "";
|
||||
"""body {
|
||||
$backgroundurl
|
||||
background-color: $*body_bgcolor;
|
||||
}
|
||||
td,body,p,div {
|
||||
color: $*text_color;
|
||||
text-decoration: none;
|
||||
font-family: verdana,arial,helvetica;
|
||||
font-size: 12px;
|
||||
}
|
||||
a:link {
|
||||
color: $*link_color;
|
||||
text-decoration: underline;
|
||||
font-family: verdana,arial,helvetica;
|
||||
font-size: 12px;
|
||||
}
|
||||
a:visited {
|
||||
color: $*vlink_color;
|
||||
text-decoration: underline;
|
||||
font-family: verdana,arial,helvetica;
|
||||
font-size:12px;
|
||||
}
|
||||
a:active {
|
||||
color: $*alink_color;
|
||||
text-decoration: underline;
|
||||
font-family: verdana,arial,helvetica;
|
||||
font-size: 12px;
|
||||
}
|
||||
a:hover {
|
||||
color: $*alink_color;
|
||||
text-decoration: underline;
|
||||
font-family: verdana,arial,helvetica;
|
||||
font-size:12px;
|
||||
}""";
|
||||
}
|
||||
|
||||
function Page::print()
|
||||
{
|
||||
var string title = $this->title();
|
||||
"""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.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>
|
||||
<table width="70%" border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<table border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td width="30"><img src="$*imguri/spacer.gif" width="30" height="10" alt='' /></td>
|
||||
<td width="120" height="18" style="background-image: url($*imguri/tab.jpg)">
|
||||
<a href="$.base_url/">Journal</a>
|
||||
</td>
|
||||
<td width="120" height="18" style="background-image: url($*imguri/tab.jpg)">
|
||||
<a href="$.base_url/friends">Friends</a>
|
||||
</td>
|
||||
<td width="120" height="18" style="background-image: url($*imguri/tab.jpg)">
|
||||
<a href="$.base_url/calendar">Archive</a>
|
||||
</td>
|
||||
<td width="120" height="18" style="background-image: url($*imguri/tab.jpg)">
|
||||
<a href="$.base_url/info">User Info</a>
|
||||
</td>
|
||||
<td width="120" height="18" style="background-image: url($*imguri/tab.jpg)">
|
||||
<a href="$*SITEROOT/tools/memories.bml?user=$.journal.username">memories</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="80" height="38" style="background-image: url($*imguri/top-left.jpg)">
|
||||
<img src="$*imguri/spacer.gif" width="80" height="10" alt='' />
|
||||
</td>
|
||||
<td height="38" style="background-image: url($*imguri/middle.jpg)">
|
||||
<img src="$*imguri/spacer.gif" width="10" height="10" alt='' />
|
||||
</td>
|
||||
<td width="10" height="38" style="background-image: url($*imguri/top-right.jpg)">
|
||||
<img src="$*imguri/spacer.gif" width="10" height="10" alt='' />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="80" height="38" style="background-image: url($*imguri/side-left.jpg)">
|
||||
|
||||
</td>
|
||||
<td width="100%" height="38" style="background-image: url($*imguri/middle.jpg)">
|
||||
<h1>$title</h1>
|
||||
<p align="center"><img src="$*imguri/hr.gif" width="345" height="23" alt='' /></p>
|
||||
""";
|
||||
|
||||
$this->print_body();
|
||||
|
||||
"<p style='text-align: center; font-size: 115%'>"; $this->lay_bottom_navigation(); "</p>";
|
||||
"""
|
||||
</td>
|
||||
<td width="8" height="38" style="background-image: url($*imguri/side-right.jpg)">
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="80" height="12" style="background-image: url($*imguri/bottom-left.jpg)">
|
||||
<img src="$*imguri/spacer.gif" width="70" height="12" alt='' />
|
||||
</td>
|
||||
<td height="12" style="background-image: url($*imguri/bottom-line.jpg)">
|
||||
<img src="$*imguri/spacer.gif" width="10" height="12" alt='' />
|
||||
</td>
|
||||
<td width="8" height="12" style="background-image: url($*imguri/bottom-right.jpg)">
|
||||
<img src="$*imguri/spacer.gif" width="8" height="12" alt='' />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
""";
|
||||
}
|
||||
|
||||
function print_entry (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text)
|
||||
{
|
||||
"<table border='0'><tr>";
|
||||
|
||||
if ($p.view == "friends" or
|
||||
$*show_entry_userpic == true or
|
||||
$e.journal.username != $e.poster.username)
|
||||
{
|
||||
var string userpic = defined $e.userpic ? "<img src='$e.userpic.url' /><br />" : "";
|
||||
"<td valign='top' width='100' align='center'>";
|
||||
if ($p.view == "friends" or $*show_entry_userpic == true) { print $userpic; }
|
||||
if ($p.view == "friends") { "<strong><a href='"; print $e.journal->base_url(); "/'>$e.journal.username</a></strong>"; }
|
||||
if ($e.journal.username != $e.poster.username)
|
||||
{
|
||||
print ($p.view == "friends" ?
|
||||
"<br />[ <a href='" + $e.poster->base_url() + "/'>$e.poster.username</a> ]" :
|
||||
"<strong><a href='" + $e.poster->base_url() + "/'>$e.poster.username</a></strong>");
|
||||
}
|
||||
"</td>";
|
||||
}
|
||||
"""<td valign="top" width='100%'><font size="+1">"""; print $e.time->date_format("med"); " "; print $e.time->time_format();
|
||||
if ($e.subject) { " <span style='color: $*subject_color'>$e.subject</span>"; }
|
||||
" $e.security_icon</font>";
|
||||
|
||||
if (not $hide_text)
|
||||
{
|
||||
print "<p>$e.text</p>";
|
||||
if (size $e.metadata) {
|
||||
"<p>";
|
||||
foreach var string k ($e.metadata) {
|
||||
var string key = $k;
|
||||
var string val = $e.metadata{$k};
|
||||
if ($k == "mood") {
|
||||
$key = $*text_meta_mood;
|
||||
} elseif ($k == "music") {
|
||||
$key = $*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='absmiddle' alt='' /> $val";
|
||||
}
|
||||
"<strong>$key:</strong> $val<br />";
|
||||
}
|
||||
"</p>";
|
||||
}
|
||||
}
|
||||
$e.comments->print();
|
||||
if ($p.view == "entry" and $*show_entrynav_icons)
|
||||
{
|
||||
$e->print_linkbar();
|
||||
}
|
||||
"""</td></tr><tr><td colspan="2"></td></tr></table>""";
|
||||
"""<p align="center"><img src="$*imguri/hr.gif" width="345" height="23" alt='' /></p>""";
|
||||
}
|
||||
|
||||
function Page::print_entry (Entry e)
|
||||
{
|
||||
print_entry($this, $e, null Color, null Color, false);
|
||||
}
|
||||
|
||||
function RecentPage::print_body ()
|
||||
{
|
||||
foreach var Entry e ($.entries) {
|
||||
$this->print_entry($e);
|
||||
}
|
||||
}
|
||||
|
||||
function FriendsPage::print_entry (Entry e) {
|
||||
var Friend f = $.friends{$e.journal.username};
|
||||
print_entry($this, $e, $f.bgcolor, $f.fgcolor, false);
|
||||
}
|
||||
|
||||
function RecentPage::lay_bottom_navigation ()
|
||||
{
|
||||
var string nav = "";
|
||||
if ($.nav.backward_url != "") {
|
||||
$nav = """<a href="$.nav.backward_url">Back a Page</a>""";
|
||||
}
|
||||
if ($.nav.forward_url != "" and $.nav.backward_url != "") {
|
||||
$nav = "$nav - ";
|
||||
}
|
||||
if ($.nav.forward_url != "") {
|
||||
$nav = """$nav<a href="$.nav.forward_url">Forward a Page</a>""";
|
||||
}
|
||||
if ($nav != "") { print $nav; }
|
||||
}
|
||||
|
||||
function CommentInfo::print()
|
||||
{
|
||||
if (not $.enabled) { return; }
|
||||
if ($.count > 0 or $.screened)
|
||||
{
|
||||
$this->print_readlink(); " - ";
|
||||
}
|
||||
$this->print_postlink();
|
||||
}
|
||||
|
||||
function YearPage::lay_bottom_navigation ()
|
||||
{
|
||||
$this->print_year_links();
|
||||
}
|
||||
|
||||
function YearPage::print_year_links ()
|
||||
{
|
||||
if (size $.years <= 0) { return; }
|
||||
foreach var YearYear y ($.years)
|
||||
{
|
||||
if ($y.displayed) {
|
||||
"$y.year ";
|
||||
} else {
|
||||
"<a href='$y.url'>$y.year</a> ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function YearPage::print_body ()
|
||||
{
|
||||
"<h2>$.year</h2>";
|
||||
foreach var YearMonth m ($.months)
|
||||
{
|
||||
$this->print_month($m);
|
||||
}
|
||||
}
|
||||
|
||||
function YearPage::print_month(YearMonth m)
|
||||
{
|
||||
if (not $m.has_entries) { return; }
|
||||
"<p align='center'><table border='1' cellpadding='4' width='80%'>";
|
||||
|
||||
# Month Header
|
||||
"<tr align=center><th colspan='7'>"; print $m->month_format(); "</th></tr>";
|
||||
|
||||
# Weekdays
|
||||
"<tr align='center'>";
|
||||
foreach var int d (weekdays())
|
||||
{
|
||||
"<td>" + $*lang_dayname_short[$d] + "</td>\n";
|
||||
}
|
||||
"</tr>";
|
||||
|
||||
# Weeks
|
||||
foreach var YearWeek w ($m.weeks)
|
||||
{
|
||||
$w->print();
|
||||
}
|
||||
"<tr align='center'><td colspan='7'>";
|
||||
"<a href='$m.url'>$*text_view_month</a>";
|
||||
"</td></tr></table></p>";
|
||||
}
|
||||
|
||||
function YearWeek::print()
|
||||
{
|
||||
"<tr>";
|
||||
if ($.pre_empty) { "<td colspan='$.pre_empty'> </td>"; }
|
||||
foreach var YearDay d ($.days)
|
||||
{
|
||||
"<td valign='top'><b><font size='-1'>$d.day</font></b><div align='center'>";
|
||||
if ($d.num_entries)
|
||||
{
|
||||
"<a href='$d.url'>$d.num_entries</a>";
|
||||
} else {
|
||||
" ";
|
||||
}
|
||||
"</div></td>";
|
||||
}
|
||||
if ($.post_empty) { "<td colspan='$.post_empty'> </td>"; }
|
||||
}
|
||||
|
||||
function DayPage::lay_bottom_navigation()
|
||||
{
|
||||
if (not $.has_entries) { "<img src='$*imguri/hr.gif' alt='' /><br />"; }
|
||||
print "<a href='$.prev_url'>Back a Day</a> - <a href='$.next_url'>Forward a Day</a>";
|
||||
}
|
||||
|
||||
function DayPage::print_body()
|
||||
{
|
||||
if (not $.has_entries) {
|
||||
"<p>No journal entries for this day.</p>";
|
||||
} else {
|
||||
foreach var Entry e ($.entries) { $this->print_entry($e); }
|
||||
}
|
||||
}
|
||||
|
||||
function EntryPage::print_body ()
|
||||
{
|
||||
set_handler("unscreen_comment_#", [
|
||||
[ "style_bgcolor", "cmtbar#", "$*comment_bar_one_bgcolor", ],
|
||||
[ "style_color", "cmtbar#", "$*comment_bar_one_fgcolor", ],
|
||||
]);
|
||||
set_handler("screen_comment_#", [
|
||||
[ "style_bgcolor", "cmtbar#", "$*comment_bar_screened_bgcolor", ],
|
||||
[ "style_color", "cmtbar#", "$*comment_bar_screened_fgcolor", ],
|
||||
]);
|
||||
|
||||
|
||||
print_entry($this, $.entry, null Color, null Color, $.viewing_thread);
|
||||
if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0)
|
||||
{
|
||||
$this->print_multiform_start();
|
||||
print "<h2>Comments:</h2>";
|
||||
if ($.comment_pages.total_subitems > 0) {
|
||||
$.comment_pages->print();
|
||||
$this->print_comments($.comments);
|
||||
}
|
||||
if ($this.multiform_on) {
|
||||
"<h2>Mass Action:</h2>";
|
||||
$this->print_multiform_actionline();
|
||||
$this->print_multiform_end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function EntryPage::print_comment (Comment c) {
|
||||
var Color barlight = $*color_comment_bar->clone();
|
||||
$barlight->lightness(($barlight->lightness() + 255) / 2);
|
||||
var Color barc = $c.depth % 2 ? $*color_comment_bar : $barlight;
|
||||
if ($c.screened) {
|
||||
$barc = $*comment_bar_screened_bgcolor;
|
||||
}
|
||||
var string poster = defined $c.poster ? $c.poster->as_string() : "<i>(Anonymous)</i>";
|
||||
|
||||
"<a name='$c.anchor'></a><div id='cmtbar$c.talkid' style='background-color: $barc; margin-top: 10px; width: 100%'>";
|
||||
"<table cellpadding='2' cellspacing='0' summary='0' style='width: 100%'><tr valign='top'>";
|
||||
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;
|
||||
}
|
||||
print "<td style='width: 102px'><img src='$c.userpic.url' width='$w' height='$h' alt='' /></td>";
|
||||
}
|
||||
"<td><table style='width: 100%'><tr>";
|
||||
|
||||
"<td align='left' style='width: 50%'>";
|
||||
print "<table>";
|
||||
print "<tr><th align='right'>$*text_comment_from</th><td>$poster</td></tr>\n";
|
||||
print "<tr><th align='right'>$*text_comment_date</th><td style='white-space: nowrap'>";
|
||||
print $c.time->date_format("long") + " - " + $c.time->time_format() + "</td></tr>";
|
||||
if ($c.metadata{"poster_ip"}) { print "<tr><th align='right'>$*text_comment_ipaddr</th><td>(" + $c.metadata{"poster_ip"} + ")</td></tr>"; }
|
||||
"</table></td>";
|
||||
|
||||
print "<td align='right' style='width: 50%'>";
|
||||
if ($this.multiform_on) {
|
||||
" <label for='ljcomsel_$c.talkid'>$*text_multiform_check</label> ";
|
||||
$c->print_multiform_check();
|
||||
}
|
||||
$c->print_linkbar();
|
||||
"</td></tr>";
|
||||
|
||||
print "<tr valign='top'><td style='width: 50%'>";
|
||||
if (defined $c.subject_icon or $c.subject != "") { "<h3>$c.subject_icon $c.subject</h3>\n"; }
|
||||
print "</td>";
|
||||
|
||||
print "<td style='width:50%;' align='right'><strong>(<a href='$c.permalink_url'>$*text_permalink</a>)</strong></td></tr>\n";
|
||||
print "</table></td></tr></table></div>";
|
||||
|
||||
print "<div style='margin-left: 5px'>$c.text</div>\n";
|
||||
print "<div style='margin-top: 3px; font-size: smaller'>";
|
||||
if ($c.frozen) {
|
||||
print "($*text_comment_frozen) ";
|
||||
} else {
|
||||
print "(<a href='$c.reply_url'>$*text_comment_reply</a>) ";
|
||||
}
|
||||
if ($c.parent_url != "") { "(<a href='$c.parent_url'>$*text_comment_parent</a>) "; }
|
||||
if ($c.thread_url != "") { "(<a href='$c.thread_url'>$*text_comment_thread</a>) "; }
|
||||
"</div>\n";
|
||||
}
|
||||
|
||||
function ReplyPage::print_body ()
|
||||
{
|
||||
if (not $.entry.comments.enabled)
|
||||
{
|
||||
print "<h2>$*text_reply_nocomments_header</h2><p>$*text_reply_nocomments</p>";
|
||||
return;
|
||||
}
|
||||
"<table border='0'><tr>";
|
||||
"<td valign='top' width='100' align='center'>";
|
||||
print defined $.replyto.userpic ? "<img src='$.replyto.userpic.url' alt='' /><br />" : "";
|
||||
print defined $.replyto.poster ? $.replyto.poster->as_string() : "<i>(Anonymous)</i>";
|
||||
"</td>";
|
||||
|
||||
"""<td valign="top"><font size="+1">"""; print $.replyto.time->date_format("med"); " "; print $.replyto.time->time_format();
|
||||
if ($.replyto.subject) { " <span style='color: $*subject_color'>$.replyto.subject</span>"; }
|
||||
"</font>";
|
||||
print "<p>$.replyto.text</p>";
|
||||
|
||||
|
||||
"<a href='$.entry.comments.read_url'>Read Comments</a>";
|
||||
"""</td></tr>""";
|
||||
"""<tr><td colspan="2"><p align="center"><img src="$*imguri/hr.gif" width="345" height="23" alt='' /></p>""";
|
||||
"</td></tr></table>\n";
|
||||
print "<h2>Reply</h2>";
|
||||
$.form->print();
|
||||
}
|
||||
|
||||
function print_theme_preview ()
|
||||
{
|
||||
"""
|
||||
<div style="color: $*text_color; background-color: $*body_bgcolor">
|
||||
<table width="70%" border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<table border="0" cellpadding="0" cellspacing="0">
|
||||
<tr>
|
||||
<td width="30"><img src="$*imguri/spacer.gif" width="30" height="10" alt='' /></td>
|
||||
<td width="120" height="18" style="background-image: url($*imguri/tab.jpg)">
|
||||
<a href="#" style="color: $*link_color">Tab</a>
|
||||
</td>
|
||||
<td width="120" height="18" style="background-image: url($*imguri/tab.jpg)">
|
||||
<a href="#" style="color: $*link_color">Tab</a>
|
||||
</td>
|
||||
<td width="120" height="18" style="background-image: url($*imguri/tab.jpg)">
|
||||
<a href="#" style="color: $*link_color">Tab</a>
|
||||
</td>
|
||||
<td width="120" height="18" style="background-image: url($*imguri/tab.jpg)">
|
||||
<a href="#" style="color: $*link_color">Tab</a>
|
||||
</td>
|
||||
<td width="120" height="18" style="background-image: url($*imguri/tab.jpg)">
|
||||
<a href="#" style="color: $*link_color">Tab</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="80" height="38" style="background-image: url($*imguri/top-left.jpg)">
|
||||
<img src="$*imguri/spacer.gif" width="80" height="10" />
|
||||
</td>
|
||||
<td height="38" style="background-image: url($*imguri/middle.jpg)">
|
||||
<img src="$*imguri/spacer.gif" width="10" height="10" />
|
||||
</td>
|
||||
<td width="10" height="38" style="background-image: url($*imguri/top-right.jpg)">
|
||||
<img src="$*imguri/spacer.gif" width="10" height="10" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="80" height="38" style="background-image: url($*imguri/side-left.jpg)">
|
||||
|
||||
</td>
|
||||
<td width="100%" height="38" style="background-image: url($*imguri/middle.jpg)">
|
||||
<h1>John Doe</h1>
|
||||
<p align="center"><img src="$*imguri/hr.gif" width="345" height="23"></p>
|
||||
<p align='center'>
|
||||
<table border='0'><tr><td valign="top">
|
||||
<h1>Dec. 16th, 2002 06:39 pm <span style='color: $*subject_color'>Neque porro quisquam est qui dolorem ipsum quia dolor sit amet…</span></h1>
|
||||
<p>
|
||||
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit
|
||||
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit
|
||||
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit
|
||||
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit
|
||||
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit
|
||||
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit
|
||||
</p>
|
||||
<p><a href="#" style="color: $*vlink_color; font-weight: bold">2 Comments</a> | <a href="#" style="color: $*link_color">Leave a comment</a></p></td></tr>
|
||||
<tr><td colspan="2"><p align="center"><img src="$*imguri/hr.gif" width="345" height="23"></p></td></tr>
|
||||
</table>
|
||||
</p>
|
||||
</td>
|
||||
<td width="8" height="38" style="background-image: url($*imguri/side-right.jpg)">
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="80" height="12" style="background-image: url($*imguri/bottom-left.jpg)">
|
||||
<img src="$*imguri/spacer.gif" width="70" height="12" alt='' />
|
||||
</td>
|
||||
<td height="12" style="background-image: url($*imguri/bottom-line.jpg)">
|
||||
<img src="$*imguri/spacer.gif" width="10" height="12" alt='' />
|
||||
</td>
|
||||
<td width="8" height="12" style="background-image: url($*imguri/bottom-right.jpg)">
|
||||
<img src="$*imguri/spacer.gif" width="8" height="12" alt='' />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
""";
|
||||
}
|
||||
BIN
livejournal/bin/upgrading/s2layers/notepad/notepad.jpg
Executable file
|
After Width: | Height: | Size: 20 KiB |
27
livejournal/bin/upgrading/s2layers/policy.dat
Executable file
@@ -0,0 +1,27 @@
|
||||
# Do not modify this file. To set the S2-usage policy for your own
|
||||
# LiveJournal-based site, create a file beside this one called
|
||||
# policy-local.dat, based on instructions you find in this document.
|
||||
# That file will override anything not set here.
|
||||
#
|
||||
# 'allow' means all users get access. 'deny' means only users with
|
||||
# the 's2styles' capability get access.
|
||||
#
|
||||
|
||||
# Default policy for layouts without their own policy section.
|
||||
layer: *
|
||||
use allow # can all users use it?
|
||||
props allow # can all users modify any property of it?
|
||||
|
||||
# If you decide to make your site's default policy for * to be 'deny',
|
||||
# then you'll have to selectively allow access to parts, like so:
|
||||
|
||||
#layer: generator/layout
|
||||
# use allow
|
||||
# props deny
|
||||
# prop page_bgcolor allow
|
||||
|
||||
# Notes:
|
||||
# -- allowing/denying access to properties is only valid on
|
||||
# layout and core layers.
|
||||
# -- you can't disallow use of a core layer, or i18n layers.
|
||||
# -- for theme layers, you can only set the 'use' property.
|
||||
11
livejournal/bin/upgrading/s2layers/punquin/en.s2
Executable file
@@ -0,0 +1,11 @@
|
||||
# -*-s2-*-
|
||||
|
||||
layerinfo type = "i18n";
|
||||
layerinfo name = "English";
|
||||
layerinfo redist_uniq = "punquin/en";
|
||||
|
||||
set text_meta_music = "music";
|
||||
set text_meta_mood = "mood";
|
||||
|
||||
set text_post_comment = "Comment on this";
|
||||
set text_post_comment_friends = "Comment on this";
|
||||
699
livejournal/bin/upgrading/s2layers/punquin/layout.s2
Executable file
@@ -0,0 +1,699 @@
|
||||
# -*-s2-*-
|
||||
|
||||
layerinfo type = "layout";
|
||||
layerinfo name = "Punquin Elegant";
|
||||
layerinfo redist_uniq = "punquin/layout";
|
||||
layerinfo previews = "punquin/punquin.jpg";
|
||||
|
||||
# Colors
|
||||
propgroup colors {
|
||||
property Color body_bgcolor {
|
||||
des = "Page background color";
|
||||
s1color = "stronger_accent";
|
||||
}
|
||||
property Color main_bgcolor {
|
||||
des = "Background of text areas";
|
||||
s1color = "page_back";
|
||||
}
|
||||
property Color main_fgcolor {
|
||||
des = "Text color";
|
||||
s1color = "page_text";
|
||||
}
|
||||
property Color subject_color {
|
||||
des = "Color of entry subjects";
|
||||
s1color = "page_text_em";
|
||||
}
|
||||
property Color title_color {
|
||||
des = "Color of headers and titles";
|
||||
s1color = "page_text_title";
|
||||
}
|
||||
property Color border_color {
|
||||
des = "Color of borders";
|
||||
s1color = "weak_back";
|
||||
}
|
||||
property Color link_color {
|
||||
des = "Link color";
|
||||
s1color = "page_link";
|
||||
}
|
||||
property Color vlink_color {
|
||||
des = "Visited link color";
|
||||
s1color = "page_vlink";
|
||||
}
|
||||
property Color alink_color {
|
||||
des = "Active link color";
|
||||
s1color = "page_alink";
|
||||
}
|
||||
property Color comment_bar_one_bgcolor {
|
||||
des = "Alternating background color for comment bars (one)";
|
||||
}
|
||||
property Color comment_bar_two_fgcolor {
|
||||
des = "Text color on alternating comment bars (one)";
|
||||
}
|
||||
property Color comment_bar_two_bgcolor {
|
||||
des = "Alternating background color for comment bars (two)";
|
||||
}
|
||||
property Color comment_bar_one_fgcolor {
|
||||
des = "Text color on alternating comment bars (two)";
|
||||
}
|
||||
property Color comment_bar_screened_bgcolor {
|
||||
des = "Background bar color for screened comments";
|
||||
}
|
||||
property Color comment_bar_screened_fgcolor {
|
||||
des = "Text color on background bar for screened comments";
|
||||
}
|
||||
}
|
||||
set body_bgcolor = "#6666cc";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set subject_color = "#c00000";
|
||||
set title_color = "#8b1a1a";
|
||||
set border_color = "#eeeeff";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#c0c0ff";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#eeeeff";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
set comment_bar_screened_bgcolor = "#dddddd";
|
||||
set comment_bar_screened_fgcolor = "#000000";
|
||||
|
||||
propgroup presentation {
|
||||
property bool show_recent_userpic {
|
||||
des = "Show the userpic on the recent entries page?";
|
||||
}
|
||||
property string sidebar_position {
|
||||
des = "Position of the sidebar relative to the main content";
|
||||
values = "left|Left|right|Right";
|
||||
}
|
||||
property use font_base;
|
||||
property use font_fallback;
|
||||
property use page_recent_items;
|
||||
property use page_friends_items;
|
||||
property use use_shared_pic;
|
||||
property use view_entry_disabled;
|
||||
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 linklist_support;
|
||||
property use external_stylesheet;
|
||||
}
|
||||
set font_base = "Verdana, Arial, Helvetica";
|
||||
set font_fallback = "sans-serif";
|
||||
set show_recent_userpic = false;
|
||||
set sidebar_position = "left";
|
||||
set page_recent_items = 20;
|
||||
set page_friends_items = 20;
|
||||
set view_entry_disabled = false;
|
||||
set show_entrynav_icons = true;
|
||||
set page_background_image = "";
|
||||
set linklist_support = false;
|
||||
|
||||
propgroup text {
|
||||
property string text_gotop {
|
||||
des = "Link text to 'top of the page'";
|
||||
noui = 1;
|
||||
}
|
||||
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_website_default_name;
|
||||
}
|
||||
set text_gotop = "Go to Top";
|
||||
set tags_aware = true;
|
||||
|
||||
function print_stylesheet ()
|
||||
{
|
||||
var string font = "$*font_base, $*font_fallback";
|
||||
print clean_url($*page_background_image) != "" ? "body { background-image: url($*page_background_image); }" : "";
|
||||
print """
|
||||
body {
|
||||
background-color: $*body_bgcolor;
|
||||
color: $*main_fgcolor;
|
||||
font: normal normal 10pt $font;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: $*link_color;
|
||||
background: transparent;
|
||||
font: normal normal 10pt $font;
|
||||
}
|
||||
a:visited {
|
||||
color: $*vlink_color;
|
||||
background: transparent;
|
||||
}
|
||||
a:active {
|
||||
color: $*alink_color;
|
||||
background: transparent;
|
||||
}
|
||||
#title {
|
||||
font: normal bold 10pt $font;
|
||||
color: $*title_color;
|
||||
text-align: center;
|
||||
}
|
||||
.date {
|
||||
font: normal bold 12pt $font;
|
||||
color: $*title_color;
|
||||
text-align: right;
|
||||
}
|
||||
.comments {
|
||||
font: normal normal 8pt $font;
|
||||
}
|
||||
hr.separator {
|
||||
color: $*border_color;
|
||||
}
|
||||
.siteplug {
|
||||
font: normal normal 8pt $font;
|
||||
}
|
||||
#yearheader {
|
||||
text-align: right;
|
||||
color: $*title_color;
|
||||
font: normal bold 12pt $font;
|
||||
}
|
||||
th.monthheader {
|
||||
color: $*title_color;
|
||||
}
|
||||
th.daysheader {
|
||||
color: $*subject_color;
|
||||
}
|
||||
|
||||
/* Tables. Fun. */
|
||||
|
||||
table#main {
|
||||
border: solid 0px $*body_bgcolor;
|
||||
}
|
||||
table.standard {
|
||||
border: solid 5px $*border_color;
|
||||
background-color: $*main_bgcolor;
|
||||
color: $*main_fgcolor;
|
||||
font: normal normal 10pt $font;
|
||||
}
|
||||
table.standard>td {
|
||||
background-color: $*main_bgcolor;
|
||||
color: $*main_fgcolor;
|
||||
}
|
||||
table.standard td {
|
||||
font: normal normal 10pt $font;
|
||||
}
|
||||
""";
|
||||
}
|
||||
|
||||
|
||||
function Page::lay_sidebar_navigation () { }
|
||||
|
||||
function print_sidebar(Page p) {
|
||||
var string title = $p->title();
|
||||
var string userpic;
|
||||
var Image up_img = $p.journal.default_pic;
|
||||
if (defined $up_img) {
|
||||
$userpic = """<p align="center"><img border="0" src="$up_img.url" height="$up_img.height" width="$up_img.width" alt="" /></p>""";
|
||||
}
|
||||
|
||||
var string website_name = $p.journal.website_name ? $p.journal.website_name : $*text_website_default_name;
|
||||
var string website;
|
||||
if ($p.journal.website_url != "") {
|
||||
$website = """> <a href="$p.journal.website_url">$website_name</a><br />""";
|
||||
}
|
||||
|
||||
var string links;
|
||||
foreach var string v ($p.views_order) {
|
||||
$links = "$links> " + ($p.view == $v ?
|
||||
lang_viewname($v) :
|
||||
"<a href='$p.view_url{$v}'>"+lang_viewname($v)+"</a>") + "<br />\n";
|
||||
}
|
||||
|
||||
# Table Wrapper
|
||||
"<!-- Begin Main Sidebar -->\n<td valign='top' align='$*sidebar_position'>";
|
||||
"<table width='150' class='standard' cellpadding='5' cellspacing='0'>\n";
|
||||
"<tr valign='top'><td align='left'>";
|
||||
|
||||
# Title
|
||||
"<div style='text-align:center'><span style='color: $*title_color'><strong>$title</strong></span></div>\n";
|
||||
|
||||
# Links
|
||||
"<p>$links\n$website\n";
|
||||
$p->lay_sidebar_navigation();
|
||||
|
||||
# Userpic
|
||||
"</p>"; if($userpic != "") { "<div style='text-align:center'>$userpic</div>"; }
|
||||
|
||||
# Link List
|
||||
if (size $p.linklist > 0 and $*linklist_support) {
|
||||
if (not $p.linklist[0].is_heading) {
|
||||
"<b>Links</b><br />";
|
||||
}
|
||||
$p->print_linklist();
|
||||
}
|
||||
|
||||
# End Table
|
||||
"</td></tr></table>\n<!-- End Main Sidebar -->";
|
||||
}
|
||||
|
||||
function print_gotop (Page p)
|
||||
{
|
||||
"<td valign='bottom' align='$*sidebar_position'>\n<!-- Begin Small Sidebar -->\n";
|
||||
"<table width='150' class='standard' cellpadding='5' cellspacing='0'>\n";
|
||||
"<tr valign='top'><td align='left'>\n";
|
||||
$p->lay_sidebar_navigation();
|
||||
"<br />> <a href='#top'>$*text_gotop</a><br>\n</td></tr></table>\n<!-- End Small Sidebar -->";
|
||||
}
|
||||
|
||||
function Page::print ()
|
||||
{
|
||||
var string title = $this->title();
|
||||
var string main_position = $*sidebar_position == "left" ? "right" : "left";
|
||||
|
||||
# Head
|
||||
println "<html><head>";
|
||||
|
||||
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>\n</head>\n";
|
||||
|
||||
# Body
|
||||
"<body>\n<a name='top'></a><div align='center'>\n";
|
||||
|
||||
# Table wrapper
|
||||
"<table id='main' cellpadding='5' cellspacing='0' width='90%'>\n<tr>";
|
||||
|
||||
if ($*sidebar_position == "left") { print_sidebar($this); }
|
||||
|
||||
# Main content
|
||||
"<td valign='top' align='$main_position' rowspan='2'>\n<!-- Begin Main -->\n";
|
||||
"<table class='standard' width='100%' height='90%' cellpadding='5' cellspacing='0'><tr valign='top'><td>\n";
|
||||
$this->print_body();
|
||||
"</td></tr></table>\n<!-- End Main -->\n</td>";
|
||||
|
||||
if ($*sidebar_position == "right") { print_sidebar($this); }
|
||||
|
||||
# Go to top
|
||||
"</tr><tr>";
|
||||
print_gotop($this);
|
||||
"</tr><tr>";
|
||||
|
||||
# Plug the site!
|
||||
"<td colspan='2' align='$main_position'>\n";
|
||||
"<a href='$*SITEROOT/'>$*SITENAME</a></td>\n";
|
||||
|
||||
"</tr></table></div></body></html>";
|
||||
}
|
||||
|
||||
function print_entry (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text)
|
||||
{
|
||||
var string time = $e.time->time_format();
|
||||
if ($e.new_day or $p.view == "entry") {
|
||||
"<p class='date'>"; print $e.time->date_format("%%month%% %%dayord%%, %%yyyy%%"); "</p>";
|
||||
"<hr class='separator' />";
|
||||
}
|
||||
|
||||
if ($p.view == "entry" and $*show_entrynav_icons)
|
||||
{
|
||||
print "<div style='text-align: center'>";
|
||||
$e->print_linkbar();
|
||||
print "</div>";
|
||||
}
|
||||
|
||||
"<table border='0' cellpadding='2' cellspacing='0'><tr>";
|
||||
|
||||
if ($p.view == "friends" or
|
||||
$e.poster.username != $e.journal.username or
|
||||
$*show_recent_userpic == true)
|
||||
{
|
||||
# Lots of muddled logic. Yay.
|
||||
|
||||
"""<td valign=top align="middle" style="background-color: $bgcolor" width="100">""";
|
||||
if ($p.view == "friends") {
|
||||
"""<a href='""" + $e.journal->base_url() + """/' style="color: $fgcolor; font-weight: bold">$e.journal.username</a><br />""";
|
||||
}
|
||||
if ($e.poster.username != $e.journal.username) {
|
||||
if ($p.view == "friends") {
|
||||
"""[<a href='""" + $e.poster->base_url() + """/' style="color: $fgcolor">$e.poster.username</a>]<br />""";
|
||||
} else {
|
||||
"""<a href='""" + $e.poster->base_url() + """/' style="color: $fgcolor; font-weight: bold">$e.poster.username</a><br />""";
|
||||
}
|
||||
}
|
||||
if (defined $e.userpic) {
|
||||
if (($*show_recent_userpic == false) and
|
||||
($p.view != "friends") and
|
||||
($p.journal_type != "C") ) { }
|
||||
else { """<img border="0" src="$e.userpic.url" width="$e.userpic.width" height="$e.userpic.height" alt="" />""";
|
||||
}
|
||||
}
|
||||
"</td>";
|
||||
}
|
||||
"<td valign='top'><strong>$time";
|
||||
if ($e.subject) { " - <span style='color: $*subject_color'>$e.subject</span>"; }
|
||||
|
||||
if ($e.security) {
|
||||
" "; $e.security_icon->print();
|
||||
}
|
||||
"</strong><br />";
|
||||
if (not $hide_text) {
|
||||
print $e.text; "<br />";
|
||||
if (size $e.metadata) {
|
||||
foreach var string k ($e.metadata) {
|
||||
var string key = $k;
|
||||
var string val = $e.metadata{$k};
|
||||
if ($k == "mood") {
|
||||
$key = $*text_meta_mood;
|
||||
} elseif ( $k == "music" ) {
|
||||
$key = $*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='absmiddle' alt='[mood icon]' /> $val";
|
||||
}
|
||||
"<strong>$key:</strong> $val<br />";
|
||||
}
|
||||
}
|
||||
if ($e.tags) {
|
||||
var int tcount = 0;
|
||||
"<div class='ljtags'><strong>Tags:</strong> ";
|
||||
foreach var Tag t ($e.tags) {
|
||||
"""<a rel="tag" href="$t.url">$t.name</a>""";
|
||||
$tcount++;
|
||||
if ($tcount != size $e.tags) { ", "; }
|
||||
}
|
||||
"</div>";
|
||||
}
|
||||
}
|
||||
"</td></tr></table>";
|
||||
$e.comments->print();
|
||||
}
|
||||
|
||||
function Page::print_entry (Entry e)
|
||||
{
|
||||
print_entry($this, $e, null Color, null Color, false);
|
||||
}
|
||||
|
||||
function FriendsPage::print_entry (Entry e) {
|
||||
var Friend f = $.friends{$e.journal.username};
|
||||
print_entry($this, $e, $f.bgcolor, $f.fgcolor, false);
|
||||
}
|
||||
|
||||
function RecentPage::print_body {
|
||||
foreach var Entry e ($.entries) {
|
||||
$this->print_entry($e);
|
||||
}
|
||||
}
|
||||
|
||||
function FriendsPage::print_body {
|
||||
foreach var Entry e ($.entries) {
|
||||
$this->print_entry($e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function RecentPage::lay_sidebar_navigation () {
|
||||
var int total = size $.entries;
|
||||
var string nav = "";
|
||||
if ($.nav.backward_url != "") {
|
||||
$nav = """> <a href="$.nav.backward_url">previous $total entries</a>""";
|
||||
}
|
||||
if ($.nav.forward_url != "" and $.nav.backward_url != "") {
|
||||
$nav = "$nav<br />";
|
||||
}
|
||||
if ($.nav.forward_url != "") {
|
||||
$nav = """${nav}> <a href="$.nav.forward_url">next $total entries</a>""";
|
||||
}
|
||||
print $nav;
|
||||
}
|
||||
|
||||
function CommentInfo::print ()
|
||||
{
|
||||
if (not $.enabled) {
|
||||
"<p align='right' class='comments'> </p>";
|
||||
return;
|
||||
}
|
||||
"<p align='right' class='comments'>(";
|
||||
if ($.count > 0 or $.screened) {
|
||||
$this->print_readlink();
|
||||
" | ";
|
||||
}
|
||||
$this->print_postlink();
|
||||
")</p>";
|
||||
}
|
||||
|
||||
function YearPage::print_body {
|
||||
"<p id='yearheader'>$.year</p>\n";
|
||||
foreach var YearMonth m ($.months) {
|
||||
$this->print_month($m);
|
||||
}
|
||||
}
|
||||
|
||||
function YearPage::print_year_links ()
|
||||
{
|
||||
foreach var YearYear y ($.years) {
|
||||
if ($y.displayed) {
|
||||
"> $y.year<br />";
|
||||
} else {
|
||||
"> <a href=\"$y.url\">$y.year</a><br />";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function YearPage::lay_sidebar_navigation ()
|
||||
{
|
||||
$this->print_year_links();
|
||||
}
|
||||
|
||||
function YearPage::print_month(YearMonth m)
|
||||
{
|
||||
if (not $m.has_entries) { return; }
|
||||
# Table Wrapper
|
||||
"<center><p><table border='1' cellpadding='4' width='80%'>\n";
|
||||
|
||||
# Month Header
|
||||
"<tr align='center'><th colspan='7' class='monthheader'>\n";
|
||||
print $m->month_format();
|
||||
"</th></tr>\n";
|
||||
|
||||
# Weekdays Header
|
||||
"<tr align='center'>\n";
|
||||
foreach var int d (weekdays()) {
|
||||
"<th class='daysheader'>"+$*lang_dayname_short[$d]+"</th>\n";
|
||||
}
|
||||
"</tr>\n";
|
||||
|
||||
# Weeks
|
||||
foreach var YearWeek w ($m.weeks) {
|
||||
$w->print();
|
||||
}
|
||||
|
||||
# Footer
|
||||
"<tr><td colspan='7'><div style='text-align: center'><a href='$m.url'>view subjects</a></div></td></tr>\n";
|
||||
|
||||
# End Table
|
||||
"</table></p></center>\n";
|
||||
}
|
||||
|
||||
function YearWeek::print () {
|
||||
"<tr>";
|
||||
if ($.pre_empty) { "<td colspan='$.pre_empty'> </td>"; }
|
||||
foreach var YearDay d ($.days) {
|
||||
"<td valign='top'><strong>$d.day</strong><div style='text-align: center'>";
|
||||
if ($d.num_entries) {
|
||||
"<a href='$d.url'>$d.num_entries</a>";
|
||||
} else {
|
||||
" ";
|
||||
}
|
||||
"</div></td>\n";
|
||||
}
|
||||
if ($.post_empty) { "<td colspan='$.post_empty'> </td>"; }
|
||||
"</tr>";
|
||||
}
|
||||
|
||||
function DayPage::print_body() {
|
||||
if (not $.has_entries) {
|
||||
"<table width='100%'><tr><td><p class='date'>\n";
|
||||
print $.date->date_format("%%month%% %%dayord%%, %%yyyy%%");
|
||||
"</p><hr class='separator' width='100%' /></td></tr>";
|
||||
"<tr><td><blockquote align='center'>"; print ehtml($*text_noentries_day); "</blockquote></td></tr></table>";
|
||||
} else {
|
||||
foreach var Entry e ($.entries) {
|
||||
$this->print_entry($e);
|
||||
}
|
||||
}
|
||||
|
||||
var string tprev = ehtml($*text_day_prev);
|
||||
var string tnext = ehtml($*text_day_next);
|
||||
|
||||
"<hr class='separator' width='100%' />\n";
|
||||
"<table width='100%'><tr align='middle'>\n";
|
||||
|
||||
"<td width='33%' align='left'><a href='$.prev_url'>$tprev</a></td>\n";
|
||||
"<td align='center' width='33%'>[<a href='"; print $this.journal->base_url(); "/calendar'>$*text_view_archive</a>]</td>\n";
|
||||
"<td width='33%' align='right'><a href='$.next_url'>$tnext</a></td>\n";
|
||||
|
||||
"</tr></table>";
|
||||
}
|
||||
|
||||
function EntryPage::print_body ()
|
||||
{
|
||||
set_handler("unscreen_comment_#", [
|
||||
[ "style_bgcolor", "cmtbar#", "$*comment_bar_one_bgcolor", ],
|
||||
[ "style_color", "cmtbar#", "$*comment_bar_one_fgcolor", ],
|
||||
]);
|
||||
set_handler("screen_comment_#", [
|
||||
[ "style_bgcolor", "cmtbar#", "$*comment_bar_screened_bgcolor", ],
|
||||
[ "style_color", "cmtbar#", "$*comment_bar_screened_fgcolor", ],
|
||||
]);
|
||||
|
||||
print_entry($this, $.entry, null Color, null Color, $.viewing_thread);
|
||||
if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0)
|
||||
{
|
||||
$this->print_multiform_start();
|
||||
print "<h2 class='date'>Comments:</h2>";
|
||||
"<hr class='separator' />";
|
||||
if ($.comment_pages.total_subitems > 0) {
|
||||
$.comment_pages->print();
|
||||
$this->print_comments($.comments);
|
||||
}
|
||||
if ($this.multiform_on) {
|
||||
print "<h2 class='date'>Mass Action:</h2>";
|
||||
"<hr class='separator' />";
|
||||
$this->print_multiform_actionline();
|
||||
$this->print_multiform_end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function EntryPage::print_comment (Comment c) {
|
||||
var Color background; var Color color;
|
||||
if ($c.screened) {
|
||||
$background = $*comment_bar_screened_bgcolor;
|
||||
$color = $*comment_bar_screened_fgcolor;
|
||||
} elseif ($c.depth % 2) {
|
||||
$background = $*comment_bar_one_bgcolor;
|
||||
$color = $*comment_bar_one_fgcolor;
|
||||
} else {
|
||||
$background = $*comment_bar_two_bgcolor;
|
||||
$color = $*comment_bar_two_fgcolor;
|
||||
}
|
||||
var string poster = defined $c.poster ? $c.poster->as_string() : "<i>(Anonymous)</i>";
|
||||
var string sub_icon;
|
||||
if (defined $c.subject_icon) {
|
||||
$sub_icon = $c.subject_icon->as_string();
|
||||
}
|
||||
"<a name='$c.anchor'></a><div id='cmtbar$c.talkid' style='background-color: $background; color: $color; margin-top: 10px; width: 100%'>";
|
||||
"<table cellpadding='2' cellspacing='0' summary='0' style='width: 100%'><tr valign='top'>";
|
||||
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;
|
||||
}
|
||||
print "<td style='width: 102px'><img src='$c.userpic.url' width='$w' height='$h' alt='[User Picture]' /></td>";
|
||||
}
|
||||
|
||||
"<td style='width: 100%'><table style='width: 100%'><tr>";
|
||||
|
||||
### From, date, etc
|
||||
"<td align='left' style='width: 50%'>";
|
||||
print "<table>";
|
||||
print "<tr><th align='right' style='font-size: .9em'>From:</th><td>$poster</td></tr>\n";
|
||||
print "<tr><th align='right' style='font-size: .9em'>Date:</th><td style='white-space: nowrap'>";
|
||||
print $c.time->date_format("long") + " - " + $c.time->time_format() + "</td></tr>";
|
||||
if ($c.metadata{"poster_ip"}) { print "<tr><th align='right' style='font-size: .9em'>IP Address:</th><td>(" + $c.metadata{"poster_ip"} + ")</td></tr>"; }
|
||||
"</table></td>";
|
||||
|
||||
### Gadgets
|
||||
"<td align='right' style='width: 50%'>";
|
||||
if ($this.multiform_on) {
|
||||
" <label for='ljcomsel_$c.talkid'>$*text_multiform_check</label>";
|
||||
$c->print_multiform_check();
|
||||
}
|
||||
$c->print_linkbar();
|
||||
"</td></tr>";
|
||||
|
||||
### Subject / icon
|
||||
print "<tr valign='top'><td style='width: 50%'>";
|
||||
print (defined $c.subject_icon or $c.subject != "") ? "<h3>$c.subject_icon $c.subject</h3>" : "";
|
||||
print "</td>";
|
||||
|
||||
### Permalink
|
||||
print "<td style='width: 50%' align='right'><strong>(<a href='$c.permalink_url'>Link</a>)</strong></td></tr>";
|
||||
|
||||
print "</table></td></tr></table></div>";
|
||||
print "<div style='margin-left: 5px'>$c.text</div>";
|
||||
print "<div style='margin-top: 3px; font-size: smaller'>";
|
||||
if ($c.frozen) {
|
||||
print "(Replies frozen)";
|
||||
} else {
|
||||
print "(<a href='$c.reply_url'>Reply to this</a>) ";
|
||||
}
|
||||
if ($c.parent_url != "") { "(<a href='$c.parent_url'>Parent</a>) "; }
|
||||
if ($c.thread_url != "") { "(<a href='$c.thread_url'>Thread</a>) "; }
|
||||
"</div>";
|
||||
}
|
||||
|
||||
function ReplyPage::print_body() {
|
||||
if (not $.entry.comments.enabled)
|
||||
{
|
||||
"<h2 class='date'>$*text_reply_nocomments_header</h2>";
|
||||
"<hr class='separator' />";
|
||||
"<p>$*text_reply_nocomments</p>";
|
||||
return;
|
||||
}
|
||||
"<p class='date'>"; print $.replyto.time->date_format("%%month%% %%dayord%%, %%yyyy%%"); "</p>";
|
||||
"<hr class='separator' />";
|
||||
|
||||
"<table border='0' cellpadding='2' cellspacing='0'><tr>";
|
||||
|
||||
"""<td valign=top align="middle" width="100">""";
|
||||
print defined $.replyto.poster ? $.replyto.poster->as_string() : "<i>(Anonymous)</i>";
|
||||
if (defined $.replyto.userpic) {
|
||||
print """<img border="0" src="$.replyto.userpic.url" width="$.replyto.userpic.width" height="$.replyto.userpic.height" alt="" />""";
|
||||
}
|
||||
"</td>";
|
||||
|
||||
"<td valign='top'><strong>"; print $.replyto.time->time_format();
|
||||
if ($.replyto.subject) { " - <span style='color: $*subject_color'>$.replyto.subject</span>"; }
|
||||
|
||||
"</strong><br />";
|
||||
|
||||
print $.replyto.text; "<br />";
|
||||
|
||||
"</td></tr></table>";
|
||||
"<p align='right' class='comments'><a href='$.entry.comments.read_url'>Read Comments</a></p>";
|
||||
"<h2 class='date'>Reply</h2>";
|
||||
"<hr class='separator' />";
|
||||
$.form->print();
|
||||
}
|
||||
|
||||
function print_theme_preview ()
|
||||
{
|
||||
"""
|
||||
<table width="100%" style="background-color: $*body_bgcolor; border: solid 1px #000000"><tr><td style="color:$*main_fgcolor">
|
||||
<table bgcolor="$*border_color" border="0" cellpadding="5" cellspacing="0" width="60%" align="center">
|
||||
<tr><td valign="center" align="center">
|
||||
<table width="100%" height=90% bgcolor="$*main_bgcolor" border="0" cellpadding="5" cellspacing="0">
|
||||
<tr valign="top"><td>
|
||||
<p align="right"><font color="$*title_color" face="verdana,arial,helvetica" size="3">
|
||||
<strong>December 18th, 2002</strong></font><hr noshade color="$*border_color" size="1" width="100%" />
|
||||
</p>
|
||||
<font face="verdana,arial,helvetica" size="2">
|
||||
<b>01:22 am - <font color="$*subject_color">Test</font></b><font face="verdana,arial,helvetica" size="2"><br />
|
||||
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit.
|
||||
Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit.</font>
|
||||
<p align="right">(<a style="color: $*link_color" href="#">Read # Comments</a> | <a style="color: $*vlink_color" href="#">Leave a comment</a>)</p>
|
||||
</td></tr>
|
||||
</table>
|
||||
</td></tr>
|
||||
</table>
|
||||
</td></tr></table>
|
||||
""";
|
||||
}
|
||||
BIN
livejournal/bin/upgrading/s2layers/punquin/punquin.jpg
Executable file
|
After Width: | Height: | Size: 12 KiB |
450
livejournal/bin/upgrading/s2layers/punquin/themes.s2
Executable file
@@ -0,0 +1,450 @@
|
||||
#NEWLAYER: punquin/bw
|
||||
layerinfo type = "theme";
|
||||
layerinfo name = "Black on White";
|
||||
layerinfo redist_uniq = "punquin/bw";
|
||||
set body_bgcolor = "#333333";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set subject_color = "#c00000";
|
||||
set title_color = "#336699";
|
||||
set border_color = "#dddddd";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#dddddd";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#aaaaaa";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: punquin/autumn
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Autumn";
|
||||
layerinfo redist_uniq = "punquin/autumn";
|
||||
layerinfo author = "pumpsnail";
|
||||
set body_bgcolor = "#660033";
|
||||
set main_bgcolor = "#990022";
|
||||
set main_fgcolor = "#ffffff";
|
||||
set subject_color = "#ffffff";
|
||||
set title_color = "#ffffff";
|
||||
set border_color = "#fcc303";
|
||||
set link_color = "#cc6600";
|
||||
set vlink_color = "#cc99cc";
|
||||
set alink_color = "#ffcc33";
|
||||
set comment_bar_one_bgcolor = "#660033";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#993366";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: punquin/greyslate
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Grey Slate Rain";
|
||||
layerinfo redist_uniq = "punquin/greyslate";
|
||||
set body_bgcolor = "#67698f";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set subject_color = "#000000";
|
||||
set title_color = "#336699";
|
||||
set border_color = "#dddddd";
|
||||
set link_color = "#8e80f8";
|
||||
set vlink_color = "#c780f8";
|
||||
set alink_color = "#f880dd";
|
||||
set comment_bar_one_bgcolor = "#dddddd";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#aaaaaa";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: punquin/minimal
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Minimalist";
|
||||
layerinfo redist_uniq = "punquin/minimal";
|
||||
set body_bgcolor = "#ffffff";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#333333";
|
||||
set subject_color = "#333333";
|
||||
set title_color = "#333333";
|
||||
set border_color = "#aaaaaa";
|
||||
set link_color = "#8e80f8";
|
||||
set vlink_color = "#c780f8";
|
||||
set alink_color = "#f880dd";
|
||||
set comment_bar_one_bgcolor = "#dddddd";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#aaaaaa";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: punquin/jewel
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Jewel Toned";
|
||||
layerinfo redist_uniq = "punquin/jewel";
|
||||
set body_bgcolor = "#950875";
|
||||
set main_bgcolor = "#f3a8e2";
|
||||
set main_fgcolor = "#000000";
|
||||
set subject_color = "#c00000";
|
||||
set title_color = "#336699";
|
||||
set border_color = "#dddddd";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#950875";
|
||||
set comment_bar_one_fgcolor = "#f3a8e2";
|
||||
set comment_bar_two_bgcolor = "#b70875";
|
||||
set comment_bar_two_fgcolor = "#f3a8e2";
|
||||
|
||||
#NEWLAYER: punquin/bold
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Bold";
|
||||
layerinfo redist_uniq = "punquin/bold";
|
||||
set body_bgcolor = "#2501da";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set subject_color = "#c00453";
|
||||
set title_color = "#f50930";
|
||||
set border_color = "#000000";
|
||||
set link_color = "#5f5cd5";
|
||||
set vlink_color = "#2a2ab2";
|
||||
set alink_color = "#4a92eb";
|
||||
set comment_bar_one_bgcolor = "#2501da";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#2501fc";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: punquin/shrinkvio
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Shrinking Violet";
|
||||
layerinfo redist_uniq = "punquin/shrinkvio";
|
||||
set body_bgcolor = "#ad22e7";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#381a45";
|
||||
set title_color = "#5d0383";
|
||||
set subject_color = "#d9a1f1";
|
||||
set link_color = "#2e053f";
|
||||
set vlink_color = "#611627";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#5d0383";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#d9a1f1";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: punquin/pistmint
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Pistachio Mint";
|
||||
layerinfo redist_uniq = "punquin/pistmint";
|
||||
set body_bgcolor = "#133422";
|
||||
set main_bgcolor = "#a7c4b4";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#096d36";
|
||||
set title_color = "#096d36";
|
||||
set subject_color = "#096d36";
|
||||
set link_color = "#8afabc";
|
||||
set vlink_color = "#1da65a";
|
||||
set alink_color = "#f9f5f5";
|
||||
set comment_bar_one_bgcolor = "#096d36";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#093d36";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: punquin/mexicanfood
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Mexican Food";
|
||||
layerinfo redist_uniq = "punquin/mexicanfood";
|
||||
set body_bgcolor = "#ff0000";
|
||||
set main_bgcolor = "#f8ff3e";
|
||||
set main_fgcolor = "#f15601";
|
||||
set border_color = "#f50701";
|
||||
set title_color = "#bdbf3e";
|
||||
set subject_color = "#f9ff9d";
|
||||
set link_color = "#f49e08";
|
||||
set vlink_color = "#b05403";
|
||||
set alink_color = "#ff7405";
|
||||
set comment_bar_one_bgcolor = "#bdbf3e";
|
||||
set comment_bar_one_fgcolor = "#ff0000";
|
||||
set comment_bar_two_bgcolor = "#e15a18";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: punquin/ashfire
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Ash and Fire";
|
||||
layerinfo redist_uniq = "punquin/ashfire";
|
||||
set body_bgcolor = "#b5b5b5";
|
||||
set main_bgcolor = "#ffb6af";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#d90308";
|
||||
set title_color = "#e75454";
|
||||
set subject_color = "#ff1106";
|
||||
set link_color = "#f70208";
|
||||
set vlink_color = "#b0161d";
|
||||
set alink_color = "#d70106";
|
||||
set comment_bar_one_bgcolor = "#e75454";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#f06c88";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: punquin/desktop
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Classic Desktop";
|
||||
layerinfo redist_uniq = "punquin/desktop";
|
||||
set body_bgcolor = "#00545c";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#000000";
|
||||
set title_color = "#ff7b05";
|
||||
set subject_color = "#ff7b05";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#5a76ff";
|
||||
set comment_bar_one_bgcolor = "#ff7b05";
|
||||
set comment_bar_one_fgcolor = "#ffeddd";
|
||||
set comment_bar_two_bgcolor = "#ffeddd";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: punquin/satinhandshake
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Satin Handshake";
|
||||
layerinfo redist_uniq = "punquin/satinhandshake";
|
||||
set body_bgcolor = "#480c0c";
|
||||
set main_bgcolor = "#d06464";
|
||||
set main_fgcolor = "#00001d";
|
||||
set border_color = "#000000";
|
||||
set title_color = "#aaaaaa";
|
||||
set subject_color = "#9d0404";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#aaaaaa";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#9d0404";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: punquin/deepmelodrama
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Deep MeloDrama";
|
||||
layerinfo redist_uniq = "punquin/deepmelodrama";
|
||||
set body_bgcolor = "#872d89";
|
||||
set main_bgcolor = "#719cff";
|
||||
set main_fgcolor = "#8e48b2";
|
||||
set border_color = "#8e48b2";
|
||||
set title_color = "#3794b3";
|
||||
set subject_color = "#8e48b2";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#dfd3ff";
|
||||
set comment_bar_one_bgcolor = "#3794b3";
|
||||
set comment_bar_one_fgcolor = "#84b8e7";
|
||||
set comment_bar_two_bgcolor = "#65b2c1";
|
||||
set comment_bar_two_fgcolor = "#f5d3ff";
|
||||
|
||||
#NEWLAYER: punquin/everwhite
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Everwhite";
|
||||
layerinfo redist_uniq = "punquin/everwhite";
|
||||
set body_bgcolor = "#ffffff";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#000000";
|
||||
set title_color = "#ffffff";
|
||||
set subject_color = "#ff0000";
|
||||
set link_color = "#e60000";
|
||||
set vlink_color = "#c10602";
|
||||
set alink_color = "#ff0600";
|
||||
set comment_bar_one_bgcolor = "#dddddd";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#aaaaaa";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: punquin/everblue
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Everblue with Greys";
|
||||
layerinfo redist_uniq = "punquin/everblue";
|
||||
set body_bgcolor = "#0f0c6d";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#000000";
|
||||
set title_color = "#000000";
|
||||
set subject_color = "#000000";
|
||||
set link_color = "#2f00f2";
|
||||
set vlink_color = "#060667";
|
||||
set alink_color = "#6691ff";
|
||||
set comment_bar_one_bgcolor = "#000000";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#aaaaaa";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: punquin/brownleather
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Brown Leather Coat";
|
||||
layerinfo redist_uniq = "punquin/brownleather";
|
||||
set body_bgcolor = "#d2b48c";
|
||||
set main_bgcolor = "#ffebcd";
|
||||
set main_fgcolor = "#8b4513";
|
||||
set border_color = "#000000";
|
||||
set title_color = "#d48014";
|
||||
set subject_color = "#d48014";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#867a55";
|
||||
set alink_color = "#fffab3";
|
||||
set comment_bar_one_bgcolor = "#d48014";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#ffe1a1";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: punquin/bruise
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Bruise";
|
||||
layerinfo redist_uniq = "punquin/bruise";
|
||||
set body_bgcolor = "#000000";
|
||||
set main_bgcolor = "#bcbcbc";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#000000";
|
||||
set title_color = "#1114a0";
|
||||
set subject_color = "#1114a0";
|
||||
set link_color = "#0000cc";
|
||||
set vlink_color = "#000088";
|
||||
set alink_color = "#0000ff";
|
||||
set comment_bar_one_bgcolor = "#1114a0";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#21c2f1";
|
||||
set comment_bar_two_fgcolor = "#0000ff";
|
||||
|
||||
#NEWLAYER: punquin/ranchhand
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Ranch Hand";
|
||||
layerinfo redist_uniq = "punquin/ranchhand";
|
||||
set body_bgcolor = "#2999c2";
|
||||
set main_bgcolor = "#cfe0ff";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#060667";
|
||||
set title_color = "#54442c";
|
||||
set subject_color = "#9d995d";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#6a20ff";
|
||||
set comment_bar_one_bgcolor = "#54442c";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#704400";
|
||||
set comment_bar_two_fgcolor = "#bababa";
|
||||
|
||||
#NEWLAYER: punquin/victim
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Victim";
|
||||
layerinfo redist_uniq = "punquin/victim";
|
||||
set body_bgcolor = "#2cd0ff";
|
||||
set main_bgcolor = "#505050";
|
||||
set main_fgcolor = "#ffffff";
|
||||
set border_color = "#000000";
|
||||
set title_color = "#166bac";
|
||||
set subject_color = "#26b6ff";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#166bac";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#353535";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: punquin/forest
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Forest";
|
||||
layerinfo redist_uniq = "punquin/forest";
|
||||
set body_bgcolor = "#778e64";
|
||||
set main_bgcolor = "#9b9ba5";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#ffffff";
|
||||
set title_color = "#72784c";
|
||||
set subject_color = "#a0ac62";
|
||||
set link_color = "#3811e1";
|
||||
set vlink_color = "#310cbb";
|
||||
set alink_color = "#4e7bef";
|
||||
set comment_bar_one_bgcolor = "#72784c";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#73777a";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: punquin/drone
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Drone";
|
||||
layerinfo redist_uniq = "punquin/drone";
|
||||
set body_bgcolor = "#395f82";
|
||||
set main_bgcolor = "#f9fcfe";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#000000";
|
||||
set title_color = "#904094";
|
||||
set subject_color = "#ff93ff";
|
||||
set link_color = "#395f82";
|
||||
set vlink_color = "#395f82";
|
||||
set alink_color = "#5266ce";
|
||||
set comment_bar_one_bgcolor = "#904094";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#eeeeff";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: punquin/lowercurtain
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Lower the Curtain";
|
||||
layerinfo redist_uniq = "punquin/lowercurtain";
|
||||
set body_bgcolor = "#000000";
|
||||
set main_bgcolor = "#6b6b6b";
|
||||
set main_fgcolor = "#ffffff";
|
||||
set border_color = "#ffffff";
|
||||
set title_color = "#363636";
|
||||
set subject_color = "#363636";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#3314ba";
|
||||
set comment_bar_one_bgcolor = "#363636";
|
||||
set comment_bar_one_fgcolor = "#f0f5fb";
|
||||
set comment_bar_two_bgcolor = "#c5c8ca";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: punquin/sunny
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Sunny Day";
|
||||
layerinfo redist_uniq = "punquin/sunny";
|
||||
set body_bgcolor = "#55e0f9";
|
||||
set main_bgcolor = "#e38202";
|
||||
set main_fgcolor = "#ffffff";
|
||||
set border_color = "#000000";
|
||||
set title_color = "#e38202";
|
||||
set subject_color = "#efe052";
|
||||
set link_color = "#df0d12";
|
||||
set vlink_color = "#ac1b25";
|
||||
set alink_color = "#fe3b3b";
|
||||
set comment_bar_one_bgcolor = "#e38202";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#ffba03";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: punquin/valentine
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Be Mine";
|
||||
layerinfo redist_uniq = "punquin/valentine";
|
||||
set body_bgcolor = "#6f104a";
|
||||
set main_bgcolor = "#f2bce9";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#ff24ab";
|
||||
set title_color = "#ff37ff";
|
||||
set subject_color = "#ae1774";
|
||||
set link_color = "#ffffff";
|
||||
set vlink_color = "#a51014";
|
||||
set alink_color = "#ed8188";
|
||||
set comment_bar_one_bgcolor = "#ff37ff";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#df2096";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: punquin/stripes
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Stripes";
|
||||
layerinfo redist_uniq = "punquin/stripes";
|
||||
set body_bgcolor = "#ffffff";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#ff0000";
|
||||
set title_color = "#e7212a";
|
||||
set subject_color = "#ffffff";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ffafc1";
|
||||
set comment_bar_one_bgcolor = "#e7212a";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#ffcfdc";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
850
livejournal/bin/upgrading/s2layers/sturdygesture/layout.s2
Executable file
@@ -0,0 +1,850 @@
|
||||
# -*-s2-*-
|
||||
|
||||
layerinfo type = "layout";
|
||||
layerinfo name = "A Sturdy Gesture";
|
||||
layerinfo lang = "en";
|
||||
|
||||
layerinfo author = "Martin Atkins";
|
||||
layerinfo author_email = "mart@livejournal.com";
|
||||
|
||||
layerinfo redist_uniq = "sturdygesture/layout";
|
||||
layerinfo previews = "sturdygesture/sturdygesture.jpg";
|
||||
|
||||
propgroup colors {
|
||||
property Color clr_page_back { des = "Page background"; }
|
||||
set clr_page_back = "#ffffff";
|
||||
|
||||
property Color clr_page_text { des = "Box border color"; }
|
||||
set clr_page_text = "#000000";
|
||||
|
||||
property Color clr_box_text { des = "Box content color"; }
|
||||
set clr_boxhead_text = "#ffffff";
|
||||
|
||||
property Color clr_box_back { des = "Box background color"; }
|
||||
set clr_boxhead_back = "#000000";
|
||||
|
||||
property Color clr_boxhead_text { des = "Box heading text color"; }
|
||||
set clr_boxhead_text = "#ffffff";
|
||||
|
||||
property Color clr_boxhead_back { des = "Box heading background color"; }
|
||||
set clr_boxhead_back = "#000000";
|
||||
|
||||
property Color clr_page_link { des = "Link color"; }
|
||||
set clr_page_link = "#0000ff";
|
||||
|
||||
property Color clr_page_vlink { des = "Visited link color"; }
|
||||
set clr_page_vlink = "#0000ff";
|
||||
}
|
||||
|
||||
propgroup fonts {
|
||||
property use font_base;
|
||||
property use font_fallback;
|
||||
}
|
||||
|
||||
propgroup presentation {
|
||||
property string opt_navbar_pos {
|
||||
des = "Navigation Bar Location";
|
||||
values = "left|Left|right|Right";
|
||||
}
|
||||
set opt_navbar_pos = "left";
|
||||
|
||||
property bool opt_friends_colors {
|
||||
des = "Use friend colors on friends page";
|
||||
note = "If this option is on, the titles of friends' entries will use the colors you have selected for each friend.";
|
||||
}
|
||||
set opt_friends_colors = true;
|
||||
|
||||
property bool opt_always_userpic {
|
||||
des = "Always show userpics";
|
||||
note = "With this off, userpics are only shown in the friends view.";
|
||||
}
|
||||
set opt_always_userpic = false;
|
||||
|
||||
|
||||
|
||||
## These have no UI, but S2 generates an empty settings page if they aren't in a group
|
||||
property string text_page_prev {
|
||||
des = "Text used to link to the previous page";
|
||||
noui = 1;
|
||||
}
|
||||
property string text_page_next {
|
||||
des = "Text used to link to the next page";
|
||||
noui = 1;
|
||||
}
|
||||
set text_page_prev = "Previous Page";
|
||||
set text_page_next = "Next Page";
|
||||
|
||||
property string{} text_entry_links {
|
||||
des = "Captions for Entry Action links";
|
||||
noui = 1;
|
||||
}
|
||||
set text_entry_links = {"edit_entry" => "Edit Entry",
|
||||
"edit_tags" => "Edit Tags",
|
||||
"mem_add" => "Add As Memory",
|
||||
"tell_friend" => "Tell a Friend",
|
||||
"nav_prev" => "Previous Entry",
|
||||
"nav_next" => "Next Entry"};
|
||||
|
||||
property string{} text_comment_links {
|
||||
des = "Captions for Comment Action links";
|
||||
noui = 1;
|
||||
}
|
||||
set text_comment_links = {"delete_comment" => "Delete",
|
||||
"screen_comment" => "Screen",
|
||||
"unscreen_comment" => "Unscreen",
|
||||
"freeze_thread" => "Freeze",
|
||||
"unfreeze_thread" => "Unfreeze", };
|
||||
|
||||
property use use_shared_pic;
|
||||
property use linklist_support;
|
||||
property use external_stylesheet;
|
||||
}
|
||||
|
||||
set tags_aware = true;
|
||||
|
||||
function navheading(RecentNav nav, int entries) : string
|
||||
"i18n layers should override this to translate the skiplink box heading." {
|
||||
return ($nav.skip == 0 ? $entries+" most recent" : "skipped back "+$nav.skip);
|
||||
}
|
||||
function navlinktext(RecentNav nav, bool next) : string
|
||||
"i18n layers should override this to translate the skiplinks. If \$next is false, output 'Previous X', else 'Next X'." {
|
||||
return ($next ? "Next "+$nav.forward_count : "Previous "+$nav.backward_count);
|
||||
}
|
||||
|
||||
function print_stylesheet() {
|
||||
"""
|
||||
body {
|
||||
background: $*clr_page_back;
|
||||
color: $*clr_page_text;
|
||||
""";
|
||||
# Ugliness
|
||||
if ($*font_base != "" or $*font_fallback != "none") {
|
||||
"font-family: ";
|
||||
if ($*font_base != "") {
|
||||
"\"$*font_base\"";
|
||||
if ($*font_fallback != "none") {
|
||||
", ";
|
||||
}
|
||||
}
|
||||
if ($*font_fallback != "none") {
|
||||
print $*font_fallback;
|
||||
}
|
||||
";";
|
||||
}
|
||||
"""
|
||||
}
|
||||
a {
|
||||
color: $*clr_page_link;
|
||||
}
|
||||
a:visited {
|
||||
color: $*clr_page_vlink;
|
||||
}
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.box {
|
||||
border: 1px solid $*clr_page_text;
|
||||
margin: 1em;
|
||||
background: $*clr_box_back;
|
||||
color: $*clr_box_text;
|
||||
}
|
||||
|
||||
#navbar {
|
||||
width: 25%;
|
||||
}
|
||||
#body {
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
#navbar .box h1, .box h2, .box h3 {
|
||||
font-size: 1em;
|
||||
background: $*clr_boxhead_back;
|
||||
color: $*clr_boxhead_text;
|
||||
padding: 3px;
|
||||
margin: 0;
|
||||
}
|
||||
#navbar .box h1 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.box h1 a, .box h2 a, .box h3 a {
|
||||
color: $*clr_boxhead_text;
|
||||
background: $*clr_boxhead_back;
|
||||
}
|
||||
|
||||
#navbar .box div.userpic {
|
||||
margin: 1em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#navbar p {
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
#navbar ul, #skipbar ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0.5em;
|
||||
}
|
||||
#navbar ul li.active, #skipbar ul li.active {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.box .entry {
|
||||
margin: 1em;
|
||||
}
|
||||
|
||||
.box .talklinks {
|
||||
margin: 1em;
|
||||
text-align: right;
|
||||
clear: both;
|
||||
}
|
||||
.box .talklinks .permalink {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.box .minicomment {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
body.day #body h1 {
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
table.box, table.box td, table.box th {
|
||||
border: 1px solid #000000;
|
||||
}
|
||||
|
||||
.metadata {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
form#postform table {
|
||||
background: $*clr_box_back;
|
||||
color: $*clr_box_text;
|
||||
}
|
||||
""";
|
||||
}
|
||||
|
||||
function Page::lay_page_nav() {
|
||||
|
||||
}
|
||||
function RecentPage::lay_page_nav() {
|
||||
if ($.nav.backward_url == "" and $.nav.forward_url == "") {
|
||||
return;
|
||||
}
|
||||
println "<div class=\"box\">";
|
||||
println "<h2>"+navheading($.nav,size $.entries)+"</h2>\n<ul>";
|
||||
if ($.nav.backward_url != "") {
|
||||
println "<li><a href=\""+$.nav.backward_url+"\">"+
|
||||
navlinktext($.nav,false)+"</a></li>";
|
||||
}
|
||||
if ($.nav.forward_url != "") {
|
||||
println "<li><a href=\""+$.nav.forward_url+"\">"+
|
||||
navlinktext($.nav,true)+"</a></li>";
|
||||
}
|
||||
println "</ul>\n";
|
||||
println "</div>\n";
|
||||
}
|
||||
function DayPage::lay_page_nav() {
|
||||
println "<div class=\"box\"><ul>";
|
||||
println "<li><a href=\"$.prev_url\">"+$.prev_date->date_format("med")+"</a></li>";
|
||||
println "<li><a href=\"$.next_url\">"+$.next_date->date_format("med")+"</a></li>";
|
||||
println "</ul></div>";
|
||||
}
|
||||
function YearPage::lay_page_nav() {
|
||||
println "<div class=\"box\"><ul>";
|
||||
foreach var YearYear y ($.years) {
|
||||
if ($y.displayed) {
|
||||
println "<li class=\"active\">$y.year</li>";
|
||||
} else {
|
||||
println "<li><a href=\"$y.url\">$y.year</a></li>";
|
||||
}
|
||||
}
|
||||
println "</ul></div>";
|
||||
}
|
||||
function MonthPage::lay_page_nav() {
|
||||
println "<div class=\"box\"><ul>";
|
||||
if ($.prev_url != "") {
|
||||
"""<li><a href="$.prev_url">"""+$.prev_date->date_format($*lang_fmt_month_long)+"""</a></li>""";
|
||||
}
|
||||
if ($.next_url != "") {
|
||||
"""<li><a href="$.next_url">"""+$.next_date->date_format($*lang_fmt_month_long)+"""</a></li>""";
|
||||
}
|
||||
"</ul>";
|
||||
|
||||
"<form method='post' action='$.redir.url'><center>";
|
||||
$.redir->print_hiddens();
|
||||
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' />";
|
||||
}
|
||||
"</center></form>\n</div>\n";
|
||||
}
|
||||
|
||||
function EntryPage::lay_page_nav() {
|
||||
println "<div class=\"box\">";
|
||||
if (size $.comments > 0 and not $.comment_pages.all_subitems_displayed) {
|
||||
"<h2>"+lang_page_of_pages($.comment_pages.current, $.comment_pages.total)+"</h2>\n";
|
||||
}
|
||||
print "<ul>\n";
|
||||
if ($.entry.comments.enabled) {
|
||||
"<li>"; $.entry.comments->print_postlink(); "</li>\n";
|
||||
}
|
||||
if ($.comment_pages.url_prev != "") {
|
||||
"""<li><a href="$.comment_pages.url_prev">$*text_page_prev</a></li>\n""";
|
||||
}
|
||||
if ($.comment_pages.url_next != "") {
|
||||
"""<li><a href="$.comment_pages.url_next">$*text_page_next</a></li>\n""";
|
||||
}
|
||||
println "<li> </li>";
|
||||
var Link l = new Link;
|
||||
$l = $.entry->get_link("nav_next");
|
||||
println """<li><a href="$l.url">$*text_entry_links{"nav_next"}</a></li>""";
|
||||
foreach var string ls ($.entry.link_keyseq) {
|
||||
$l = $.entry->get_link($ls);
|
||||
if (defined $l) {
|
||||
println """<li><a href="$l.url">$*text_entry_links{$ls}</a></li>""";
|
||||
}
|
||||
}
|
||||
$l = $.entry->get_link("nav_prev");
|
||||
println """<li><a href="$l.url">$*text_entry_links{"nav_prev"}</a></li>""";
|
||||
println "</ul></div>";
|
||||
}
|
||||
|
||||
function Page::lay_show_firstnav() : bool {
|
||||
return false;
|
||||
}
|
||||
function RecentPage::lay_show_firstnav() : bool {
|
||||
return ((size $.entries) > 5);
|
||||
}
|
||||
function DayPage::lay_show_firstnav() : bool {
|
||||
return ((size $.entries) > 5);
|
||||
}
|
||||
function YearPage::lay_show_firstnav() : bool {
|
||||
return true;
|
||||
}
|
||||
function MonthPage::lay_show_firstnav() : bool {
|
||||
return true;
|
||||
}
|
||||
function EntryPage::lay_show_firstnav() : bool {
|
||||
return ((size $.comments) > 5);
|
||||
}
|
||||
function EntryPage::lay_show_firstnav() : bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
function Page::lay_navbar() {
|
||||
var string userpic;
|
||||
var Image up_img = $.journal.default_pic;
|
||||
if (defined $up_img) {
|
||||
$userpic = """<div class="userpic">
|
||||
<img src="$up_img.url"
|
||||
class="userpic" alt=""
|
||||
height="$up_img.height" width="$up_img.width" />
|
||||
</div>
|
||||
""";
|
||||
}
|
||||
var string website;
|
||||
if ($.journal.website_url != "") {
|
||||
$website = """<li><a href="$.journal.website_url">$.journal.website_name</a></li>\n""";
|
||||
}
|
||||
|
||||
"""
|
||||
<td id="navbar" width="25%">
|
||||
<div class="box">
|
||||
<h1>$.journal.name</h1>
|
||||
<ul>
|
||||
""";
|
||||
foreach var string v ($.views_order) {
|
||||
if ($.view == $v) {
|
||||
println "<li class=\"active\">"+lang_viewname($v)+"</li>";
|
||||
} else {
|
||||
println "<li><a href=\""+$.view_url{$v}+"\">"+lang_viewname($v)+"</a></li>";
|
||||
}
|
||||
}
|
||||
"""
|
||||
$website</ul>
|
||||
$userpic
|
||||
</div>
|
||||
""";
|
||||
|
||||
if ($this->lay_show_firstnav()) {
|
||||
$this->lay_page_nav();
|
||||
}
|
||||
|
||||
if (size $this.linklist > 0 and $*linklist_support) {
|
||||
println "<div class=\"box\">";
|
||||
println "<h2>Links</h2>\n";
|
||||
$this->print_linklist();
|
||||
println "</div>";
|
||||
}
|
||||
|
||||
"</td>";
|
||||
|
||||
}
|
||||
|
||||
function Page::print_linklist() {
|
||||
if (size $.linklist <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var bool section_open = false;
|
||||
|
||||
println "<ul>";
|
||||
foreach var UserLink l ($.linklist) {
|
||||
if ($l.title) {
|
||||
if ($l.is_heading) {
|
||||
if ($section_open) {
|
||||
println "</ul></li>";
|
||||
}
|
||||
println """<li><span style="font-weight: bold;">$l.title</span>\n<ul>""";
|
||||
$section_open = true;
|
||||
} else {
|
||||
println """<li><a href="$l.url">$l.title</a></li>""";
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($section_open) {
|
||||
println "</ul></li>";
|
||||
}
|
||||
println "</ul>";
|
||||
}
|
||||
|
||||
function Page::print() {
|
||||
var string title = $this->title();
|
||||
|
||||
"""<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>"+$this->title()+"</title>";
|
||||
"""
|
||||
</head>
|
||||
<body class="$.view">
|
||||
<table border="0" cellpadding="0" cellspacing="0" width="100%">
|
||||
<tr valign="top">
|
||||
""";
|
||||
|
||||
if ($*opt_navbar_pos == "left") {
|
||||
$this->lay_navbar();
|
||||
}
|
||||
|
||||
"<td rowspan=\"2\" id=\"body\">\n";
|
||||
$this->print_body();
|
||||
"</td>\n";
|
||||
|
||||
if ($*opt_navbar_pos == "right") {
|
||||
$this->lay_navbar();
|
||||
}
|
||||
|
||||
"</tr><tr><td valign=\"bottom\" id=\"skipbar\">";
|
||||
$this->lay_page_nav();
|
||||
"</td>";
|
||||
|
||||
"""
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
""";
|
||||
}
|
||||
|
||||
function print_entry(Page p, Entry e, Color bgcolor, Color fgcolor) {
|
||||
var string datetime;
|
||||
if ($p.view != "day") {
|
||||
$datetime = $e.time->date_format("med_day")+", "+$e.time->time_format();
|
||||
} else {
|
||||
$datetime = $e.time->time_format();
|
||||
}
|
||||
|
||||
if (not (defined $bgcolor) or not $*opt_friends_colors) {
|
||||
$bgcolor = $*clr_boxhead_back;
|
||||
}
|
||||
if (not (defined $fgcolor) or not $*opt_friends_colors) {
|
||||
$fgcolor = $*clr_boxhead_text;
|
||||
}
|
||||
|
||||
"""<div class="box"><h2 style="color: $fgcolor; background: $bgcolor;">$datetime """;
|
||||
|
||||
if ($e.security != "") {
|
||||
print """<img src="$e.security_icon.url" align="right" """+
|
||||
"""width="$e.security_icon.width" height="$e.security_icon.height" """+
|
||||
"""alt="[$e.security]" />""";
|
||||
}
|
||||
|
||||
if ($p.view == "friends" or
|
||||
$e.subject != "" or
|
||||
$e.poster.username != $p.journal.username) {
|
||||
|
||||
print "<br />";
|
||||
if ($p.view == "friends" or $e.poster.username != $p.journal.username) {
|
||||
$p->print_entry_poster($e);
|
||||
print ": ";
|
||||
}
|
||||
print $e.subject;
|
||||
}
|
||||
"</h2>\n<div class=\"entry\">\n";
|
||||
if (defined $e.userpic and (
|
||||
$*opt_always_userpic
|
||||
or ($e.poster.username != $p.journal.username and $e.userpic.url != $p.journal.default_pic.url)
|
||||
or $p.view == "friends"
|
||||
or $p.view == "entry")) {
|
||||
|
||||
"""<img src="$e.userpic.url" """;
|
||||
"""width="$e.userpic.width" height="$e.userpic.height" """;
|
||||
"""alt="" align="right" style="margin: 5px;" />\n""";
|
||||
}
|
||||
|
||||
"$e.text";
|
||||
|
||||
$e->print_metadata();
|
||||
|
||||
"""</div><div class="talklinks">""";
|
||||
"""<div class="permalink"><a href="$e.permalink_url">$*text_permalink</a></div> """;
|
||||
$e.comments->print();
|
||||
"</div>";
|
||||
|
||||
"</div>";
|
||||
|
||||
} # print_entry(Page,Entry,Color,Color)
|
||||
|
||||
function Entry::print_metadata() {
|
||||
var string caption;
|
||||
var string val;
|
||||
var Image i;
|
||||
if (size $.metadata == 0 and size $.tags == 0) { return; }
|
||||
println """<div class="metadata">""";
|
||||
if ($this.tags) {
|
||||
var int tcount = 0;
|
||||
"<div class='ljtags'><strong>Tags:</strong> ";
|
||||
foreach var Tag t ($this.tags) {
|
||||
"""<a rel="tag" href="$t.url">$t.name</a>""";
|
||||
$tcount++;
|
||||
if ($tcount != size $this.tags) { ", "; }
|
||||
}
|
||||
"</div>";
|
||||
}
|
||||
if (size $.metadata != 0) {
|
||||
foreach var string k ($.metadata) {
|
||||
$caption = $k;
|
||||
$val = $.metadata{$k};
|
||||
if ($k == "music") {
|
||||
$caption = $*text_meta_music;
|
||||
}
|
||||
elseif ($k == "mood") {
|
||||
$caption = $*text_meta_mood;
|
||||
if (defined $.mood_icon) {
|
||||
$i = $.mood_icon;
|
||||
$val = """<img src="$i.url" width="$i.width" height="$i.height" align="absmiddle"> $val""";
|
||||
}
|
||||
}
|
||||
println """<div class="metadata-$k"><span style="font-weight: bold;">$caption:</span> $val</div>""";
|
||||
}
|
||||
}
|
||||
println "</div>";
|
||||
}
|
||||
|
||||
function Page::print_entry(Entry e) {
|
||||
print_entry($this, $e, null Color, null Color);
|
||||
}
|
||||
|
||||
function FriendsPage::print_entry(Entry e) {
|
||||
var Friend f = $.friends{$e.journal.username};
|
||||
print_entry($this, $e, $f.bgcolor, $f.fgcolor);
|
||||
}
|
||||
function colored_ljuser(UserLite u, Color fg, Color bg) : string {
|
||||
var Image uiimg = userinfoicon($u);
|
||||
var string dir = $u.journal_type == "C" ? "community" : "users";
|
||||
return """<span class="ljuser" style="white-space:nowrap;"><a href="$*SITEROOT/userinfo.bml?user=$u.username" style="color: $fg; background: $bg;"><img src="$uiimg.url" alt="[i]" width="$uiimg.width" height="$uiimg.height" style="vertical-align:bottom;border:0;" /></a><a href="$*SITEROOT/$dir/$u.username/" style="color: $fg; background: $bg; font-weight: bold;">$u.username</a></span>""";
|
||||
}
|
||||
function FriendsPage::print_entry_poster(Entry e) {
|
||||
var Friend f = $.friends{$e.journal.username};
|
||||
var Color fg; var Color bg;
|
||||
if ($*opt_friends_colors) {
|
||||
$fg = $f.fgcolor;
|
||||
$bg = $f.bgcolor;
|
||||
} else {
|
||||
$fg = $*clr_boxhead_text;
|
||||
$bg = $*clr_boxhead_back;
|
||||
}
|
||||
print colored_ljuser($e.poster, $fg, $bg);
|
||||
if ($e.poster.username != $e.journal.username) {
|
||||
" posting in ";
|
||||
print colored_ljuser($e.journal, $fg, $bg);
|
||||
}
|
||||
}
|
||||
|
||||
function RecentPage::print_body() {
|
||||
foreach var Entry e ($.entries) {
|
||||
$this->print_entry($e);
|
||||
}
|
||||
}
|
||||
|
||||
function CommentInfo::print() {
|
||||
if ($.enabled) {
|
||||
$this->print_postlink();
|
||||
if ($.count > 0 or $.screened) {
|
||||
" | ";
|
||||
$this->print_readlink();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function DayPage::print_body() {
|
||||
println """<h1 style="font-size: 1.5em; text-align: center;">"""+$.date->date_format("long")+"</h1>";
|
||||
|
||||
if (not $.has_entries) {
|
||||
print "<p>$*text_noentries_day</p>";
|
||||
return;
|
||||
}
|
||||
|
||||
foreach var Entry e ($.entries) {
|
||||
$this->print_entry($e);
|
||||
}
|
||||
}
|
||||
|
||||
function EntryPage::print_body() {
|
||||
$this->print_entry($.entry);
|
||||
if ($this.multiform_on) {
|
||||
$this->print_multiform_start();
|
||||
}
|
||||
if ($.entry.comments.enabled) {
|
||||
$this->print_comments($.comments);
|
||||
}
|
||||
if ($this.multiform_on) {
|
||||
"<div class='box'><h2>Mass Action on Selected Comments:</h2>";
|
||||
"<p class='entry'>"; $this->print_multiform_actionline(); "</p>";
|
||||
"</div>";
|
||||
$this->print_multiform_end();
|
||||
}
|
||||
}
|
||||
|
||||
function EntryPage::print_comments(Comment[] cs) {
|
||||
if (size $cs == 0) { return; }
|
||||
print "<div style=\"margin-left: 25px;\">";
|
||||
foreach var Comment c ($cs) {
|
||||
var int indent = ($c.depth - 1) * 25;
|
||||
if ($c.full) {
|
||||
$this->print_comment($c);
|
||||
} else {
|
||||
$this->print_comment_partial($c);
|
||||
}
|
||||
}
|
||||
print "</div>";
|
||||
}
|
||||
|
||||
function EntryPage::print_comment(Comment c) {
|
||||
var string datetime;
|
||||
$datetime = $c.time->date_format("med_day")+", "+$c.time->time_format();
|
||||
|
||||
"""<a name='$c.anchor'></a><div id="$c.dom_id" class="box"><h3 style="color: $*clr_boxhead_text; background: $*clr_boxhead_back;">""";
|
||||
|
||||
if ($c.metadata{"poster_ip"}) { print """<div style="float: right; vertical-align: top; font-size: 0.75em;">(""" +
|
||||
$c.metadata{"poster_ip"} +
|
||||
""")</div>"""; }
|
||||
|
||||
print $datetime;
|
||||
|
||||
if (defined $c.subject_icon) {
|
||||
print """<img src="$c.subject_icon.url" align="right" """+
|
||||
"""width="$c.subject_icon.width" height="$c.subject_icon.height" """+
|
||||
"""alt="" />""";
|
||||
}
|
||||
|
||||
var string poster = defined $c.poster ? $c.poster->as_string() : "<i>(Anonymous)</i>";
|
||||
print "<br />"+$poster;
|
||||
|
||||
if ($c.subject != "") {
|
||||
print ": "+$c.subject;
|
||||
}
|
||||
|
||||
"</h3>\n<div class=\"entry\">\n";
|
||||
if (defined $c.userpic and $*comment_userpic_style != "off") {
|
||||
"""<img src="$c.userpic.url" """;
|
||||
"""width="$c.userpic.width" height="$c.userpic.height" """;
|
||||
"""alt="" align="right" style="margin: 5px;" />\n""";
|
||||
}
|
||||
|
||||
"$c.text</div>";
|
||||
"""<div class="talklinks">""";
|
||||
"""<div class="permalink"><a href="$c.permalink_url">$*text_permalink</a></div>""";
|
||||
|
||||
if ($c.parent_url != "") { """<a href="$c.parent_url">$*text_comment_parent</a> - """; }
|
||||
if ($c.thread_url != "") { """<a href="$c.thread_url">$*text_comment_thread</a> - """; }
|
||||
var Link l = new Link;
|
||||
foreach var string ls ($c.link_keyseq) {
|
||||
$l = $c->get_link($ls);
|
||||
if (defined $l) {
|
||||
println """<a href="$l.url">$*text_comment_links{$ls}</a> - """;
|
||||
}
|
||||
}
|
||||
if (not $c.frozen) {
|
||||
"""<a href="$c.reply_url">$*text_comment_reply</a>""";
|
||||
} else {
|
||||
"""$*text_comment_frozen""";
|
||||
}
|
||||
# FIXME: better location?
|
||||
if ($.multiform_on) {
|
||||
"""<br /><label for="ljcomsel_$c.talkid">$*text_multiform_check</label> """; $c->print_multiform_check();
|
||||
}
|
||||
"</div>";
|
||||
|
||||
if ((size $c.replies) > 0 and $c.replies[0].full == false) {
|
||||
"""<div style="margin-top: 5px; margin-bottom: 5px; clear: both;">\n""";
|
||||
$this->print_comments($c.replies);
|
||||
"</div>\n";
|
||||
}
|
||||
|
||||
"</div>";
|
||||
|
||||
if ((size $c.replies) > 0 and $c.replies[0].full == true) {
|
||||
$this->print_comments($c.replies);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function EntryPage::print_comment_partial(Comment c) {
|
||||
var string poster = defined $c.poster ? $c.poster->as_string() : "<i>(Anonymous)</i>";
|
||||
var string subj = $c.subject != "" ? $c.subject : $*text_nosubject;
|
||||
print """<div class="minicomment"><a href="$c.permalink_url">$subj</a> - $poster</div>""";
|
||||
$this->print_comments($c.replies);
|
||||
}
|
||||
|
||||
|
||||
function ReplyPage::print_body() {
|
||||
|
||||
var EntryLite c = $.replyto;
|
||||
var string datetime;
|
||||
$datetime = $c.time->date_format("med_day")+", "+$c.time->time_format();
|
||||
|
||||
"""<div class="box"><h2 style="color: $*clr_boxhead_text; background: $*clr_boxhead_back;">$datetime """;
|
||||
|
||||
var string poster = defined $c.poster ? $c.poster->as_string() : "<i>(Anonymous)</i>";
|
||||
print "<br />"+$poster;
|
||||
|
||||
if ($c.subject != "") {
|
||||
print ": "+$c.subject;
|
||||
}
|
||||
|
||||
"</h2>\n<div class=\"entry\">\n";
|
||||
if (defined $c.userpic and $*comment_userpic_style != "off") {
|
||||
"""<img src="$c.userpic.url" """;
|
||||
"""width="$c.userpic.width" height="$c.userpic.height" """;
|
||||
"""alt="" align="right" style="margin: 5px;" />\n""";
|
||||
}
|
||||
|
||||
"$c.text</div>";
|
||||
|
||||
if (defined $c.userpic and $*comment_userpic_style != "off") {
|
||||
"""<br clear="all" />""";
|
||||
}
|
||||
|
||||
"</div>";
|
||||
|
||||
"""<div class="box" style="margin-left: 25px;">\n""";
|
||||
$.form->print();
|
||||
"</div>\n";
|
||||
|
||||
}
|
||||
|
||||
function YearPage::print_body {
|
||||
foreach var YearMonth m ($.months) {
|
||||
$this->print_month($m);
|
||||
}
|
||||
}
|
||||
|
||||
function YearPage::print_month(YearMonth m) {
|
||||
if (not $m.has_entries) { return; }
|
||||
"""<table class="box" style="border-collapse: collapse; border: 1px solid; width: 80%; margin-left: 10%; margin-right: 10%;" border="1">\n
|
||||
<tr><th colspan="7" style="background: $*clr_boxhead_back; color: $*clr_boxhead_text; text-align: center;">""";
|
||||
print $m->month_format();
|
||||
"""</th></tr>\n""";
|
||||
foreach var int d (weekdays()) {
|
||||
"<th style=\"width: 14%;\">"+$*lang_dayname_short[$d]+"</th>\n";
|
||||
}
|
||||
"</tr>\n";
|
||||
foreach var YearWeek w ($m.weeks) {
|
||||
$w->print();
|
||||
}
|
||||
"""<tr><td colspan="7" style="text-align: center;">
|
||||
<a href="$m.url">$*text_view_month</a></td></tr>\n""";
|
||||
"</table>";
|
||||
}
|
||||
|
||||
function YearWeek::print() {
|
||||
"""<tr valign="top" style="height: 2.75em;">\n""";
|
||||
if ($.pre_empty > 0) {
|
||||
"""<td class="emptyday" colspan="$.pre_empty"> </td>\n""";
|
||||
}
|
||||
foreach var YearDay d ($.days) {
|
||||
"""<td>\n""";
|
||||
"""<div style="text-align: right;">$d.day</div>\n""";
|
||||
if ($d.num_entries > 0) {
|
||||
"""<div style="text-align: center;"><a href="$d.url">$d.num_entries</a></div>\n""";
|
||||
}
|
||||
"""</td>\n""";
|
||||
}
|
||||
if ($.post_empty > 0) {
|
||||
"""<td colspan="$.post_empty"> </td>\n""";
|
||||
}
|
||||
"</tr>";
|
||||
}
|
||||
|
||||
function MonthPage::print_body {
|
||||
"""<div class="box"><h2>"""+$.date->date_format($*lang_fmt_month_long)+"</h2>\n";
|
||||
"<dl style=\"margin: 1em;\">";
|
||||
foreach var MonthDay d ($.days) {
|
||||
if ($d.has_entries) {
|
||||
"<dt><a href=\"$d.url\"><b>";
|
||||
print lang_ordinal($d.day);
|
||||
"</b></a></dt>\n<dd>";
|
||||
$d->print_subjectlist();
|
||||
"</dd>\n";
|
||||
}
|
||||
}
|
||||
"</dl>\n</div>\n";
|
||||
}
|
||||
|
||||
|
||||
### Handler for the theme previews
|
||||
|
||||
function print_theme_preview() {
|
||||
"""
|
||||
<div style="padding: 1em; background: $*clr_page_back; color: $*clr_page_text;">
|
||||
<div style="border: 1px solid $*clr_page_text; margin: 1em; background: $*clr_box_back; color: $*clr_box_text;">
|
||||
<h2 style="color: $*clr_boxhead_text; background: $*clr_boxhead_back; font-size: 1em; padding: 4px; margin: 0;">Cir zuta besho cavu mabu</h2>
|
||||
<div style="margin: 1em;">
|
||||
Cir zuta besho cavu mabu. Jad dop fugu hige wiju. Jam nek sapu shek noshea, moz lolle jil hattou daz.
|
||||
Heck mippe giffou tipe pello, govo goof wachou fenu betui, mumu niffo puffu hivoo ziv! Sap gap jozo vem
|
||||
sushu jiwo peru diche gese zar. Zuk kah rec sok vapui, mumu. Puw wuti mufe bak jivo, zef kazou gipwew cus.
|
||||
Cev lepp gik fego rer. Tucku mickou jeck helou soopp! Vowa vov fawea pip wok. Heg fum heafsum pele.
|
||||
Piz kuzu louw rome puir. Pashi jog huku pobi ckush. Zuj bit wido guih biha. Som veh nelo ruh ruju.
|
||||
Coosh jecko nuh tutt tab. Zutt ckek vano fic der, hivu?
|
||||
</div>
|
||||
<div style="margin: 1em; text-align: right; clear: both;">
|
||||
<div style="float: left;"><span style="color: #0000ff; text-decoration: underline; cursor: hand;">$*text_permalink</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
""";
|
||||
|
||||
|
||||
}
|
||||
BIN
livejournal/bin/upgrading/s2layers/sturdygesture/sturdygesture.jpg
Executable file
|
After Width: | Height: | Size: 19 KiB |
75
livejournal/bin/upgrading/s2layers/sturdygesture/themes.s2
Executable file
@@ -0,0 +1,75 @@
|
||||
#NEWLAYER: sturdygesture/beansprout
|
||||
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Beansprout";
|
||||
layerinfo "redist_uniq" = "sturdygesture/beansprout";
|
||||
|
||||
set clr_page_link = "#006760";
|
||||
set clr_boxhead_text = "#ffffff";
|
||||
set clr_box_text = "#000000";
|
||||
set clr_page_text = "#ffffff";
|
||||
set clr_box_back = "#ffffff";
|
||||
set clr_boxhead_back = "#006760";
|
||||
set clr_page_back = "#000000";
|
||||
set clr_page_vlink = "#002C29";
|
||||
|
||||
#NEWLAYER: sturdygesture/boxless
|
||||
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Boxless";
|
||||
layerinfo "redist_uniq" = "sturdygesture/boxless";
|
||||
|
||||
set clr_page_link = "#0000ff";
|
||||
set clr_boxhead_text = "#ffffff";
|
||||
set clr_box_text = "#000000";
|
||||
set clr_page_text = "#ffffff";
|
||||
set clr_box_back = "#ffffff";
|
||||
set clr_boxhead_back = "#000000";
|
||||
set clr_page_back = "#ffffff";
|
||||
set clr_page_vlink = "#00007f";
|
||||
|
||||
#NEWLAYER: sturdygesture/martialblue
|
||||
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Martial Blue";
|
||||
layerinfo "redist_uniq" = "sturdygesture/martialblue";
|
||||
|
||||
set clr_page_link = "#0068CF";
|
||||
set clr_boxhead_text = "#000000";
|
||||
set clr_box_text = "#000000";
|
||||
set clr_page_text = "#000000";
|
||||
set clr_box_back = "#FFFFFF";
|
||||
set clr_boxhead_back = "#6FB7FF";
|
||||
set clr_page_back = "#BFD8FF";
|
||||
set clr_page_vlink = "#003070";
|
||||
|
||||
#NEWLAYER: sturdygesture/redmond
|
||||
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Redmond";
|
||||
layerinfo "redist_uniq" = "sturdygesture/redmond";
|
||||
|
||||
set clr_page_link = "#0000ff";
|
||||
set clr_boxhead_text = "#ffffff";
|
||||
set clr_box_text = "#000000";
|
||||
set clr_page_text = "#000000";
|
||||
set clr_box_back = "#ffffff";
|
||||
set clr_boxhead_back = "#00007F";
|
||||
set clr_page_back = "#007F7F";
|
||||
set clr_page_vlink = "#0000ff";
|
||||
|
||||
#NEWLAYER: sturdygesture/shadesofgray
|
||||
|
||||
layerinfo "type" = "theme";
|
||||
layerinfo "name" = "Shades of Gray"; # or, indeed, "grey" :)
|
||||
layerinfo "redist_uniq" = "sturdygesture/shadesofgray";
|
||||
|
||||
set clr_page_link = "#444444";
|
||||
set clr_boxhead_text = "#ffffff";
|
||||
set clr_box_text = "#000000";
|
||||
set clr_page_text = "#7f7f7f";
|
||||
set clr_box_back = "#cccccc";
|
||||
set clr_boxhead_back = "#7f7f7f";
|
||||
set clr_page_back = "#888888";
|
||||
set clr_page_vlink = "#222222";
|
||||
|
||||
14
livejournal/bin/upgrading/s2layers/tabularindent/en.s2
Executable file
@@ -0,0 +1,14 @@
|
||||
# -*-s2-*-
|
||||
|
||||
layerinfo type = "i18n";
|
||||
layerinfo name = "English";
|
||||
layerinfo redist_uniq = "tabularindent/en";
|
||||
|
||||
set text_meta_music = "Music";
|
||||
set text_meta_mood = "Mood";
|
||||
|
||||
set text_post_comment = "Add Your Own";
|
||||
set text_read_comments = "Read # Comments";
|
||||
|
||||
set text_post_comment_friends = "Add Your Own";
|
||||
set text_read_comments_friends = "Read # Comments";
|
||||
741
livejournal/bin/upgrading/s2layers/tabularindent/layout.s2
Executable file
@@ -0,0 +1,741 @@
|
||||
# -*-s2-*-
|
||||
|
||||
layerinfo type = "layout";
|
||||
layerinfo name = "Tabular Indent";
|
||||
layerinfo redist_uniq = "tabularindent/layout";
|
||||
layerinfo previews = "tabularindent/tabularindent.jpg";
|
||||
|
||||
propgroup colors {
|
||||
property Color body_bgcolor {
|
||||
des = "Body background color";
|
||||
s1color = "page_back";
|
||||
}
|
||||
property Color main_bgcolor {
|
||||
des = "Background of main text areas";
|
||||
s1color = "page_back";
|
||||
}
|
||||
property Color main_fgcolor {
|
||||
des = "Main text color";
|
||||
s1color = "page_text";
|
||||
}
|
||||
property Color border_color {
|
||||
des = "Color of borders";
|
||||
# No s1color equivalent
|
||||
}
|
||||
property Color headerbar_bgcolor {
|
||||
des = "Background color of header bar(s)";
|
||||
s1color = "stronger_back";
|
||||
}
|
||||
property Color headerbar_fgcolor {
|
||||
des = "Header bar text color";
|
||||
s1color = "stronger_text";
|
||||
}
|
||||
property Color captionbar_mainbox_bgcolor {
|
||||
des = "Main background color of caption bar";
|
||||
s1color = "page_back";
|
||||
}
|
||||
property Color captionbar_mainbox_fgcolor {
|
||||
des = "Text color of caption bar";
|
||||
s1color = "page_text";
|
||||
}
|
||||
property Color captionbar_userpicbox_color {
|
||||
des = "User picture background color of caption bar";
|
||||
s1color = "strong_back";
|
||||
}
|
||||
property Color accent_bgcolor {
|
||||
des = "Background color of accented areas";
|
||||
s1color = "weak_back";
|
||||
}
|
||||
property Color accent_fgcolor {
|
||||
des = "Accented area text color";
|
||||
s1color = "weak_text";
|
||||
}
|
||||
property Color link_color {
|
||||
des = "Link color";
|
||||
s1color = "page_link";
|
||||
}
|
||||
property Color vlink_color {
|
||||
des = "Visited link color";
|
||||
s1color = "page_vlink";
|
||||
}
|
||||
property Color alink_color {
|
||||
des = "Active link color";
|
||||
s1color = "page_alink";
|
||||
}
|
||||
property Color comment_bar_one_bgcolor {
|
||||
des = "Alternating background color for comment bars (one)";
|
||||
}
|
||||
property Color comment_bar_two_fgcolor {
|
||||
des = "Text color on alternating comment bars (one)";
|
||||
}
|
||||
property Color comment_bar_two_bgcolor {
|
||||
des = "Alternating background color for comment bars (two)";
|
||||
}
|
||||
property Color comment_bar_one_fgcolor {
|
||||
des = "Text color on alternating comment bars (two)";
|
||||
}
|
||||
property Color comment_bar_screened_bgcolor {
|
||||
des = "Background bar color for screened comments";
|
||||
}
|
||||
property Color comment_bar_screened_fgcolor {
|
||||
des = "Text color on background bar for screened comments";
|
||||
}
|
||||
}
|
||||
set body_bgcolor = "#ffffff";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#000000";
|
||||
set headerbar_bgcolor = "#6666cc";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set captionbar_mainbox_bgcolor = "#ffffff";
|
||||
set captionbar_mainbox_fgcolor = "#000000";
|
||||
set captionbar_userpicbox_color = "#c0c0ff";
|
||||
set accent_bgcolor = "#eeeeff";
|
||||
set accent_fgcolor = "#000000";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#c0c0ff";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#eeeeff";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
set comment_bar_screened_bgcolor = "#dddddd";
|
||||
set comment_bar_screened_fgcolor = "#000000";
|
||||
|
||||
propgroup presentation {
|
||||
property bool show_entry_userpic {
|
||||
des = "Show the userpic on the journal entries?";
|
||||
}
|
||||
property use page_recent_items;
|
||||
property use page_friends_items;
|
||||
property use use_shared_pic;
|
||||
property use view_entry_disabled;
|
||||
property string page_background_image {
|
||||
des = "URL to an image to be used for the page background";
|
||||
}
|
||||
property use external_stylesheet;
|
||||
}
|
||||
set show_entry_userpic = true;
|
||||
set page_recent_items = 20;
|
||||
set page_friends_items = 20;
|
||||
set view_entry_disabled = false;
|
||||
set page_background_image = "";
|
||||
|
||||
propgroup text {
|
||||
property use text_post_comment;
|
||||
property use text_read_comments;
|
||||
property use text_post_comment_friends;
|
||||
property use text_read_comments_friends;
|
||||
}
|
||||
|
||||
set tags_aware = true;
|
||||
|
||||
function Page::lay_captionbar_navigation () { }
|
||||
|
||||
function captionbar (Page p) {
|
||||
var string title = $p->title();
|
||||
|
||||
var string userpic;
|
||||
var Image up_img = $p.journal.default_pic;
|
||||
if (defined $up_img) {
|
||||
$userpic = """<img src="$up_img.url" height="$up_img.height" width="$up_img.width" alt="[icon]" />""";
|
||||
}
|
||||
|
||||
var string website_name = $p.journal.website_name ? $p.journal.website_name : $*text_website_default_name;
|
||||
var string website;
|
||||
if ($p.journal.website_url != "") {
|
||||
$website = """<tr><td>View:</td><td><a href="$p.journal.website_url">Website ($website_name)</a>.</td></tr>""";
|
||||
}
|
||||
|
||||
var string links;
|
||||
foreach var string v ($p.views_order) {
|
||||
$links = "$links<tr><td>View:</td><td>" + ($p.view == $v ?
|
||||
lang_viewname($v) :
|
||||
"<a href='$p.view_url{$v}'>"+lang_viewname($v)+"</a>") + ".</td></tr>\n";
|
||||
}
|
||||
|
||||
var string captionbar_userpicbox_style = "background-color: $*captionbar_userpicbox_color";
|
||||
"""
|
||||
<table height='100' class='captionbar' cellpadding='5' cellspacing='1'><tr>
|
||||
<td class="captionbar-userpicbox" align='center' valign='center' width='100' style='$captionbar_userpicbox_style'>$userpic</td>
|
||||
<td><b>$title</b><br />
|
||||
<table border='0'>
|
||||
$links
|
||||
$website
|
||||
<tr>
|
||||
<td colspan='2'>""";
|
||||
|
||||
$p->lay_captionbar_navigation();
|
||||
"
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr></table>";
|
||||
}
|
||||
|
||||
function print_stylesheet ()
|
||||
{
|
||||
var string backgroundurl = clean_url($*page_background_image) != "" ? "background-image: url($*page_background_image);" : "";
|
||||
"""/* Tabular Indent Stylesheet */
|
||||
body {
|
||||
$backgroundurl
|
||||
background-color: $*body_bgcolor;
|
||||
}
|
||||
.captionbar {
|
||||
width: 100%;
|
||||
border: 1px solid $*border_color;
|
||||
}
|
||||
.captionbar, .captionbar td {
|
||||
background-color: $*captionbar_mainbox_bgcolor;
|
||||
color: $*captionbar_mainbox_fgcolor;
|
||||
}
|
||||
.captionbar-userpicbox {
|
||||
border-right: 1px solid $*border_color;
|
||||
background-color: $*captionbar_userpicbox_color;
|
||||
color: $*captionbar_mainbox_fgcolor;
|
||||
}
|
||||
body,td,p {
|
||||
font-family: verdana, arial, helvetica, sans-serif;
|
||||
font-size: 8pt;
|
||||
}
|
||||
a {
|
||||
color: $*link_color;
|
||||
font-family: verdana, arial, helvetica, sans-serif;
|
||||
font-size: 8pt;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:visited {
|
||||
color: $*vlink_color;
|
||||
font-family: verdana, arial, helvetica, sans-serif;
|
||||
font-size: 8pt;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:active {
|
||||
color: $*alink_color;
|
||||
font-family: verdana, arial, helvetica, sans-serif;
|
||||
font-size: 8pt;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover {
|
||||
color: $*alink_color;
|
||||
font-family: verdana, arial, helvetica, sans-serif;
|
||||
font-size: 8pt;
|
||||
text-decoration: underline;
|
||||
}
|
||||
h3.page-header {
|
||||
font-size: 8pt;
|
||||
font-family: verdana, arial, helvetica, sans-serif;
|
||||
font-weight: normal;
|
||||
background-color: $*headerbar_bgcolor;
|
||||
color: $*headerbar_fgcolor;
|
||||
padding: 6px;
|
||||
border: 1px solid $*border_color;
|
||||
}
|
||||
""";
|
||||
}
|
||||
|
||||
function Page::print ()
|
||||
{
|
||||
var string title = $this->title();
|
||||
println "<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>
|
||||
""";
|
||||
"<p>"; captionbar($this); "</p>";
|
||||
|
||||
"<p>"; $this->print_body(); "</p>";
|
||||
|
||||
"<p>"; captionbar($this); "</p>";
|
||||
|
||||
"""
|
||||
</body>
|
||||
</html>
|
||||
""";
|
||||
}
|
||||
|
||||
function print_box (string{} colors, string metapic, string{} meta, string content, string footer, string domid) {
|
||||
var string bgcolor = $colors{"bgcolor"};
|
||||
var string fgcolor = $colors{"fgcolor"};
|
||||
if ($domid != "") { $domid = "id='$domid'"; }
|
||||
|
||||
var string style = "background-color: $bgcolor; color: $fgcolor";
|
||||
"<div align='right'><table $domid border='0' width='95%' cellpadding='5' cellspacing='1' style='$style'>";
|
||||
"<tr><td><table border='0' width='100%'><tr>";
|
||||
|
||||
if ($metapic) {
|
||||
"<td width='100' valign='top' align='center'>$metapic</td>";
|
||||
}
|
||||
|
||||
"<td valign='top'><table border='0'>";
|
||||
|
||||
foreach var string k ($meta) {
|
||||
var string key = $k;
|
||||
var string val = $meta{$k};
|
||||
"<tr><td align='right'>$key</td><td>$val</td></tr>";
|
||||
}
|
||||
|
||||
"</table></td></tr></table></td></tr>";
|
||||
"<tr><td style='background-color: $*main_bgcolor; color: $*main_fgcolor'>";
|
||||
|
||||
print $content;
|
||||
|
||||
"</td></tr>";
|
||||
|
||||
if ($footer) {
|
||||
"<tr><td style='white-space: nowrap'>$footer</td></tr>";
|
||||
}
|
||||
|
||||
"</table></div><br />";
|
||||
}
|
||||
|
||||
function print_header (string header)
|
||||
{
|
||||
print "<h3 class='page-header'>$header</h3>";
|
||||
}
|
||||
|
||||
function print_genericbox_open () {
|
||||
"<div align='right'><table border='0' width='95%' cellpadding='5' cellspacing='1' bgcolor='$*accent_bgcolor'>";
|
||||
"<tr><td style='background-color: $*main_bgcolor; color: $*main_fgcolor'>";
|
||||
}
|
||||
|
||||
function print_genericbox_close ()
|
||||
{
|
||||
"</font></td></tr></table></div><br />";
|
||||
}
|
||||
|
||||
function print_entry (Page p, Entry e, Color bgcolor, Color fgcolor, bool hide_text)
|
||||
{
|
||||
var string{} colors; var string{} meta; var string content = ""; var string footer = "";
|
||||
$colors{"bgcolor"} = "$*accent_bgcolor";
|
||||
$colors{"fgcolor"} = "$*accent_fgcolor";
|
||||
if ($p.view == "recent") {
|
||||
if ($e.new_day) {
|
||||
print_header($e.time->date_format("%%month%% %%dayord%%, %%yyyy%%"));
|
||||
}
|
||||
} else {
|
||||
print_header($e.time->date_format("%%month%% %%dayord%%, %%yyyy%%"));
|
||||
}
|
||||
# Userpic
|
||||
var string metapic = "";
|
||||
if ($p.view == "friends" or
|
||||
$*show_entry_userpic == true or
|
||||
$e.journal.username != $e.poster.username)
|
||||
{
|
||||
var string userpic = defined $e.userpic ? "<img src='$e.userpic.url' style='border: 0' />" : "";
|
||||
var string url = $e.journal->base_url() + "/";
|
||||
$metapic = "<div style='background-color: $bgcolor'>";
|
||||
$metapic = "$metapic <a href='$url'>$userpic</a>";
|
||||
if ($e.journal.username != $e.poster.username) {
|
||||
var string purl = $e.poster->base_url() + "/";
|
||||
$metapic = "$metapic<br /><font color='$fgcolor'>[<a href='$purl'>$e.poster.username</a>]</font>";
|
||||
}
|
||||
if ($p.view == "friends") { $metapic = "$metapic<br /><font color='$fgcolor'><a href='$url'>$e.journal.username</a></font>"; }
|
||||
$metapic = "$metapic</div>";
|
||||
}
|
||||
# Security Icon
|
||||
if ($e.security) {
|
||||
$meta{"Security:"} = "$e.security_icon $e.security";
|
||||
}
|
||||
# Subject
|
||||
if ($e.subject) {
|
||||
$meta{"Subject:"} = $e.subject;
|
||||
}
|
||||
# Time posted
|
||||
var string time = $e.time->time_format();
|
||||
$meta{"Time:"} = $time;
|
||||
# Current
|
||||
if (size $e.metadata) {
|
||||
foreach var string k ($e.metadata) {
|
||||
var string key = $k; var string val = $e.metadata{$k};
|
||||
if ($k == "mood") {
|
||||
$key = $*text_meta_mood;
|
||||
} elseif ($k == "music") {
|
||||
$key = $*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='absmiddle' alt='[mood icon]' /> $val";
|
||||
}
|
||||
$meta{"$key:"} = $val;
|
||||
}
|
||||
}
|
||||
# Tags
|
||||
if ($e.tags) {
|
||||
var int tcount = 0;
|
||||
var string tag;
|
||||
foreach var Tag t ($e.tags) {
|
||||
$tag = $tag + """<a rel="tag" href="$t.url">$t.name</a>""";
|
||||
$tcount++;
|
||||
if ($tcount != size $e.tags) { $tag = $tag + ", "; }
|
||||
}
|
||||
$meta{"Tags:"} = $tag;
|
||||
}
|
||||
|
||||
|
||||
if (not $hide_text) { $content = $e.text; }
|
||||
|
||||
if ($e.comments.enabled) {
|
||||
$footer = "comments:";
|
||||
if (($e.comments.count > 0 or $e.comments.screened) and ($p.view != "entry")) {
|
||||
$footer = "$footer <a href=\"$e.comments.read_url\">"
|
||||
+ get_plural_phrase($e.comments.count, $p.view == "friends" ?
|
||||
"text_read_comments_friends" : "text_read_comments")
|
||||
+ "</a> or";
|
||||
}
|
||||
$footer = "$footer <a href=\"$e.comments.post_url\">"
|
||||
+ ($p.view == "friends" ? $*text_post_comment_friends : $*text_post_comment)
|
||||
+ "</a>";
|
||||
}
|
||||
|
||||
# Misc Links
|
||||
var Link link;
|
||||
if ($p.view == "entry")
|
||||
{
|
||||
$link = $e->get_link("nav_prev"); $footer = "$footer $link";
|
||||
}
|
||||
$link = $e->get_link("edit_entry"); $footer = "$footer $link";
|
||||
$link = $e->get_link("edit_tags"); $footer = "$footer $link";
|
||||
$link = $e->get_link("tell_friend"); $footer = "$footer $link";
|
||||
$link = $e->get_link("mem_add"); $footer = "$footer $link";
|
||||
if ($p.view == "entry")
|
||||
{
|
||||
$link = $e->get_link("nav_next"); $footer = "$footer $link";
|
||||
}
|
||||
|
||||
# Print
|
||||
print_box($colors, $metapic, $meta, $content, $footer, "");
|
||||
}
|
||||
|
||||
function Page::print_entry (Entry e)
|
||||
{
|
||||
print_entry($this, $e, null Color, null Color, false);
|
||||
}
|
||||
|
||||
function FriendsPage::print_entry (Entry e) {
|
||||
var Friend f = $.friends{$e.journal.username};
|
||||
print_entry($this, $e, $f.bgcolor, $f.fgcolor, false);
|
||||
}
|
||||
|
||||
function RecentPage::lay_captionbar_navigation()
|
||||
{
|
||||
var int total = size $.entries;
|
||||
var string nav = "";
|
||||
if ($.nav.backward_url != "") {
|
||||
$nav = """<a href="$.nav.backward_url">back $total entries</a>""";
|
||||
}
|
||||
if ($.nav.forward_url != "" and $.nav.backward_url != "") {
|
||||
$nav = "$nav or ";
|
||||
}
|
||||
if ($.nav.forward_url != "") {
|
||||
$nav = """$nav<a href="$.nav.forward_url">forward $total entries</a>""";
|
||||
}
|
||||
print "You're looking at the latest ";
|
||||
print size $.entries;
|
||||
print ($.nav.skip > 0) ? " entries, after skipping $.nav.skip newer ones." :" entries.";
|
||||
if ($nav != "") { print "<br />Missed some entries? Then simply jump $nav"; }
|
||||
}
|
||||
|
||||
function RecentPage::print_body {
|
||||
foreach var Entry e ($.entries) {
|
||||
$this->print_entry($e);
|
||||
}
|
||||
}
|
||||
|
||||
function FriendsPage::print_body {
|
||||
foreach var Entry e ($.entries) {
|
||||
$this->print_entry($e);
|
||||
}
|
||||
}
|
||||
|
||||
function CommentInfo::print()
|
||||
{
|
||||
if (not $.enabled) { return; }
|
||||
"<tr><td bgcolor='$*accent_bgcolor'><font color='$*accent_fgcolor'>";
|
||||
"<nobr>comments: ";
|
||||
if ($.count > 0 or $.screened) {
|
||||
$this->print_readlink(); " or ";
|
||||
}
|
||||
$this->print_postlink();
|
||||
"</nobr></font></td></tr>";
|
||||
}
|
||||
|
||||
function YearPage::print_body {
|
||||
print_header(string($.year));
|
||||
print_genericbox_open();
|
||||
foreach var YearMonth m ($.months) {
|
||||
$this->print_month($m);
|
||||
}
|
||||
print_genericbox_close();
|
||||
}
|
||||
|
||||
function YearPage::lay_captionbar_navigation()
|
||||
{
|
||||
$this->print_year_links();
|
||||
}
|
||||
|
||||
function YearPage::print_year_links ()
|
||||
{
|
||||
foreach var YearYear y ($.years) {
|
||||
if ($y.displayed) {
|
||||
"$y.year ";
|
||||
} else {
|
||||
"<a href=\"$y.url\">$y.year</a> ";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function YearPage::print_month(YearMonth m)
|
||||
{
|
||||
if (not $m.has_entries) { return; }
|
||||
"<center><table border='1' cellpadding='4' width='80%'>";
|
||||
# Month header
|
||||
"<tr align='center'><td colspan='7' bgcolor='$*headerbar_bgcolor'>";
|
||||
"<font color='$*headerbar_fgcolor'><b>"; print $m->month_format(); "</b></font></td></tr>";
|
||||
# Weekdays
|
||||
"<tr align='center' bgcolor='$*accent_bgcolor'>";
|
||||
foreach var int d (weekdays()) {
|
||||
"<td><font color='$*accent_fgcolor'>"+$*lang_dayname_short[$d]+"</font></td>\n";
|
||||
}
|
||||
"</tr>";
|
||||
foreach var YearWeek w ($m.weeks) {
|
||||
$w->print();
|
||||
}
|
||||
"<tr align='center'><td colspan='7'><a href='$m.url'>View Subjects</a>";
|
||||
"</td></tr></table></center>";
|
||||
}
|
||||
|
||||
function YearWeek::print () {
|
||||
"<tr>";
|
||||
if ($.pre_empty) { "<td colspan='$.pre_empty' bgcolor='$*accent_bgcolor'> </td>"; }
|
||||
foreach var YearDay d ($.days) {
|
||||
"<td valign='top'><b>$d.day</b>";
|
||||
"<div align='center'>";
|
||||
if ($d.num_entries) {
|
||||
"""<a href="$d.url">$d.num_entries</a>""";
|
||||
} else {
|
||||
" ";
|
||||
}
|
||||
"</div></td>";
|
||||
}
|
||||
if ($.post_empty) { "<td colspan='$.post_empty' bgcolor='$*accent_bgcolor'> </td>"; }
|
||||
"</tr>";
|
||||
}
|
||||
|
||||
function DayPage::lay_captionbar_navigation()
|
||||
{
|
||||
print "Missed some entries? Then simply jump to the <a href='$.prev_url'>previous day</a> or the <a href='$.next_url'>next day</a>.";
|
||||
}
|
||||
|
||||
function DayPage::print_body ()
|
||||
{
|
||||
if (not $.has_entries) {
|
||||
"<table border='0' width='100%' cellpadding='5' cellspacing='1' bgcolor='$*border_color'>";
|
||||
"<tr><td bgcolor='$*headerbar_bgcolor'><font color='$*headerbar_fgcolor'>";
|
||||
print $.date->date_format("%%month%% %%dayord%%, %%yyyy%%");
|
||||
"</font></td></tr></table><br />";
|
||||
print "No journal entries for this day.";
|
||||
} else {
|
||||
foreach var Entry e ($.entries) {
|
||||
$this->print_entry($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function MonthPage::print_body {
|
||||
print_header($.date->date_format("%%month%% %%yyyy%%"));
|
||||
print_genericbox_open();
|
||||
"<form method='post' action='$.redir.url'><center>";
|
||||
$.redir->print_hiddens();
|
||||
if ($.prev_url != "") { "[<a href='$.prev_url'><<<</a>]\n"; }
|
||||
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 != "") { "\n[<a href='$.next_url'>>>></a>]\n"; }
|
||||
"</center></form>\n<dl>";
|
||||
foreach var MonthDay d ($.days) {
|
||||
if ($d.has_entries) {
|
||||
"<dt><a href=\"$d.url\"><b>";
|
||||
print lang_ordinal($d.day);
|
||||
"</b></a></dt>\n<dd>";
|
||||
$d->print_subjectlist();
|
||||
"</dd>\n";
|
||||
}
|
||||
}
|
||||
"</dl>\n";
|
||||
print_genericbox_close();
|
||||
}
|
||||
|
||||
function EntryPage::print_body () {
|
||||
set_handler("unscreen_comment_#", [
|
||||
[ "style_bgcolor", "cmtbar#", "$*comment_bar_one_bgcolor", ],
|
||||
[ "style_color", "cmtbar#", "$*comment_bar_one_fgcolor", ],
|
||||
]);
|
||||
set_handler("screen_comment_#", [
|
||||
[ "style_bgcolor", "cmtbar#", "$*comment_bar_screened_bgcolor", ],
|
||||
[ "style_color", "cmtbar#", "$*comment_bar_screened_fgcolor", ],
|
||||
]);
|
||||
|
||||
print_entry($this, $.entry, null Color, null Color, $.viewing_thread);
|
||||
if ($.entry.comments.enabled and $.comment_pages.total_subitems > 0)
|
||||
{
|
||||
$this->print_multiform_start();
|
||||
|
||||
print_header("Comments:");
|
||||
if ($.comment_pages.total_subitems > 0) {
|
||||
$.comment_pages->print();
|
||||
$this->print_comments($.comments);
|
||||
}
|
||||
if ($this.multiform_on) {
|
||||
print_header("Mass Action:");
|
||||
|
||||
print_genericbox_open();
|
||||
$this->print_multiform_actionline();
|
||||
print_genericbox_close();
|
||||
|
||||
$this->print_multiform_end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function EntryPage::print_comment_partial (Comment c) {
|
||||
var string poster = defined $c.poster ? $c.poster->as_string() : "<i>(Anonymous)</i>";
|
||||
var string subj = $c.subject != "" ? $c.subject : $*text_nosubject;
|
||||
print_genericbox_open();
|
||||
print "<a href='$c.permalink_url'>$subj</a> - $poster";
|
||||
print_genericbox_close();
|
||||
}
|
||||
|
||||
function EntryPage::print_comment (Comment c) {
|
||||
var string{} colors; var string{} meta; var string content = ""; var string footer = "";
|
||||
|
||||
if ($c.screened) {
|
||||
$colors{"bgcolor"} = "$*comment_bar_screened_bgcolor";
|
||||
$colors{"fgcolor"} = "$*comment_bar_screened_fgcolor";
|
||||
} elseif ($c.depth % 2) {
|
||||
$colors{"bgcolor"} = "$*comment_bar_one_bgcolor";
|
||||
$colors{"fgcolor"} = "$*comment_bar_one_fgcolor";
|
||||
} else {
|
||||
$colors{"bgcolor"} = "$*comment_bar_two_bgcolor";
|
||||
$colors{"fgcolor"} = "$*comment_bar_two_fgcolor";
|
||||
}
|
||||
|
||||
# Userpic
|
||||
var string poster = defined $c.poster ? $c.poster->as_string() : "<i>(Anonymous)</i>";
|
||||
var string metapic = "";
|
||||
if (defined $c.userpic and $*comment_userpic_style != "off")
|
||||
{
|
||||
var string userpic = defined $c.userpic ? "<img src='$c.userpic.url' style='border: 0' />" : "";
|
||||
$metapic = "$userpic<br />$poster";
|
||||
} else {
|
||||
$metapic = $poster;
|
||||
}
|
||||
|
||||
# Subject
|
||||
var string sub_icon;
|
||||
if (defined $c.subject_icon) {
|
||||
$sub_icon = $c.subject_icon->as_string();
|
||||
}
|
||||
if ($c.subject or $sub_icon) {
|
||||
$meta{"Subject:"} = "$c.subject $sub_icon";
|
||||
}
|
||||
|
||||
# Time posted
|
||||
$meta{"Time:"} = $c.time->time_format();
|
||||
|
||||
# Link
|
||||
$meta{"Link:"} = "(<a href='$c.permalink_url'>Link</a>)";
|
||||
|
||||
# IP Address:
|
||||
if ($c.metadata{"poster_ip"}) {
|
||||
$meta{"IP Address:"} = $c.metadata{"poster_ip"};
|
||||
}
|
||||
|
||||
if ($c.frozen) {
|
||||
$footer = "(Replies frozen) ";
|
||||
} else {
|
||||
$footer = "(<a href='$c.reply_url'>Reply to this</a>) ";
|
||||
}
|
||||
if ($c.parent_url != "") { $footer = "$footer (<a href='$c.parent_url'>Parent</a>) "; }
|
||||
if ($c.thread_url != "") { $footer = "$footer (<a href='$c.thread_url'>Thread</a>) "; }
|
||||
|
||||
var Link link = new Link;
|
||||
foreach var string k ($c.link_keyseq) {
|
||||
$link = $c->get_link($k); $footer = "$footer $link";
|
||||
}
|
||||
println "<a name='$c.anchor'></a>";
|
||||
print_box($colors, $metapic, $meta, $c.text, $footer, "cmtbar$c.talkid");
|
||||
}
|
||||
|
||||
function ReplyPage::print_body () {
|
||||
if (not $.entry.comments.enabled)
|
||||
{
|
||||
print_header($*text_reply_nocomments_header);
|
||||
print "<p>$*text_reply_nocomments</p>";
|
||||
return;
|
||||
}
|
||||
|
||||
var string{} meta; var string metapic;
|
||||
|
||||
# Userpic
|
||||
if (defined $.replyto.userpic and $*comment_userpic_style != "off")
|
||||
{
|
||||
$metapic = "<img src='$.replyto.userpic.url' />";
|
||||
}
|
||||
|
||||
# Subject
|
||||
if ($.replyto.subject) {
|
||||
$meta{"Subject:"} = $.replyto.subject;
|
||||
}
|
||||
|
||||
# Time posted
|
||||
$meta{"Time:"} = $.replyto.time->time_format();
|
||||
|
||||
print_box({ "bgcolor" => "$*accent_bgcolor", "fgcolor" => "$*accent_fgcolor" },
|
||||
$metapic, $meta, $.replyto.text, "", "");
|
||||
|
||||
print_header("Reply:");
|
||||
|
||||
print_genericbox_open();
|
||||
$.form->print();
|
||||
print_genericbox_close();
|
||||
|
||||
}
|
||||
|
||||
function print_theme_preview()
|
||||
{
|
||||
"<table width='100%' bgcolor='$*body_bgcolor' cellpadding=10><tr><td>";
|
||||
"<table border='0' width='100%' cellpadding='5' cellspacing='1' bgcolor='$*border_color'>";
|
||||
"<tr><td bgcolor='$*headerbar_bgcolor'><font color='$*headerbar_fgcolor'>October 29th, 2003";
|
||||
"</font></td></tr></table><br />";
|
||||
"<div align='right'><table border='0' width='95%' cellpadding='5' cellspacing='1' bgcolor='$*accent_bgcolor'>";
|
||||
"<tr><td align='left' bgcolor='$*accent_bgcolor'>";
|
||||
"<table border='0' width='100%'><tr>";
|
||||
"<td valign='top'><table border='0'>";
|
||||
"<tr><td align='right'><font color='$*accent_fgcolor'>Subject:</font>";
|
||||
"</td><td><font color='$*accent_fgcolor'>Words Words Words</font></td></tr>";
|
||||
"<tr><td align='right'><font color='$*accent_fgcolor'>Time:</font></td>";
|
||||
"<td><font color='$*accent_fgcolor'>1:37 pm</font></td></tr>";
|
||||
"</table></td></tr></table></td></tr>";
|
||||
"<tr><td align='left' bgcolor='$*main_bgcolor'><font color='$*main_fgcolor'>Preview text, preview text, etc, etc..... words, words and more words.</font></td></tr>";
|
||||
"""<tr><td align='left' bgcolor='$*accent_bgcolor'><font color='$*accent_fgcolor'><nobr>comments: <a href="#">20 comments</a> or <a href="#">Leave a comment</a></nobr></font></td></tr>""";
|
||||
"</table></div><br />";
|
||||
"</td></tr></table>";
|
||||
}
|
||||
BIN
livejournal/bin/upgrading/s2layers/tabularindent/tabularindent.jpg
Executable file
|
After Width: | Height: | Size: 19 KiB |
437
livejournal/bin/upgrading/s2layers/tabularindent/themes.s2
Executable file
@@ -0,0 +1,437 @@
|
||||
#NEWLAYER: tabularindent/shrinkvio
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Shrinking Violet";
|
||||
layerinfo redist_uniq = "tabularindent/shrinkvio";
|
||||
set body_bgcolor = "#ad22e7";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#381a45";
|
||||
set headerbar_bgcolor = "#5d0383";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set captionbar_mainbox_bgcolor = "#5d0383";
|
||||
set captionbar_mainbox_fgcolor = "#ffffff";
|
||||
set captionbar_userpicbox_color = "#d9a1f1";
|
||||
set accent_bgcolor = "#d9a1f1";
|
||||
set accent_fgcolor = "#000000";
|
||||
set link_color = "#2e053f";
|
||||
set vlink_color = "#611627";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#5d0383";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#d9a1f1";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: tabularindent/pistmint
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Pistachio Mint";
|
||||
layerinfo redist_uniq = "tabularindent/pistmint";
|
||||
set body_bgcolor = "#133422";
|
||||
set main_bgcolor = "#a7c4b4";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#096d36";
|
||||
set headerbar_bgcolor = "#096d36";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set captionbar_mainbox_bgcolor = "#096d36";
|
||||
set captionbar_mainbox_fgcolor = "#ffffff";
|
||||
set captionbar_userpicbox_color = "#096d36";
|
||||
set accent_bgcolor = "#096d36";
|
||||
set accent_fgcolor = "#000000";
|
||||
set link_color = "#8afabc";
|
||||
set vlink_color = "#1da65a";
|
||||
set alink_color = "#f9f5f5";
|
||||
set comment_bar_one_bgcolor = "#096d36";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#093f36";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: tabularindent/mexicanfood
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Mexican Food";
|
||||
layerinfo redist_uniq = "tabularindent/mexicanfood";
|
||||
set body_bgcolor = "#ff0000";
|
||||
set main_bgcolor = "#f8ff3e";
|
||||
set main_fgcolor = "#f15601";
|
||||
set border_color = "#f50701";
|
||||
set headerbar_bgcolor = "#bdbf3e";
|
||||
set headerbar_fgcolor = "#ff0000";
|
||||
set captionbar_mainbox_bgcolor = "#ffc664";
|
||||
set captionbar_mainbox_fgcolor = "#000000";
|
||||
set captionbar_userpicbox_color = "#f9ff9d";
|
||||
set accent_bgcolor = "#e15a18";
|
||||
set accent_fgcolor = "#ffffff";
|
||||
set link_color = "#f49e08";
|
||||
set vlink_color = "#b05403";
|
||||
set alink_color = "#ff7405";
|
||||
set comment_bar_one_bgcolor = "#bdbf3e";
|
||||
set comment_bar_one_fgcolor = "#ff0000";
|
||||
set comment_bar_two_bgcolor = "#e15a18";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: tabularindent/ashfire
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Ash and Fire";
|
||||
layerinfo redist_uniq = "tabularindent/ashfire";
|
||||
set body_bgcolor = "#b5b5b5";
|
||||
set main_bgcolor = "#ffb6af";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#d90308";
|
||||
set headerbar_bgcolor = "#e75454";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set captionbar_mainbox_bgcolor = "#ff9696";
|
||||
set captionbar_mainbox_fgcolor = "#ffffff";
|
||||
set captionbar_userpicbox_color = "#ff1106";
|
||||
set accent_bgcolor = "#f06c88";
|
||||
set accent_fgcolor = "#000000";
|
||||
set link_color = "#f70208";
|
||||
set vlink_color = "#b0161d";
|
||||
set alink_color = "#d70106";
|
||||
set comment_bar_one_bgcolor = "#e75454";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#f06c88";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: tabularindent/desktop
|
||||
# for layout: 13 (tabularindent/layout)
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Classic Desktop";
|
||||
layerinfo redist_uniq = "tabularindent/desktop";
|
||||
set body_bgcolor = "#00545c";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#000000";
|
||||
set headerbar_bgcolor = "#ff7b05";
|
||||
set headerbar_fgcolor = "#ffeddd";
|
||||
set captionbar_mainbox_bgcolor = "#ffffff";
|
||||
set captionbar_mainbox_fgcolor = "#000000";
|
||||
set captionbar_userpicbox_color = "#ff7b05";
|
||||
set accent_bgcolor = "#ffeddd";
|
||||
set accent_fgcolor = "#000000";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#5a76ff";
|
||||
set comment_bar_one_bgcolor = "#ff7b05";
|
||||
set comment_bar_one_fgcolor = "#ffeddd";
|
||||
set comment_bar_two_bgcolor = "#ffeddd";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: tabularindent/satinhandshake
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Satin Handshake";
|
||||
layerinfo redist_uniq = "tabularindent/satinhandshake";
|
||||
set body_bgcolor = "#480c0c";
|
||||
set main_bgcolor = "#d06464";
|
||||
set main_fgcolor = "#00001d";
|
||||
set border_color = "#000000";
|
||||
set headerbar_bgcolor = "#aaaaaa";
|
||||
set headerbar_fgcolor = "#000000";
|
||||
set captionbar_mainbox_bgcolor = "#aaaaaa";
|
||||
set captionbar_mainbox_fgcolor = "#000000";
|
||||
set captionbar_userpicbox_color = "#9d0404";
|
||||
set accent_bgcolor = "#9d0404";
|
||||
set accent_fgcolor = "#000000";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#aaaaaa";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#9d0404";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: tabularindent/deepmelodrama
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Deep MeloDrama";
|
||||
layerinfo redist_uniq = "tabularindent/deepmelodrama";
|
||||
set body_bgcolor = "#872d89";
|
||||
set main_bgcolor = "#719cff";
|
||||
set main_fgcolor = "#8e48b2";
|
||||
set border_color = "#8e48b2";
|
||||
set headerbar_bgcolor = "#3794b3";
|
||||
set headerbar_fgcolor = "#84b8e7";
|
||||
set captionbar_mainbox_bgcolor = "#65b2c1";
|
||||
set captionbar_mainbox_fgcolor = "#f5d3ff";
|
||||
set captionbar_userpicbox_color = "#8e48b2";
|
||||
set accent_bgcolor = "#65b2c1";
|
||||
set accent_fgcolor = "#f5d3ff";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#dfd3ff";
|
||||
set comment_bar_one_bgcolor = "#3794b3";
|
||||
set comment_bar_one_fgcolor = "#84b8e7";
|
||||
set comment_bar_two_bgcolor = "#65b2c1";
|
||||
set comment_bar_two_fgcolor = "#f5d3ff";
|
||||
|
||||
#NEWLAYER: tabularindent/everwhite
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Everwhite";
|
||||
layerinfo redist_uniq = "tabularindent/everwhite";
|
||||
set body_bgcolor = "#ffffff";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#000000";
|
||||
set headerbar_bgcolor = "#ffffff";
|
||||
set headerbar_fgcolor = "#000000";
|
||||
set captionbar_mainbox_bgcolor = "#ffffff";
|
||||
set captionbar_mainbox_fgcolor = "#000000";
|
||||
set captionbar_userpicbox_color = "#ffffff";
|
||||
set accent_bgcolor = "#ffffff";
|
||||
set accent_fgcolor = "#000000";
|
||||
set link_color = "#e60000";
|
||||
set vlink_color = "#c10602";
|
||||
set alink_color = "#ff0600";
|
||||
set comment_bar_one_bgcolor = "#dddddd";
|
||||
set comment_bar_one_fgcolor = "#000000";
|
||||
set comment_bar_two_bgcolor = "#aaaaaa";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: tabularindent/everblue
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Everblue with Greys";
|
||||
layerinfo redist_uniq = "tabularindent/everblue";
|
||||
set body_bgcolor = "#0f0c6d";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#000000";
|
||||
set headerbar_bgcolor = "#000000";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set captionbar_mainbox_bgcolor = "#aaaaaa";
|
||||
set captionbar_mainbox_fgcolor = "#000000";
|
||||
set captionbar_userpicbox_color = "#000000";
|
||||
set accent_bgcolor = "#aaaaaa";
|
||||
set accent_fgcolor = "#000000";
|
||||
set link_color = "#2f00f2";
|
||||
set vlink_color = "#060667";
|
||||
set alink_color = "#6691ff";
|
||||
set comment_bar_one_bgcolor = "#000000";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#aaaaaa";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: tabularindent/brownleather
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Brown Leather Coat";
|
||||
layerinfo redist_uniq = "tabularindent/brownleather";
|
||||
set body_bgcolor = "#d2b48c";
|
||||
set main_bgcolor = "#ffebcd";
|
||||
set main_fgcolor = "#8b4513";
|
||||
set border_color = "#000000";
|
||||
set headerbar_bgcolor = "#d48014";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set captionbar_mainbox_bgcolor = "#d48014";
|
||||
set captionbar_mainbox_fgcolor = "#d48014";
|
||||
set captionbar_userpicbox_color = "#d48014";
|
||||
set accent_bgcolor = "#ffe1a1";
|
||||
set accent_fgcolor = "#000000";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#867a55";
|
||||
set alink_color = "#fffab3";
|
||||
set comment_bar_one_bgcolor = "#d48014";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#ffe1a1";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: tabularindent/bruise
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Bruise";
|
||||
layerinfo redist_uniq = "tabularindent/bruise";
|
||||
set body_bgcolor = "#000000";
|
||||
set main_bgcolor = "#bcbcbc";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#000000";
|
||||
set headerbar_bgcolor = "#1114a0";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set captionbar_mainbox_bgcolor = "#21c2f1";
|
||||
set captionbar_mainbox_fgcolor = "#ffffff";
|
||||
set captionbar_userpicbox_color = "#1114a0";
|
||||
set accent_bgcolor = "#21c2f1";
|
||||
set accent_fgcolor = "#0000ff";
|
||||
set link_color = "#0000cc";
|
||||
set vlink_color = "#000088";
|
||||
set alink_color = "#0000ff";
|
||||
set comment_bar_one_bgcolor = "#1114a0";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#21c2f1";
|
||||
set comment_bar_two_fgcolor = "#0000ff";
|
||||
|
||||
#NEWLAYER: tabularindent/ranchhand
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Ranch Hand";
|
||||
layerinfo redist_uniq = "tabularindent/ranchhand";
|
||||
set body_bgcolor = "#2999c2";
|
||||
set main_bgcolor = "#cfe0ff";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#060667";
|
||||
set headerbar_bgcolor = "#54442c";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set captionbar_mainbox_bgcolor = "#bababa";
|
||||
set captionbar_mainbox_fgcolor = "#000000";
|
||||
set captionbar_userpicbox_color = "#9d995d";
|
||||
set accent_bgcolor = "#704400";
|
||||
set accent_fgcolor = "#bababa";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#6a20ff";
|
||||
set comment_bar_one_bgcolor = "#54442c";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#704400";
|
||||
set comment_bar_two_fgcolor = "#bababa";
|
||||
|
||||
#NEWLAYER: tabularindent/victim
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Victim";
|
||||
layerinfo redist_uniq = "tabularindent/victim";
|
||||
set body_bgcolor = "#2cd0ff";
|
||||
set main_bgcolor = "#505050";
|
||||
set main_fgcolor = "#ffffff";
|
||||
set border_color = "#000000";
|
||||
set headerbar_bgcolor = "#166bac";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set captionbar_mainbox_bgcolor = "#2098f3";
|
||||
set captionbar_mainbox_fgcolor = "#ffffff";
|
||||
set captionbar_userpicbox_color = "#26b6ff";
|
||||
set accent_bgcolor = "#353535";
|
||||
set accent_fgcolor = "#ffffff";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ff00c0";
|
||||
set comment_bar_one_bgcolor = "#166bac";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#353535";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: tabularindent/forest
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Forest";
|
||||
layerinfo redist_uniq = "tabularindent/forest";
|
||||
set body_bgcolor = "#778e64";
|
||||
set main_bgcolor = "#9b9ba5";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#ffffff";
|
||||
set headerbar_bgcolor = "#72784c";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set captionbar_mainbox_bgcolor = "#72784c";
|
||||
set captionbar_mainbox_fgcolor = "#ffffff";
|
||||
set captionbar_userpicbox_color = "#a0ac62";
|
||||
set accent_bgcolor = "#73777a";
|
||||
set accent_fgcolor = "#000000";
|
||||
set link_color = "#3811e1";
|
||||
set vlink_color = "#310cbb";
|
||||
set alink_color = "#4e7bef";
|
||||
set comment_bar_one_bgcolor = "#72784c";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#73777a";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: tabularindent/drone
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Drone";
|
||||
layerinfo redist_uniq = "tabularindent/drone";
|
||||
set body_bgcolor = "#395f82";
|
||||
set main_bgcolor = "#f9fcfe";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#000000";
|
||||
set headerbar_bgcolor = "#904094";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set captionbar_mainbox_bgcolor = "#f56efc";
|
||||
set captionbar_mainbox_fgcolor = "#ffffff";
|
||||
set captionbar_userpicbox_color = "#ff93ff";
|
||||
set accent_bgcolor = "#eeeeff";
|
||||
set accent_fgcolor = "#000000";
|
||||
set link_color = "#395f82";
|
||||
set vlink_color = "#395f82";
|
||||
set alink_color = "#5266ce";
|
||||
set comment_bar_one_bgcolor = "#904094";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#eeeeff";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: tabularindent/lowercurtain
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Lower the Curtain";
|
||||
layerinfo redist_uniq = "tabularindent/lowercurtain";
|
||||
set body_bgcolor = "#000000";
|
||||
set main_bgcolor = "#6b6b6b";
|
||||
set main_fgcolor = "#ffffff";
|
||||
set border_color = "#ffffff";
|
||||
set headerbar_bgcolor = "#363636";
|
||||
set headerbar_fgcolor = "#f0f5fb";
|
||||
set captionbar_mainbox_bgcolor = "#c6c6c6";
|
||||
set captionbar_mainbox_fgcolor = "#222222";
|
||||
set captionbar_userpicbox_color = "#363636";
|
||||
set accent_bgcolor = "#c5c8ca";
|
||||
set accent_fgcolor = "#000000";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#3314ba";
|
||||
set comment_bar_one_bgcolor = "#363636";
|
||||
set comment_bar_one_fgcolor = "#f0f5fb";
|
||||
set comment_bar_two_bgcolor = "#c5c8ca";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: tabularindent/sunny
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Sunny Day";
|
||||
layerinfo redist_uniq = "tabularindent/sunny";
|
||||
set body_bgcolor = "#55e0f9";
|
||||
set main_bgcolor = "#e38202";
|
||||
set main_fgcolor = "#ffffff";
|
||||
set border_color = "#000000";
|
||||
set headerbar_bgcolor = "#e38202";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set captionbar_mainbox_bgcolor = "#fff505";
|
||||
set captionbar_mainbox_fgcolor = "#ffffff";
|
||||
set captionbar_userpicbox_color = "#efe052";
|
||||
set accent_bgcolor = "#ffba03";
|
||||
set accent_fgcolor = "#ffffff";
|
||||
set link_color = "#df0d12";
|
||||
set vlink_color = "#ac1b25";
|
||||
set alink_color = "#fe3b3b";
|
||||
set comment_bar_one_bgcolor = "#ffba03";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#ffba36";
|
||||
set comment_bar_two_fgcolor = "#ffffff";
|
||||
|
||||
#NEWLAYER: tabularindent/valentine
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Be Mine";
|
||||
layerinfo redist_uniq = "tabularindent/valentine";
|
||||
set body_bgcolor = "#6f104a";
|
||||
set main_bgcolor = "#f2bce9";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#ff24ab";
|
||||
set headerbar_bgcolor = "#ff37ff";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set captionbar_mainbox_bgcolor = "#df2096";
|
||||
set captionbar_mainbox_fgcolor = "#ffffff";
|
||||
set captionbar_userpicbox_color = "#ae1774";
|
||||
set accent_bgcolor = "#df2096";
|
||||
set accent_fgcolor = "#000000";
|
||||
set link_color = "#ffffff";
|
||||
set vlink_color = "#a51014";
|
||||
set alink_color = "#ed8188";
|
||||
set comment_bar_one_bgcolor = "#ff37ff";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#df2096";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||
|
||||
#NEWLAYER: tabularindent/stripes
|
||||
layerinfo type = theme;
|
||||
layerinfo name = "Stripes";
|
||||
layerinfo redist_uniq = "tabularindent/stripes";
|
||||
set body_bgcolor = "#ffffff";
|
||||
set main_bgcolor = "#ffffff";
|
||||
set main_fgcolor = "#000000";
|
||||
set border_color = "#ff0000";
|
||||
set headerbar_bgcolor = "#e7212a";
|
||||
set headerbar_fgcolor = "#ffffff";
|
||||
set captionbar_mainbox_bgcolor = "#ffffff";
|
||||
set captionbar_mainbox_fgcolor = "#000000";
|
||||
set captionbar_userpicbox_color = "#ffffff";
|
||||
set accent_bgcolor = "#ffcfdc";
|
||||
set accent_fgcolor = "#000000";
|
||||
set link_color = "#000050";
|
||||
set vlink_color = "#500050";
|
||||
set alink_color = "#ffafc1";
|
||||
set comment_bar_one_bgcolor = "#e7212a";
|
||||
set comment_bar_one_fgcolor = "#ffffff";
|
||||
set comment_bar_two_bgcolor = "#ffcfdc";
|
||||
set comment_bar_two_fgcolor = "#000000";
|
||||