body<= "; } return "" if $u->{'statusvis'} eq "S"; if (LJ::did_post() && $POST{'userid'} != $u->{'userid'}) { return ""; } my $error = sub { return " '/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 .= ""; $ret .= "
"; $ret .= LJ::html_hidden("userid", $u->{'userid'}, 'synurl', $url); $ret .= "
"; $ret .= "

$ML{'.account'} "; $ret .= "

"; $ret .= "

"; return $ret; } return "" 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 "" unless $content; my $syn_url; # analyze link/meta tags while ($content =~ m!<(link|meta)\b([^>]+)>!g) { my ($type, $val) = ($1, $2); # RSS/Atom # 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 "" 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 "" 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 = ""; $ret .= "
"; $ret .= LJ::html_hidden("userid", $u->{'userid'}); if (@pop) { $ret .= ""; $ret .= "

"; $ret .= ""; $ret .= ""; foreach (@pop) { my ($user, $url, $count) = @$_; $ret .= ""; $ret .= ""; $ret .= ""; } else { $ret .= "$names{$user}"; } $ret .= ""; $ret .= ""; $ret .= ""; } $ret .= ""; $ret .= "
$ML{'.table.account'}$ML{'.table.feed'}$ML{'.table.watchers'}
"; $ret .= LJ::ljuser($user, { 'type' => 'Y' }) . ""; if ($urls{$user}) { my $displayurl = $urls{$user}; $displayurl = substr($urls{$user}, 0, 50) . "..." if length $displayurl > 60; $ret .= "$names{$user}
$displayurl
" . LJ::img('xml', '', { border => 0 }) . "$count
"; $ret .= ""; $ret .= "
"; } $ret .= "

"; $ret .= LJ::html_hidden("userid", $u->{'userid'}); $ret .= ""; $ret .= "
"; $ret .= "

$ML{'.feed.url'} "; $ret .= "

"; $ret .= "

"; $ret .= "
"; return $ret; } _code?> <=body page?>