242 lines
10 KiB
Plaintext
Executable File
242 lines
10 KiB
Plaintext
Executable File
<?page
|
|
title=><?_ml .title _ml?>
|
|
body<=
|
|
|
|
<?_code
|
|
{
|
|
use strict;
|
|
use vars qw(%POST);
|
|
|
|
my $dbh = LJ::get_db_writer();
|
|
my $u = LJ::get_remote();
|
|
|
|
unless ($u) {
|
|
return "<?h1 $ML{'.loginrequired.title'} h1?><?p $ML{'.loginrequired.text'} p?>";
|
|
}
|
|
return "<?h1 $ML{'error.suspended.title'} h1?><?p $ML{'error.suspended.text'} p?>" if $u->{'statusvis'} eq "S";
|
|
|
|
if (LJ::did_post() && $POST{'userid'} != $u->{'userid'}) {
|
|
return "<?h1 $ML{'.invalid.submission'} h1?><?p $ML{'.user.nomatch'} p?>";
|
|
}
|
|
|
|
my $error = sub {
|
|
return "<?h1 $ML{'Error'} h1?><?p $_[0] p?><?p " .
|
|
BML::ml('Backlink', {'link' => '/syn/', 'text' => $ML{'.back'}}) . " p?>";
|
|
};
|
|
|
|
# add custom feed
|
|
if ($POST{'action:addcustom'} || $GET{'url'}) {
|
|
my $acct = LJ::trim($POST{'acct'});
|
|
my $url = LJ::trim($POST{'synurl'} || $GET{'url'});
|
|
|
|
if ($acct ne "") {
|
|
return $error->($ML{'.invalid.accountname'})
|
|
if $acct && $acct !~ /^\w{3,15}$/;
|
|
foreach my $re ("^system\$", @LJ::PROTECTED_USERNAMES) {
|
|
next unless ($acct =~ /$re/);
|
|
return $error->($ML{'.invalid.reserved'});
|
|
}
|
|
}
|
|
if ($url ne "") {
|
|
return $error->($ML{'.invalid.url'})
|
|
unless $url =~ m!^http://(.+?)(?::(\d+))?/!;
|
|
my $hostname = $1;
|
|
my $port = $2;
|
|
return $error->($ML{'.invalid.cantadd'})
|
|
if $hostname =~ /\Q$LJ::DOMAIN\E/i;
|
|
|
|
return $error->($ML{'.invalid.port'})
|
|
if defined $port && $port != 80 && $port < 1024;
|
|
$url =~ s/:80// if $port == 80;
|
|
}
|
|
|
|
my $su; # account to add
|
|
if ($url) {
|
|
$su = $dbh->selectrow_hashref("SELECT u.user, s.* FROM syndicated s, useridmap u ".
|
|
"WHERE s.synurl=? AND s.userid=u.userid",
|
|
undef, $url);
|
|
|
|
unless ($su) {
|
|
# check cap to create new feeds
|
|
return $error->($ML{'.error.nocreate'})
|
|
unless LJ::get_cap($u, 'synd_create');
|
|
|
|
# if no account name, give them a proper entry form to pick one, but don't reprompt
|
|
# for the url, just pass that through (we'll recheck it anyway, though)
|
|
unless ($acct) {
|
|
my $ret .= "<?h1 $ML{'.create'} h1?><?p $ML{'.create.name'} p?>";
|
|
$ret .= "<form method='post' action='./'>";
|
|
$ret .= LJ::html_hidden("userid", $u->{'userid'}, 'synurl', $url);
|
|
$ret .= "<blockquote>";
|
|
$ret .= "<p>$ML{'.account'} <input size='15' maxlength='15' name='acct' />";
|
|
$ret .= "<p><input name='action:addcustom' type='submit' value='" . LJ::ehtml($ML{'.create'}) . "' />";
|
|
$ret .= "</blockquote></form>";
|
|
return $ret;
|
|
}
|
|
|
|
return "<?h1 $ML{'.invalid.needname.title'} h1?><?p $ML{'.invalid.needname.text'} p?>"
|
|
unless $acct;
|
|
|
|
# create a safeagent to fetch the feed for validation purposes
|
|
require LWPx::ParanoidAgent;
|
|
my $ua = LWPx::ParanoidAgent->new(
|
|
timeout => 7,
|
|
max_size => (1024 * 300),
|
|
);
|
|
$ua->agent("$LJ::SITENAME ($LJ::ADMIN_EMAIL; Initial check)");
|
|
|
|
my $res = $ua->get($url);
|
|
my $content = $res && $res->is_success ? $res->content : undef;
|
|
return "<?h1 $ML{'.invalid.http.title'} h1?><?p $ML{'.invalid.http.text'} p?>"
|
|
unless $content;
|
|
|
|
my $syn_url;
|
|
# analyze link/meta tags
|
|
while ($content =~ m!<(link|meta)\b([^>]+)>!g) {
|
|
my ($type, $val) = ($1, $2);
|
|
# RSS/Atom
|
|
# <link rel="alternate" type="application/(?:rss|atom)+xml" title="RSS" href="http://...." />
|
|
if ($type eq "link" &&
|
|
$val =~ m!rel=.alternate.!i &&
|
|
$val =~ m!type=.application/(?:rss|atom)\+xml.!i &&
|
|
$val =~ m!href=[\"\']([^\"\']+)[\"\']!i) {
|
|
$syn_url = $1;
|
|
}
|
|
}
|
|
|
|
$res = $ua->get($syn_url);
|
|
$content = $res && $res->is_success ? $res->content : "";
|
|
|
|
# check whatever we did get for validity (or pseudo-validity)
|
|
return "<?h1 $ML{'.invalid.notrss.title'} h1?><?p $ML{'.invalid.notrss.text'} p?>"
|
|
unless $content =~ m/<(\w+:)?(?:rss|feed|RDF)/; # Must have a <[?:]rss <[?:]feed (for Atom support) <[?:]RDF
|
|
|
|
# create the feed account
|
|
my $id = LJ::create_account({
|
|
'user' => $acct,
|
|
'name' => $acct,
|
|
'password' => '',
|
|
'caps' => $LJ::SYND_CAPS,
|
|
'cluster' => $LJ::SYND_CLUSTER,
|
|
});
|
|
return "<?h1 $ML{'.invalid.inuse.title'} h1?><?p $ML{'.invalid.inuse.text'} p?>"
|
|
unless $id;
|
|
|
|
LJ::update_user($id, { journaltype => 'Y' });
|
|
$dbh->do("INSERT INTO syndicated (userid, synurl, checknext) VALUES (?,?,NOW())",
|
|
undef, $id, $url);
|
|
|
|
LJ::statushistory_add($u->{'userid'}, $id, "synd_create", "acct: $acct");
|
|
|
|
$su = $dbh->selectrow_hashref("SELECT u.user, s.* FROM syndicated s, useridmap u ".
|
|
"WHERE s.userid=? AND s.userid=u.userid",
|
|
undef, $id);
|
|
}
|
|
} elsif ($acct) {
|
|
# account but no URL, we can add this in any case
|
|
$su = $dbh->selectrow_hashref("SELECT u.user, s.* FROM syndicated s, useridmap u ".
|
|
"WHERE u.userid=s.userid AND u.user=?",
|
|
undef, $acct);
|
|
unless ($su) {
|
|
return $error->($ML{'.invalid.notexist'});
|
|
}
|
|
} else {
|
|
# need at least a URL
|
|
return $error->($ML{'.invalid.needurl'});
|
|
}
|
|
|
|
return $error->($ML{'.error.unknown'}) unless $su;
|
|
|
|
# at this point, we have a new account, or an old account, but we have an account, so
|
|
# let's redirect them to the add page
|
|
return BML::redirect("$LJ::SITEROOT/friends/add.bml?user=$su->{user}");
|
|
|
|
# TAG:FR:bml_syn:count_friendofs
|
|
my $count = $dbh->selectrow_array("SELECT COUNT(*) FROM friends WHERE friendid=?", undef,
|
|
$su->{'userid'});
|
|
LJ::add_friend($u->{'userid'}, $su->{'userid'}, { 'defaultview' => 1 });
|
|
}
|
|
|
|
# get most popular feeds from memcache
|
|
my $popsyn = LJ::Syn::get_popular_feeds();
|
|
|
|
# load user's friends so we can strip feeds they already watch
|
|
my $friends = LJ::get_friends($u) || {};
|
|
|
|
# populate @pop and add users they've chosen to add
|
|
my @pop;
|
|
my %urls;
|
|
my %names;
|
|
for (0 .. 99) {
|
|
next if not defined $popsyn->[$_];
|
|
my ($user, $name, $suserid, $url, $count) = @{ $popsyn->[$_] };
|
|
$names{$user} = $name;
|
|
|
|
my $suser = LJ::load_userid($suserid);
|
|
LJ::load_user_props($suser, 'url');
|
|
$urls{$user} = $suser->{url};
|
|
|
|
# skip suspended/deleted accounts, already watched feeds
|
|
next if $friends->{$suserid} || $suser->{'statusvis'} ne "V";
|
|
|
|
if ($POST{'action:add'} && $POST{"add_$user"}) {
|
|
LJ::add_friend($u->{'userid'}, $suserid, { 'defaultview' => 1 });
|
|
} else {
|
|
push @pop, [ $user, $url, $count ];
|
|
last if @pop >= 20;
|
|
}
|
|
}
|
|
|
|
# intro paragraph
|
|
my $title = BML::ml('.using.title', {'sitename' => $LJ::SITENAME});
|
|
my $ret = "<?h1 $title h1?><?p $ML{'.using.text'} p?><?p $ML{'.promo.text'} p?>";
|
|
|
|
$ret .= "<form method='post' action='./'>";
|
|
$ret .= LJ::html_hidden("userid", $u->{'userid'});
|
|
|
|
if (@pop) {
|
|
$ret .= "<?h1 $ML{'.add.pop.title'} h1?><?p $ML{'.add.pop.text'} p?>";
|
|
$ret .= "<p><table cellpadding='3' style='margin-bottom: 10px; width: 80%;'>";
|
|
$ret .= "<tr><td><b>$ML{'.table.account'}</b></td><td><b>$ML{'.table.feed'}</b></td><td></td>";
|
|
$ret .= "<td align='right'><b>$ML{'.table.watchers'}</b></td></tr>";
|
|
foreach (@pop) {
|
|
my ($user, $url, $count) = @$_;
|
|
$ret .= "<tr>";
|
|
$ret .= "<td nowrap='nowrap' valign='top'><input type='checkbox' value='1' name='add_$user' /> ";
|
|
$ret .= LJ::ljuser($user, { 'type' => 'Y' }) . "</td>";
|
|
$ret .= "<td valign='top'>";
|
|
if ($urls{$user}) {
|
|
my $displayurl = $urls{$user};
|
|
$displayurl = substr($urls{$user}, 0, 50) . "..." if length $displayurl > 60;
|
|
$ret .= "$names{$user}<br /><a href='$urls{$user}'>$displayurl</a></td>";
|
|
} else {
|
|
$ret .= "$names{$user}</td>";
|
|
}
|
|
$ret .= "<td valign='top'><a href='$url'>" . LJ::img('xml', '', { border => 0 }) . "</a></td>";
|
|
$ret .= "<td align='right' valign='top'>$count</td>";
|
|
$ret .= "</tr>";
|
|
}
|
|
$ret .= "<tr><td align='left' colspan='4'>";
|
|
$ret .= "<input type='submit' name='action:add' value='" . LJ::ehtml($ML{'.add.selected'}) . "'>";
|
|
$ret .= "</td></tr>";
|
|
$ret .= "</table>";
|
|
}
|
|
|
|
$ret .= "</form><form method='post' action='./'>";
|
|
$ret .= LJ::html_hidden("userid", $u->{'userid'});
|
|
|
|
$ret .= "<?h1 $ML{'.add.byurl.title'} h1?><?p $ML{'.add.byurl.text'} p?>";
|
|
$ret .= "<blockquote>";
|
|
$ret .= "<p>$ML{'.feed.url'} <input size='40' maxlength='255' name='synurl' />";
|
|
$ret .= "<p><input name='action:addcustom' type='submit' value='" . LJ::ehtml($ML{'.add'}) . "' />";
|
|
$ret .= "</blockquote>";
|
|
|
|
$ret .= "</form>";
|
|
|
|
return $ret;
|
|
}
|
|
_code?>
|
|
|
|
<=body
|
|
page?>
|