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

75
ljcom/htdocs/code/cache/html vendored Normal file
View File

@@ -0,0 +1,75 @@
<HTML>
<HEAD>
<TITLE>LJ::Cache - LRU Cache</TITLE>
<LINK REV="made" HREF="mailto:hackers@FreeBSD.org">
</HEAD>
<BODY>
<!-- INDEX BEGIN -->
<UL>
<LI><A HREF="#NAME">NAME</A>
<LI><A HREF="#SYNOPSIS">SYNOPSIS</A>
<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>
<LI><A HREF="#AUTHOR">AUTHOR</A>
<LI><A HREF="#SEE_ALSO">SEE ALSO</A>
</UL>
<!-- INDEX END -->
<HR>
<P>
<H1><A NAME="NAME">NAME</A></H1>
<P>
LJ::Cache - LRU Cache
<P>
<HR>
<H1><A NAME="SYNOPSIS">SYNOPSIS</A></H1>
<P>
<PRE> use LJ::Cache;
my $cache = new LJ::Cache { 'maxsize' =&gt; 20 };
my $value = $cache-&gt;get($key);
unless (defined $value) {
$val = &quot;load some value&quot;;
$cache-&gt;set($key, $value);
}
</PRE>
<P>
<HR>
<H1><A NAME="DESCRIPTION">DESCRIPTION</A></H1>
<P>
This class implements an LRU dictionary cache. The two operations on it are
<CODE>get()</CODE> and <CODE>set(),</CODE> both of which promote the key
being referenced to the ``top'' of the cache, so it will stay alive
longest.
<P>
When the cache is full and and a new item needs to be added, the oldest one
is thrown away.
<P>
You should be able to regenerate the data at any time, if
<CODE>get()</CODE> returns undef.
<P>
This class is useful for caching information from a slower data source
while also keeping a bound on memory usage.
<P>
<HR>
<H1><A NAME="AUTHOR">AUTHOR</A></H1>
<P>
Brad Fitzpatrick, <A
HREF="mailto:bradfitz@bradfitz.com">bradfitz@bradfitz.com</A>
<P>
<HR>
<H1><A NAME="SEE_ALSO">SEE ALSO</A></H1>
<P>
<CODE>perl(1).</CODE>
</BODY>
</HTML>

25
ljcom/htdocs/code/cache/index.bml vendored Normal file
View File

@@ -0,0 +1,25 @@
<?page
title=>LJ::Cache
body<=
<a href="../"><B>&lt;&lt; Code</b></a> |
<b>Download:</b> <?dl code/cache/ dl?>
<?h1 License h1?>
<?p
LJ::Cache is licensed under the <a href="http://www.gnu.org/copyleft/library.txt">LGPL</a>, also available in the distribution.
p?>
<?_code
my $doc = `perldoc -u LJ::Cache | pod2html`;
$doc =~ s/<H1>(.+?)<\/H1>/<?h1 $1 h1?>/g;
$doc =~ s/<H2>(.+?)<\/H2>/<?h2 $1 h2?>/g;
$doc =~ s/<HR>/<?hr?>/g;
return $doc;
_code?>
<=body
page?>

View File

@@ -0,0 +1,18 @@
<?page
title=>Windows Client Source
body<=
<?h1 Win32 client source h1?>
<?p
You can download the source to the windows client application here:
<?dl code/clients/win32/ dl?>.
p?>
<?p
It is licensed under the <A HREF="http://www.gnu.org/copyleft/gpl.html">GPL</A>.
p?>
<?p
Send <?ljuser visions ljuser?> changes to include in the core distribution.
p?>
<=body
page?>

View File

@@ -0,0 +1,38 @@
<?page
title=>Code
body<=
<?_code
return LJ::set_active_crumb('code');
_code?>
<?h1 Open Source h1?>
<?p
Nearly all the source code to run the LiveJournal.com server is <a href="http://www.opensource.org/">Open Source</a> / <a href="http://www.gnu.org/philosophy/free-sw.html">Free Software</a> (depending which label you prefer), as are most the <a href="/download/">client apps</a>.
p?>
<?h1 Server Code h1?>
<?p
You can get the LiveJournal server code either from the <a href="http://www.livejournal.org/download/code/">latest snapshots</a> in *.tar.gz format, or <a href="http://cvs.livejournal.org/">from CVS</a>. The snapshots are taken pretty regularly, and CVS is almost always stable, so use whatever's easiest for you. Whatever you do, though, <a href="http://www.livejournal.com/doc/server/">read the documentation</a>. You can consult current issues and pending feature requests in <a href="http://zilla.livejournal.org/">our bug database</a>.
p?>
<?h1 Libraries h1?>
<?p
The server distribution above includes the following reusable components:
<p><table cellpadding=4 border=1>
<tr bgcolor=<?emcolor?>><td><b>Name</b></td></td><td><b>Description</b></td></tr>
<tr><td>LJ::Cache</td><td>Perl module to do caching of images and other data from the database, while keeping a bound on memory usage.</tr>
<tr><td>LJ::TextMessage</td><td>Perl module to send people text messages on their cellphones and pagers</td></tr>
<tr><td>LJ::SpellCheck</td><td>Perl module to check spelling, using ispell or aspell</td></tr>
<tr><td>HTML Cleaner</td><td>Removes JavaScript and other harmful markup from HTML.</td></tr>
<tr><td>BML</td><td>Server-side markup language and templating engine.</td></tr>
</table>
p?>
<=body
page?>

View File

@@ -0,0 +1,287 @@
#!/usr/bin/perl
# -*-perl-*-
#
# LiveJournal Sync Client
# (see http://www.livejournal.com/)
# (protocol information at http://www.livejournal.com/developer/)
#
# Brad Fitzpatrick
# bradfitz@bradfitz.com
#
# For this to work, make a ~/.livejournal.rc file like:
#
# user: username
# password: password
# syncdir: /path/to/syncdir/
#
# use_proxy: 1 (optional)
# proxy_host: my.proxy.com (optional)
# proxy_port: 81 (optional)
#
# And, if not using livejournal.com's servers:
#
# server_host: ...
# server_port: ...
# server_uri: ...
use strict;
my $VERSION = "0.1";
my $SERVER_HOST = "www.livejournal.com";
my $SERVER_PORT = 80;
my $SERVER_URI = "/cgi-bin/log.cgi";
##########################################################
use URI::Escape;
use LWP::UserAgent;
# load the ~/.livejournal.rc file
my %rc = ();
load_rc_file(\%rc);
$rc{'server_host'} ||= $SERVER_HOST;
$rc{'server_port'} ||= $SERVER_PORT;
$rc{'server_uri'} ||= $SERVER_URI;
unless ($rc{'user'}) {
die "Error: No username (user) specified in ~/.livejournal.rc\n";
}
unless ($rc{'password'}) {
die "Error: No password specified in ~/.livejournal.rc\n";
}
unless ($rc{'syncdir'}) {
die "Error: No sync directory specified in ~/.livejournal.rc\n";
}
unless (-d $rc{'syncdir'}) {
die "Sync dir does not exist ($rc{'syncdir'})\n";
}
unless (-w $rc{'syncdir'}) {
die "Sync dir is not writable ($rc{'syncdir'})\n";
}
print "Starting sync.\n";
my %last;
if (open (LAST, "$rc{'syncdir'}/lastsyncs.dat")) {
print "lastsync file opened.\n";
while (<LAST>) {
chomp;
if (/^(\w+):\s*(\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d)/) {
$last{$1} = $2;
}
}
close LAST;
} else {
print "no lastsync file found (first use?)\n";
}
my $ua = make_lj_agent();
my $get_sync_items = 1;
while ($get_sync_items)
{
print "Getting some sync items...\n";
print " last{L} = $last{'L'}\n";
my %ljres = lj_request($ua, {
"mode" => "syncitems",
"user" => $rc{'user'},
"password" => $rc{'password'},
"lastsync" => $last{'L'},
});
if ($ljres{'success'} eq "OK")
{
print "Got $ljres{'sync_count'} sync items of $ljres{'sync_total'} total.\n";
if ($ljres{'sync_count'} == $ljres{'sync_total'}) {
print "Done getting sync items!\n";
$get_sync_items = 0;
}
my %syncitem;
for (my $i=1; $i<=$ljres{'sync_count'}; $i++) {
next unless ($ljres{"sync_${i}_item"} =~ /^(.+?)-(\d+)/);
my $type = $1;
my $id = $2;
my $time = $ljres{"sync_${i}_time"};
$syncitem{$type}->{$id} = $time;
}
# currently there's only type "L" (journal entries), but
# this later could be "C"omment or "T"odo, etc..
foreach my $type (keys %syncitem)
{
print "Syncing type: $type\n";
# journal entries
if ($type eq "L") {
# rebuild journal entry here ($entry{$itemid}->{$key} = $val)
# before writing it to disk.
my %entry;
# keep track of the most recent journal entry saved,
# but only use in the case when there are no left to
# find the minimum from. (for sending "lastsync")
my $maxtime = "0000-00-00 00:00:00";
# we want to keep fetching more items until no more of
# this type exist (we'll delete the key after we write
# it to disk)
while (keys %{$syncitem{$type}})
{
print "Getting a batch of log entries...\n";
print " keys = ", scalar(keys %{$syncitem{$type}}), "\n";
print " lastsync = $last{'L'}\n";
my %sres = lj_request($ua, {
"mode" => "getevents",
"selecttype" => "syncitems",
"user" => $rc{'user'},
"password" => $rc{'password'},
"lastsync" => $last{'L'},
});
if ($sres{"success"} ne "OK") {
die "getevents failed: $sres{'errmsg'}\n";
}
# these next two loops reconstruct the journal entry
# from the response
for (my $i=1; $i<=$sres{'events_count'}; $i++) {
my $itemid = $sres{"events_${i}_itemid"};
$entry{$itemid} = {
'itemid' => $itemid,
'eventtime' => $sres{"events_${i}_eventtime"},
'event' => $sres{"events_${i}_event"},
'security' => $sres{"events_${i}_security"},
'allowmask' => $sres{"events_${i}_allowmask"},
};
}
for (my $i=1; $i<=$sres{'prop_count'}; $i++) {
my $itemid = $sres{"prop_${i}_itemid"};
my $prop = $sres{"prop_${i}_name"};
my $value = $sres{"prop_${i}_value"};
$entry{$itemid}->{"prop_$prop"} = $value;
}
# now, write each journal entry to disk, then erase
# its from the $syncitem{'L'} hash
print "Writing journal entries to disk...\n";
print "Wrote: ";
foreach my $itemid (sort { $a <=> $b } keys %entry)
{
if (open(E, ">$rc{'syncdir'}/$itemid.entry")) {
foreach (sort keys %{$entry{$itemid}}) {
print E "$_: $entry{$itemid}->{$_}\n";
}
close E;
print "$itemid, ";
# increment maxtime if this sync item was newer.
if ($syncitem{'L'}->{$itemid} gt $maxtime) {
$maxtime = $syncitem{'L'}->{$itemid};
}
delete $entry{$itemid};
delete $syncitem{'L'}->{$itemid};
} else {
die "Couldn't open $itemid.entry for write!\n";
}
}
print "\n";
# now that's stuff written to disk, we need to update
# the $last{'L'} time
print "Find new LastL...\n";
if (keys %{$syncitem{'L'}}) {
# find the earliest that isn't yet synced
my @times = sort values %{$syncitem{'L'}};
$last{'L'} = $times[0];
print "New LastL (keys) = $last{'L'}\n";
} else {
$last{'L'} = $maxtime; # FIXME: subtract a second
# in case two entries were on
# same second.
print "New LastL (maxtime) = $last{'L'}\n";
}
if (open (LAST, ">>$rc{'syncdir'}/lastsyncs.dat")) {
print LAST "L: $last{'L'}\n";
close LAST;
} else {
die "Couldn't append lastsyncs.dat file.\n";
}
}
}
}
}
else
{
die "Error getting sync items: $ljres{'errmsg'}\n";
}
}
print "DONE!\n";
sub load_rc_file
{
my $rcref = shift;
my $file = "$ENV{'HOME'}/.livejournal.rc";
return unless (-e $file);
open (RC, $file);
while (<RC>)
{
s/^\s+//;
s/\s+$//;
next unless /\S/;
my ($var, $val) = split(/\s*:\s*/, $_);
$rcref->{$var} = $val;
}
close RC;
}
sub make_lj_agent
{
my $ua = new LWP::UserAgent;
$ua->agent("PerlLiveJournalClient/$VERSION");
$ua->timeout(10);
return $ua;
}
sub lj_request
{
my $ua = shift;
my $vars = shift;
my %ljres = ();
# Create a request
my $req = new HTTP::Request POST => "http://$SERVER_HOST:$SERVER_PORT/$SERVER_URI";
$req->content_type('application/x-www-form-urlencoded');
$req->content(request_string($vars));
# Pass request to the user agent and get a response back
my $res = $ua->request($req);
# Check the outcome of the response
if ($res->is_success) {
%ljres = split(/\n/, $res->content);
} else {
$ljres{'success'} = "FAIL";
$ljres{'errmsg'} = "Client error: Error contacing server.";
}
return %ljres;
}
sub request_string
{
my ($vars) = shift;
my $req = "";
foreach (sort keys %{$vars})
{
my $val = uri_escape($vars->{$_},"\+\=\&");
$val =~ s/ /+/g;
$req .= "&" if $req;
$req .= "$_=$val";
}
return $req;
}

View File

@@ -0,0 +1,25 @@
<?page
title=>LJ::SpellCheck
body<=
<a href="../"><B>&lt;&lt; Code</b></a> |
<b>Download:</b> <?dl code/spellcheck/ dl?>
<?h1 License h1?>
<?p
LJ::SpellCheck is licensed under the <a href="http://www.gnu.org/copyleft/library.txt">LGPL</a>, also available in the distribution.
p?>
<?_code
my $doc = `perldoc -u LJ::SpellCheck | pod2html`;
$doc =~ s/<H1>(.+?)<\/H1>/<?h1 $1 h1?>/g;
$doc =~ s/<H2>(.+?)<\/H2>/<?h2 $1 h2?>/g;
$doc =~ s/<HR>/<?hr?>/g;
return $doc;
_code?>
<=body
page?>

View File

@@ -0,0 +1,25 @@
<?page
title=>LJ::TextMessage
body<=
<a href="../"><B>&lt;&lt; Code</b></a> |
<b>Download:</b> <?dl code/textmessage/ dl?>
<?h1 License h1?>
<?p
LJ::TextMessage is licensed under the <a href="http://www.gnu.org/copyleft/library.txt">LGPL</a>, also available in the distribution.
p?>
<?_code
my $doc = `perldoc -u LJ::TextMessage | pod2html`;
$doc =~ s/<H1>(.+?)<\/H1>/<?h1 $1 h1?>/g;
$doc =~ s/<H2>(.+?)<\/H2>/<?h2 $1 h2?>/g;
$doc =~ s/<HR>/<?hr?>/g;
return $doc;
_code?>
<=body
page?>