"; # $body .= LJ::run_hook("bot_director", $pre, $post); if ($LJ::SERVER_DOWN) { $title = $ML{'Sorry'}; $body = LJ::server_down_html(); return; } my $MAX_FRIENDS_SHOW = 500; my $MAX_FRIENDOF_SHOW = 150; my $remote = LJ::get_remote(); if ($GET{'user'} eq "" && !$remote) { $body = ""; return; } my $sth; my %countries = (); my %states = (); LJ::load_codes({ "country" => \%countries, "state" => \%states }); my $error = sub { my $e = shift; $body = ""; return; }; my $user = LJ::canonical_username($GET{'user'}); if ($GET{'user'} && ! $user) { $body = $ML{'.error.malfname'}; return; } if ($user eq "" && $remote) { $user = $remote->{'user'}; } my $dbr = LJ::get_db_reader(); return $error->($ML{'error.nodb'}) unless $dbr; my $userid = $GET{'userid'}; my $u; $userid += 0; { if ($userid) { $u = LJ::load_userid($userid); } else { $u = LJ::load_user($user); } return $error->($ML{'.label.reqfinduser'}) if $userid && ! LJ::check_priv($remote, "finduser") && ! ($GET{t} eq "I" && $u && $u->{journaltype} eq "I"); # fix accidentally broken ext_nnnn URLs for identity users if ($u->{journaltype} eq "I" && ! $userid && $u->{user} !~ /^imp.*/ ) { return BML::redirect("$LJ::SITEROOT/userinfo.bml?userid=$u->{'userid'}&t=I"); } $user = $u->{'user'} if $u; $userid = $u->{'userid'}+0 if $u; LJ::text_out(\$u->{'name'}) if $u; if ($u && ($GET{'mode'} eq "full" || $u->{'journaltype'} eq "Y")) { $sth = $dbr->prepare("SELECT timeupdate, timecreate, ". "UNIX_TIMESTAMP()-UNIX_TIMESTAMP(timeupdate) ". "AS 'secondsold' FROM userusage ". "WHERE userid=$userid"); $sth->execute; ($u->{'timeupdate'}, $u->{'timecreate'}, $u->{'secondsold'}) = $sth->fetchrow_array; } } unless ($u->{'userid'}) { $title = $ML{'Error'}; $body = "$user}) . " p?>"; return; } if ($LJ::LJR_FIF && $u->{'user'} eq $LJ::LJR_FIF) {$fif=1;} # account purged? if ($u->{'statusvis'} eq "X") { $title = $ML{'error.purged.title'}; $body = ""; BML::set_status(410); # 410 Gone return; } my $dbcr = LJ::get_cluster_reader($u); return $error->($ML{'error.nodb'}) unless $dbcr; # option my %hide_fo; # userid -> 1 if ($LJ::HIDE_FRIENDOF_VIA_BAN) { if (my $list = LJ::load_rel_user($u, 'B')) { $hide_fo{$_} = 1 foreach @$list; } } if ($LJ::LJR_FIF) { $hide_fo{LJ::get_userid($LJ::LJR_FIF)} = 1; } my $remote_isowner = $remote && $remote->{'user'} eq $u->{'user'}; my $remote_isfriend = LJ::is_friend($u, $remote); my $com = $u->{'journaltype'} eq "C" ? 1 : 0; my $extid = $u->{'journaltype'} eq "I" ? $u->identity : undef; my $synd; if ($u->{'journaltype'} eq "Y") { $synd = $dbr->selectrow_hashref("SELECT * FROM syndicated WHERE userid=$u->{'userid'}"); } my $dir = "users"; ### load user props. some don't apply to communities { my @props = qw(opt_whatemailshow country state city zip renamedto journaltitle journalsubtitle public_key url urlname opt_hidefriendofs dont_load_members opt_showmutualfriends fb_num_pubpics); unless ($com || $synd) { push @props, qw(aolim icq yahoo msn gender jabber); } if ($synd) { push @props, qw(rssparseerror); } if ($u->{'statusvis'} eq 'V') { push @props, qw(opt_blockrobots); } LJ::run_hooks('userinfo_local_props', { 'props' => \@props }); LJ::load_user_props($u, @props); } if ($u->{'statusvis'} ne 'V' || $u->{'opt_blockrobots'}) { $head .= LJ::robot_meta_tags(); } if ($u->{'journaltype'} eq "R" && $u->{'renamedto'}) { my $extra = $GET{'mode'} eq 'full' ? "&mode=full" : ''; return BML::redirect("$LJ::SITEROOT/userinfo.bml?user=$u->{'renamedto'}$extra"); } my %friends = ('load'=>1, 'loaded'=>0, 'display'=>1, 'count'=>0); my %friendsof = ('load'=>1, 'loaded'=>0, 'display'=>1, 'count'=>0); if ($com) { $title = $ML{'.title.communityinfo'}; $dir = "community"; } elsif ($synd) { $title = $ML{'.title.syndicated'}; $u->{'opt_whatemailshow'} = "N"; # don't show email $friends{'load'} = $friends{'display'} = 0; $friendsof{'load'} = 1; } if ($extid) { $windowtitle = "External identity profile"; } else { $windowtitle = "$u->{'user'} - $title"; } $friends{'load'} = $friendsof{'load'} = 0 if $com && $u->{'dont_load_members'}; # do they have the viewall priv? # there are no entries on this page, so we just check if they have any viewall, so viewsome # applies here too. we can't see info they've hidden anyway, but we can see the page. my $viewall = 0; if ($GET{'viewall'} && LJ::check_priv($remote, "canview")) { $viewall = LJ::check_priv($remote, 'canview', '*'); LJ::statushistory_add($u->{'userid'}, $remote->{'userid'}, "viewall", "userinfo: $u->{'user'}, statusvis: $u->{'statusvis'}"); } else { if ($u->{'statusvis'} eq "S") { $title = $ML{'error.suspended.title'}; $body = " LJ::ljuser($user), 'sitename' => $LJ::SITENAME }) . " p?>"; BML::set_status(403); # 403 Forbidden return; } if ($u->{'statusvis'} eq "D") { $title = $ML{'error.deleted.title'}; $body = "$user}) . " p?>"; BML::set_status(404); # 404 Not Found return; } } $user = $u->{'user'}; $userid = $u->{'userid'}; $u->{'bio'} = LJ::get_bio($u); LJ::text_out(\$u->{'bio'}); # arrayref of interests rows: [ intid, intname, intcount ] my $intu = LJ::get_interests($u); my %remote_interest; if ($remote && $remote->{'userid'} != $userid) { if (my $rint = LJ::get_interests($remote, { justids => 1 })) { $remote_interest{$_} = 1 foreach @$rint; } } if ($u->{'opt_hidefriendofs'} && ! $remote_isowner) { # at this point, load should be on if viewall is on or if the user # wants to show their mutual friends $friendsof{'load'} = $u->{'opt_showmutualfriends'} || $viewall; $friendsof{'display'} = $viewall; } # Add metadata links to my $digest = Digest::SHA1::sha1_hex('mailto:' . $u->{'email'}); $head .= "\n"; $head .= "\n"; $head .= "\n"; $head .= "\n"; my @friends; my $fr_res; my %fr; # TAG:FR:userinfo:loadfriends if ($friends{'load'}) { $fr_res = LJ::get_friends($u); my @ids = keys %$fr_res; $friends{'count'} = @ids; unless ($fif) { if (@ids > $MAX_FRIENDS_SHOW) { @ids = splice(@ids, 0, $MAX_FRIENDS_SHOW); } } LJ::load_userids_multiple([ map { $_ => \$fr{$_} } @ids ]); push @friends, sort { $a->{user} cmp $b->{user} } values %fr; $friends{'loaded'} = 1; } my (@friend_of, @member_of, @mutual); # TAG:FR:userinfo:loadfriendofs if ($friendsof{'load'}) { # figure at most 50 people are not statusvis='V' *shrug* (this is lame pending the friend changes) my @ids = grep { ! $hide_fo{$_} } LJ::get_friendofs($u); unless ($fif) {$friendsof{'load_clipped'} = @ids > $LJ::MAX_FRIENDOF_LOAD;} my %fro; LJ::load_userids_multiple([ map { $_ => \$fro{$_} } @ids ]); foreach my $ulocal (sort { $a->{'user'} cmp $b->{'user'} } values %fro) { next unless $ulocal->{'statusvis'} eq 'V'; if ($ulocal->{'journaltype'} eq 'P' || $ulocal->{'journaltype'} eq "I") { if (!$com && $u->{'opt_showmutualfriends'} && $fr{$ulocal->{userid}}) { push @mutual, $ulocal; } else { push @friend_of, $ulocal; } } else { push @member_of, $ulocal; # 'S' or 'C' (shared or community) } } $friendsof{'count'} = scalar @friend_of; $friendsof{'count_m'} = scalar @member_of; $friendsof{'count_b'} = scalar @mutual; $friendsof{'loaded'} = 1; } $u->{'name'} = LJ::ehtml($u->{'name'}); # TAG:FR:userinfo:remotefriends # who does the remote user list as a friend? my %remote_friendid; if ($remote && $friends{'loaded'}) { if ($remote->{'userid'} == $u->{'userid'}) { foreach (@friends) { $remote_friendid{$_->{'userid'}} = 1; } } else { my $frs = LJ::get_friends($remote) || {}; $remote_friendid{$_} = 1 while $_ = each %$frs; } } # BML helpers. we do BML by hand in this page, so we don't force BML # to evaluate this huge page looking for non-existent BML. this # makes it quicker, and prevents us from having to clean out BML in # the HTML cleaner too. my $h1 = sub { return BML::fill_template("h1", { DATA => $_[0] }); }; my $p = sub { return BML::fill_template("p", { DATA => $_[0] }); }; if ($com) { $body .= $h1->($ML{'.comminfo.name'}); my $pt = BML::ml('.comminfo.body',{'commname'=>$u->{'name'}}) . " "; my $userinfo_join_community; LJ::run_hooks("userinfo_join_community", { 'u' => $u, 'ret' => \$userinfo_join_community, }); $pt .= $userinfo_join_community ? $userinfo_join_community : BML::ml('.membership.body',{'commname'=>$u->{'user'}}); $pt .= BML::ml('.body.leave',{'commname'=>$u->{'user'}}); $body .= $p->($pt); } elsif ($synd) { $body .= $h1->($ML{'.syndinfo.name'}) . $p->(BML::ml('.syndinfo.body', { 'addtofriends' => "$LJ::SITEROOT/friends/add.bml?user=$u->{'user'}", })); } elsif ($extid) { if ($extid->[0] eq "O") { $body .= $h1->("OpenID user"); $body .= $p->("This is a non-$LJ::SITENAME user that's using their external identity to log in to $LJ::SITENAME using OpenID in order to leave authenticated comments and read friends-only entries."); } } else { $body .= $h1->($ML{'.userinfo.name'}) . $p->(BML::ml('.userinfo.body', { 'username' => $u->{'name'}, 'siteroot'=>$LJ::SITEROOT, })); } ## standout bar { my @linkele; my $label = $com ? $ML{'.monitor.comm'} : $ML{'.monitor.user'}; if ($u->{user} !~ /^imp\_/o) { push @linkele, "$label"; } else { push @linkele, "No available actions"; } if (LJ::can_use_journal($remote->{'userid'}, $user) && !$extid) { if($remote_isowner) { $label = $ML{'.label.postalt'}; } else { $label = BML::ml('.label.post', {'journal' => $user}); } $label = LJ::ehtml("$label"); push @linkele, "$label"; } $label = $ML{'.label.todo'}; push @linkele, "$label" unless $extid; $label = $ML{'.label.memories'}; push @linkele, "$label" unless $extid; unless ($LJ::DISABLED{'tellafriend'} || $extid) { push @linkele, "$ML{"; } unless ($LJ::DISABLED{'feedster_search'} || $extid || $u->{'opt_blockrobots'}) { push @linkele, "$ML{"; } if (@linkele) { $body .= BML::fill_template("standout", { DATA => join("  ", @linkele), }); } } $body .= ""; { my $hook_extra; LJ::run_hooks("userinfo_html_by_user", { 'u' => $u, 'ret' => \$hook_extra, }); if ($u->{journaltype} eq "I") { if ($u->{user} =~ /^imp\_/o) { $body .= ""; } else { $body .= ""; } } else { $body .= "\n"; } } ### picture my $narrow_left = 2; ## rows with smaller colspan to 2 $body .= ""; ### /picture $body .= "\n"; ## journal title if ($u->{'journaltitle'}) { my $span = ($narrow_left-- >= 0) ? 1 : 2; $body .= "\n"; } ### name or 'syndicated from' unless ($synd) { unless ($u->underage || $u->{'name'} eq $u->{'journaltitle'}) { $narrow_left--; $body .= "\n"; } } else { $narrow_left--; my $link; if (my $url = $u->{'url'}) { $link="$u->{'name'}"; } else { $link=$u->{'name'}; } my $icon="". ""; $body .= "\n". "\n"; # syndication status $body .= "\n"; } ## text message if ($u->{'txtmsg_status'} eq "on" && LJ::get_cap($u, "textmessaging")) { my $span = ($narrow_left-- >= 0) ? 1 : 2; $body .= ""; } if ( ! $synd && $u->{'url'}) { my $url = LJ::ehtml($u->{'url'}); my $span = ($narrow_left-- >= 0) ? 1 : 2; unless ($url =~ /^https?:\/\//) { $url =~ s/^http\W*//; $url = "http://$url"; } my $urlname = LJ::ehtml($u->{'urlname'} || $url); $url = "$urlname"; $body .= "\n" if ($u->{'url'}); } if ( ! $synd && ($u->{'allow_infoshow'} eq "Y" || $viewall)) { if ($u->{'city'} || $u->{'state'} || $u->{'country'}) { my $span = ($narrow_left-- >= 0) ? 1 : 2; $body .= ""; } if ($u->{'bdate'} && !$com && $u->{'bdate'} ne "0000-00-00" && !$u->underage) { my $bdate = $u->{'bdate'}; $bdate =~ s/^0000-//; my $span = ($narrow_left-- >= 0) ? 1 : 2; $body .= "\n"; } } if ( ! $synd && ! $u->underage && ($u->{'allow_contactshow'} eq "Y" || ($u->{'allow_contactshow'} eq "F" && $remote_isfriend) || $viewall)) { my $mangleaddress = sub { my $email = shift; my $mret = "
Imported:" . LJ::ljuser($u) . "
OpenID:" . LJ::ljuser($u) . "
$ML{'.label.user'}$user ($u->{'userid'}) $hook_extra "; if ($u->{public_key}) { $body .= ""; $body .= "View public key"; } $body .= ""; if ($u->{'defaultpicid'}) { my $picid = $u->{'defaultpicid'}; my %pic; LJ::load_userpics(\%pic, [ $u, $picid ]); $body .= "$user"; } else { $body .= " "; } $body .= "
"; $body .= "" . LJ::ehtml($u->{'journaltitle'}) . ""; if ($u->{'journalsubtitle'}) { $body .= "
" . LJ::ehtml($u->{'journalsubtitle'}) . ""; } $body .= "
$ML{'.label.name'}$u->{'name'}
$ML{'.label.syndicatedfrom'}$link $icon
$ML{'.label.syndicatedstatus'}\n"; $body .= "$ML{'.syn.lastcheck'} "; $body .= $synd->{'lastcheck'} || $ML{'.syn.last.never'}; my $status = { 'parseerror' => "Parse error", 'notmodified' => "Not Modified", 'toobig' => "Too big", 'posterror' => "Posting error", 'ok' => "", # no status line necessary 'nonew' => "", # no status line necessary 'httperror' => "HTTP error", }->{$synd->{'laststatus'}}; $body .= " ($status)" if $status; if ($synd->{'laststatus'} eq "parseerror" || $synd->{'laststatus'} eq "httperror") { $body .= "
$ML{'.syn.parseerror'} " . LJ::ehtml($u->{'rssparseerror'}); } $body .= "
$ML{'.syn.nextcheck'} $synd->{'checknext'}"; $body .= "
$ML{'.label.textmessage'}" . BML::ml('.sendmessage.body',{'user'=>$u->{'user'}, 'link'=>"/tools/textmessage.bml?user=$u->{'user'}"}) . "
$ML{'.label.website'}$url
$ML{'.label.location'}"; my $estate = LJ::eurl($u->{'state'}); my $ecity = LJ::eurl($u->{'city'}); my $ecountry = LJ::eurl($u->{'country'}); my ($state, $city, $country); if ($u->{'country'}) { $country = $LJ::DISABLED{'directory'} ? $countries{$u->{'country'}} : "". $countries{$u->{'country'}} . ""; } my $estate; if ($u->{'state'}) { $state = $u->{'state'}; if ($u->{'country'} eq "US") { $state = $states{$state}; } $estate = LJ::eurl($state); $state = $LJ::DISABLED{'directory'} || ! $u->{'country'} ? $state : "$state"; } if ($u->{'city'}) { my $ecity = LJ::eurl($u->{'city'}); $city = LJ::ehtml($u->{'city'}); if (! $LJ::DISABLED{'directory'} && $u->{'country'}) { $city = "$city"; } } $body .= join(", ", grep { $_ } ($city, $state, $country)); $body .= "
$ML{'.label.birthdate'}$bdate
"; for (my $i = 0; $i < length($email); $i++) { my $letter = substr($email, $i, 1); if ($letter eq "\@") { $letter = "\@"; } $mret .= $letter; } $mret .= "
"; return $mret; }; # some classes of users we want to have their contact info hidden # after so much time of activity, to prevent people from bugging # them for their account or trying to brute force it. my $hide_contactinfo = sub { my $hide_after = LJ::get_cap($u, "hide_email_after"); return 0 unless $hide_after; my $memkey = [$u->{userid}, "timeactive:$u->{userid}"]; my $active; unless (defined($active = LJ::MemCache::get($memkey))) { $active = $dbcr->selectrow_array("SELECT timeactive FROM clustertrack2 ". "WHERE userid=?", undef, $u->{userid}); LJ::MemCache::set($memkey, $active, 86400); } return $active && (time() - $active) > $hide_after * 86400; }; my $useremail_cap = LJ::get_cap($u, 'useremail'); unless ($u->{'opt_whatemailshow'} eq "N" || $u->{'journaltype'} eq "I" || $u->{'opt_whatemailshow'} eq "L" && ($u->{'no_mail_alias'} || ! $useremail_cap || ! $LJ::USER_EMAIL) || $hide_contactinfo->()) { my $span = ($narrow_left-- >= 0) ? 1 : 2; $body .= "$ML{'.label.email'}"; my @emails = ($u->{'email'}); if ($u->{'opt_whatemailshow'} eq "L") { @emails = (); } if ($LJ::USER_EMAIL && $useremail_cap) { unless ($u->{'opt_whatemailshow'} eq "A" || $u->{'no_mail_alias'}) { push @emails, "$u->{'user'}\@$LJ::USER_DOMAIN"; } } foreach my $email (@emails) { $body .= ($u->{'opt_mangleemail'} eq "Y" || $email =~ /\@lj\.rossial\.org$/) ? $mangleaddress->($email) : "$email
"; } $body .= ""; } foreach my $k (qw(aolim icq yahoo msn jabber)) { $u->{$k} = LJ::ehtml($u->{$k}); } if ($u->{'aolim'}) { my $qim = $u->{'aolim'}; $qim =~ s/ //g; my $span = ($narrow_left-- >= 0) ? 1 : 2; $body .= "$ML{'.label.aolim'}AIM status $u->{'aolim'} ($ML{'.label.addbuddy'}, $ML{'.label.sendmessage'})\n"; } if ($u->{'icq'}) { my $span = ($narrow_left-- >= 0) ? 1 : 2; $body .= "$ML{'.label.icquin'}"; $body .= "ICQ status "; $body .= "$u->{'icq'} ("; $body .= "$ML{'.label.userprofile'})"; $body .= "\n"; } if ($u->{'yahoo'}) { my $span = ($narrow_left-- >= 0) ? 1 : 2; $body .= "$ML{'.label.yahooid'}Yahoo status $u->{'yahoo'} ($ML{'.label.adduser'}, $ML{'.label.sendmessage'}) \n"; } if ($u->{'msn'}) { my $span = ($narrow_left-- >= 0) ? 1 : 2; my $msnname = ($u->{'opt_mangleemail'} eq "Y") ? $mangleaddress->($u->{'msn'}) : $u->{'msn'}; $body .= "$ML{'.label.msnusername'}$msnname\n"; } if ($u->{'jabber'}) { my $span = ($narrow_left-- >= 0) ? 1 : 2; my $jabber = $mangleaddress->($u->{'jabber'}); $body .= "$ML{'.label.jabber'}$jabber\n"; } } if ($u->{'has_bio'} eq "Y") { my $span = ($narrow_left-- > 0) ? 1 : 2; my $label = $com ? $ML{'.about.comm'} : $ML{'.about.user'}; LJ::CleanHTML::clean_userbio(\$u->{'bio'}); $body .= "$label$u->{'bio'}\n"; } ### memories { my $memcount = LJ::Memories::count($userid); if ($memcount) { my $span = ($narrow_left-- > 0) ? 1 : 2; my $noun_name = $memcount == 1 ? '.memories.entry' : '.memories.entries'; my $count = BML::ml($noun_name, {'count'=>$memcount}); $body .= "$ML{'.label.memories'}$count\n"; } } ### Fotobilder gallery count { if (LJ::get_cap($u, 'fb_account') && LJ::get_cap($u, 'fb_can_upload') && $u->{'fb_num_pubpics'}+0 > 0) { my $span = ($narrow_left-- >= 0) ? 1 : 2; # what we display is an estimate. to eliminate confusion on the user end, we'll display the # estimate in a way that makes it clear it's not an exact number. rules are: # # * < 10 == "under 10" # * 10..999 == "at least 150" (rounded down to nearest 10) # * 1000+ == "at least 1500" (rounded down to nearest 100) # my $ct = $u->{fb_num_pubpics}; my $ct_str; if ($ct < 10) { $ct_str = BML::ml('.fbpictures.lessthan', { count => 10 }); } else { my $order = $ct < 100 ? 10 : 100; my $base = POSIX::floor($ct / $order); $ct_str = BML::ml('.fbpictures.over', { count => $base * $order }); } $body .= "$ML{'.label.fbpictures'}$ct_str\n"; } } if (@$intu) { my $span = ($narrow_left-- > 0) ? 1 : 2; $body .= "$ML{'.label.interests'}:"; my $intcount = 0; my $intlist = ""; foreach my $int (@$intu) { next if $intcount++ > 150; LJ::text_out(\$int->[1]); # 1==interest my $eint = LJ::eurl($int->[1]); if ($int->[2] > 1) { # 2==intcount if ($remote_interest{$int->[0]}) { # 0==intid $intlist .= "$int->[1], "; } else { $intlist .= "$int->[1], "; } } else { $intlist .= "$int->[1], "; } } chop $intlist; chop $intlist; # remove trailing ", " if ($intcount > 150) { my $notshown = $intcount - 150; $intlist .= BML::ml('.label.intsnotshown',{'intnotshown'=>$notshown}); } $body .= "$intcount: " . $intlist; if ($remote) { my $link = "/interests.bml?mode=enmasse"; $link .= "&fromuser=$user" unless ($remote->{'userid'} == $userid); $body .= ". "; my $mlcode = ($remote->{'userid'} == $userid) ? '.label.interests.removesome' : '.label.interests.modifyyours'; $body .= BML::ml('Actionlink', { 'link' => "$ML{$mlcode}" }); $body .= ""; } $body .= ""; } ## ## friends ## unless ($synd || $LJ::FORCE_EMPTY_FRIENDS{$userid}) { my $label = $com ? $ML{'.friends.comm'} : $ML{'.friends.user'}; my $span = ($narrow_left-- >= 0) ? 1 : 2; $body .= "$label:"; unless ($fif) {$friends{'display'} = 0 if $friends{'count'} > $MAX_FRIENDS_SHOW;} if ($friends{'count'}) { if (!$friends{'loaded'} || !$friends{'display'}) { $body .= "" . $friends{'count'} . ": "; $body .= " " . ($com ? $ML{'.label.viewmembers'} : $ML{'.label.viewfriends'}) . " ."; } elsif ($u->{'journaltype'} eq 'P' or $u->{'journaltype'} eq 'S') { # personal/shared journals have a special way of showing their friends list, it breaks it down into # three sublists: personal/shared, community/news, syndication my (@pfriends, @cfriends, @yfriends); my $friend_link = sub { my $f = shift; my $status = $f->{'statusvis'}; my $frlink = "$f->{'user'}"; $frlink = "$frlink" if $status =~ /[DXS]/; $frlink = "$frlink" if $remote_friendid{$f->{'userid'}} && $remote->{'userid'} != $u->{'userid'}; return $frlink; }; foreach my $f (@friends) { push @pfriends, $friend_link->($f) if $f->{'journaltype'} eq 'P' or $f->{'journaltype'} eq 'S'; push @cfriends, $friend_link->($f) if $f->{'journaltype'} eq 'C' or $f->{'journaltype'} eq 'N'; push @yfriends, $friend_link->($f) if $f->{'journaltype'} eq 'Y'; } my ($pcount, $ccount, $ycount) = (scalar @pfriends, scalar @cfriends, scalar @yfriends); my $pfriends = join ', ', @pfriends; my $yfriends = join ', ', @yfriends; my $cfriends = join ', ', @cfriends; # now spit out the HTML $body .= ""; if ($pfriends) { my $text = LJ::ehtml($ML{'.label.frpeople'}); $body .= "" . "". ""; } if ($cfriends) { my $text = LJ::ehtml($ML{'.label.frcommunity'}); $body .= "" . "" . ""; } if ($yfriends) { my $text = LJ::ehtml($ML{'.label.frsyndication2'}); $body .= "" . "" . ""; } $body .= "
" . "$text$pcount:$pfriends
" . "$text$ccount:$cfriends
" . "$text$ycount:$yfriends
"; } else { $body .= "" . $friends{'count'} . ": "; foreach my $f (@friends) { my $status = $f->{'statusvis'}; my $frlink = "$f->{'user'}"; $frlink = "$frlink" if $status =~ /[DXS]/; $frlink = "$frlink" if $remote_friendid{$f->{'userid'}} && $remote->{'userid'} != $u->{'userid'}; $body .= $frlink; $body .= ", "; } chop $body; chop $body; } } else { $body .= $ML{'.label.nofriends'}; } $body .= "\n"; } # friend of and mutual friends display # there are two options that will affect what gets shown below: opt_hidefriendofs, opt_showmutualfriends # if the option to show mutual friends is on, then what was known as the friend of list is broken down # into two lists: mutual friends (people you list and who also list you back) and 'also friend of', which # lists the people you don't also list as friends. you can hide your friend of list, and leave just # your mutual friends list showing, or you can not split them and have both be hidden. # unless ($synd) { if ($friendsof{'loaded'}) { my $label; if ($u->{'opt_showmutualfriends'} && @mutual) { $label = $ML{'.label.mutual'}; $body .= "$label"; $body .= ""; my $plus = $friendsof{'load_clipped'} ? "+" : ""; $body .= "" . $friendsof{'count_b'} . "$plus: "; my $count = 0; my $bold_mutual = ! LJ::u_equals($remote, $u); foreach (@mutual) { my $frlink = "{'user'}\">$_->{'user'}"; $frlink = "$frlink" if $bold_mutual && $remote_friendid{$_->{'userid'}}; $body .= "$frlink, "; if (++$count == $MAX_FRIENDOF_SHOW && $GET{'mode'} ne "full") { $friendsof{'clipped'} = 1; last; } } chop $body; chop $body; $body .= ", ..." if $friendsof{'clipped'} || $friendsof{'load_clipped'}; $friendsof{'clipped'} = 0; # reset for @friend_of display $body .= "\n"; } if ($friendsof{'display'} && @friend_of) { $label = $com ? $ML{'.friendof.comm'} : ($u->{'opt_showmutualfriends'} ? $ML{'.label.alsofriendof'} : $ML{'.friendof.user'}); $body .= "$label"; if ($u->{'opt_hidefriendofs'}) { $body .= "
$ML{'.friendof.hidden'}"; } $body .= ""; my $plus = $friendsof{'load_clipped'} ? "+" : ""; $body .= "" . $friendsof{'count'} . "$plus: "; my $count = 0; foreach (@friend_of) { my $frlink; if ($_->{'journaltype'} eq "P") { $frlink = "{'user'}\">$_->{'user'}"; } elsif ($_->{'journaltype'} eq "I") { $frlink = "{'userid'}&t=I\">" . LJ::ehtml($_->{'name'}) . ""; } $frlink = "$frlink" if $remote_friendid{$_->{'userid'}}; $body .= "$frlink, "; if (++$count == $MAX_FRIENDOF_SHOW && $GET{'mode'} ne "full") { $friendsof{'clipped'} = 1; last; } } chop $body; chop $body; $body .= ", ..." if $friendsof{'clipped'} || $friendsof{'load_clipped'}; $body .= "\n"; }; if ($friendsof{'display'} && @member_of) { $label = $ML{'.label.memberof'}; $body .= "$label:"; my $plus = $friendsof{'load_clipped'} ? "+" : ""; $body .= "" . $friendsof{'count_m'} . "$plus: "; foreach (@member_of) { my $frlink = "$_->{'user'}"; $frlink = "$frlink" if $remote_friendid{$_->{'userid'}}; $body .= "$frlink, "; } chop $body; chop $body; $body .= "\n"; }; } # } else { # Syndication journals are special # $body .= "$ML{'.friendof.syndreadcount'}:"; # $body .= "$friendsof{'count'}\n"; # } ## extra rows generated by hooks foreach my $row (LJ::run_hooks("userinfo_rows", { 'dbr' => $dbr, 'u' => $u, 'remote' => $remote, })) { next unless $row->[0]; $body .= ""; $body .= $row->[0]; $body .=":"; $body .= $row->[1]; $body .= "\n"; } unless ($synd || $GET{'mode'} eq "full") { # Synd accts are always full, but their full ends early (see below) $body .= "\n"; $body .= "

$ML{'.label.moredetails'}

"; $bml_okay = 0; return; } ## ## interesting times ## $body .= "$ML{'.label.datecreated'}$u->{'timecreate'}"; $body .= "$ML{'.label.dateupdated'}"; if ($u->{'timeupdate'}) { $body .= "$u->{'timeupdate'}, "; my $secondsold = $u->{'secondsold'}; my $num; if ($secondsold > 60*60*24*7) { $num = int($secondsold / (60*60*24*7)); $body .= $num == 1 ? $ML{'.timeupdate.weekago'} : BML::ml('.timeupdate.weeksago',{'num'=>$num}); } elsif ($secondsold > 60*60*24) { $num = int($secondsold / (60*60*24)); $body .= $num == 1 ? $ML{'.timeupdate.dayago'} : BML::ml('.timeupdate.daysago',{'num'=>$num}); } elsif ($secondsold > 60*60) { $num = int($secondsold / (60*60)); $body .= $num == 1 ? $ML{'.timeupdate.hourago'} : BML::ml('.timeupdate.hoursago',{'num'=>$num}); } elsif ($secondsold > 60) { $num = int($secondsold / (60)); $body .= $num == 1 ? $ML{'.timeupdate.minuteago'} : BML::ml('.timeupdate.minutesago',{'num'=>$num}); } else { $num = $secondsold; $body .= $num == 1 ? $ML{'.timeupdate.secondago'} : BML::ml('.timeupdate.secondsago',{'num'=>$num}); } $body .= ""; } else { $body .= $ML{'.date.never'}; } $body .= ""; if ($synd) { # The rest of the rows are not useful to synd accts $body .= "\n"; $bml_okay = 0; return ""; } unless ($LJ::DISABLED{'userinfo_clientusage'}) { $body .= "" . BML::ml('.label.clientsused',{'siteroot'=>$LJ::SITEROOT}) . ""; $sth = $dbr->prepare("SELECT DISTINCT c.client FROM clients c, clientusage cu ". "WHERE cu.userid=$userid AND cu.clientid=c.clientid ORDER BY c.client"); $sth->execute; my $lastclient = ""; while ($_ = $sth->fetchrow_hashref) { next unless ($_->{'client'} =~ m!(.+)/(.+)!); my ($client, $ver) = ($1, $2); if ($lastclient ne $client) { if ($lastclient) { chop $body; chop $body; $body .= "
"; } else { 1; } $body .= "" . LJ::ehtml($client) .": "; $lastclient = $client; } $body .= LJ::ehtml($ver) . ", "; } if ($lastclient) { chop $body; chop $body; } $body .= ""; } # count journal entries { my $memkey = [$userid, "log2ct:$userid"]; my $count = LJ::MemCache::get($memkey); unless ($count) { my $expire = time() + 3600*24*2; # 2 days $count = $dbcr->selectrow_array("SELECT COUNT(*) FROM log2 WHERE journalid=?", undef, $userid); LJ::MemCache::set($memkey, $count, $expire); } $body .= "$ML{'.label.journalentrs'}" . "" . &comma($count) . ""; } my $points = $dbr->selectrow_array("SELECT SUM(points) AS 'points' FROM supportpoints WHERE userid=$userid"); if ($points) { $body .= "$ML{'.label.supportpoints'}:" . &comma($points) . ""; } sub comma { my $num = shift; if ($num =~ s/(\d)(\d\d\d)$/$1,$2/) { $num =~ s/(\d)(\d\d\d),/$1,$2/g; } return $num; } ## ## journal comments { my ($com_post, $com_got); unless ($LJ::DISABLED{'show-talkleft'}) { my $memkey = [$userid, "talkleftct:$userid"]; my $count = LJ::MemCache::get($memkey); unless ($count) { my $expire = time() + 3600*24*2; # 2 days $count = $dbcr->selectrow_array("SELECT COUNT(*) FROM talkleft " . "WHERE userid=?", undef, $userid); LJ::MemCache::set($memkey, $count, $expire) if defined $count; } $com_post = comma($count); $com_post = BML::ml('.label.composted', {'num'=>$com_post}); } my $memkey = [$userid, "talk2ct:$userid"]; my $count = LJ::MemCache::get($memkey); unless ($count) { my $expire = time() + 900; # 15 minutes; $count = $dbcr->selectrow_array("SELECT COUNT(*) FROM talk2 ". "WHERE journalid=?", undef, $userid); LJ::MemCache::set($memkey, $count, $expire) if defined $count; } $com_got = comma($count); $com_got = BML::ml('.label.comreceived', {'num'=>$com_got}); $body .= "$ML{'.label.comments'}$com_post" . $com_got . ""; } ### ### shared journal access ### { my $list; if ($com || $u->{'journaltype'} eq 'S') { # load user who can post to this community $list = LJ::load_rel_user($u, 'P'); } else { # load communities/accounts this user can post to $list = LJ::load_rel_target($u, 'P'); } my %u; my @ids = @$list; my $count = @ids; my $chopped = 0; my $CHOP_POINT = 500; unless ($fif) { if (@ids > $CHOP_POINT) { @ids = splice(@ids, 0, $CHOP_POINT); $chopped = 1; } } LJ::load_userids_multiple([ map { $_ => \$u{$_} } @ids ]); my @accesslist = sort { $a->{user} cmp $b->{user} } grep { $_->{statusvis} eq 'V' } values %u; if (my $vcount = @accesslist) { unless ($fif) { $count = $vcount if $count < $CHOP_POINT; } $body .= "$ML{'.label.shared'}$count: "; $body .= join(", ", map { "$_->{user}" } @accesslist); $body .= ", ..." if $chopped; $body .= ""; } } $body .= "\n"; # removed until we run graphviz locally # $body .= "

Graph of friends

"; $bml_okay = 0; return; _code?> title=> body=> head=> page?> lib: cgi-bin/ljlib.pl, cgi-bin/cleanhtml.pl link: htdocs/editinfo.bml, htdocs/userinfo.bml, htdocs/users link: htdocs/community/join.bml, htdocs/community/leave.bml, htdocs/friends/add.bml, htdocs/todo/index.bml link: htdocs/tools/memories.bml, htdocs/tools/tellafriend.bml, htdocs/allpics.bml link: htdocs/tools/textmessage.bml, htdocs/interests.bml, htdocs/support/faqbrowse.bml, htdocs/download/index.bml link: htdocs/support/index.bml img: img/btn_addfriend.gif, img/btn_todo.gif, img/btn_memories.gif, img/btn_tellfriend.gif, img/talk/md10_thumbup.gif, img/xml.gif hook: userinfo_html_by_user, userinfo_rows _c?>