<?_code
#line 2
 use strict;
 use vars qw($title $windowtitle $body $head $bml_okay %GET);

 $bml_okay = 1;
 $title = $ML{'.title'};
 $body = "";
 $head = "";
 $windowtitle = "";
 my $fif;

 # # Deal with bots
 # my $sep  = "**";
 # my $pre  = "<!-- \n" . ($sep x 40 . "\n") x 2 . "$sep\n" x 10 . $sep;
 # my $post = "\n" . "$sep\n" x 10 . ($sep x 40 . "\n") x 2 . " -->";
 # $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 = "<?h1 $ML{'Error'} h1?><?p $ML{'.error.notloggedin'} p?>";
     return;
 }

 my $sth;
 my %countries = ();
 my %states = ();
 LJ::load_codes({ "country" => \%countries, "state" => \%states });

 my $error = sub {
     my $e = shift;
     $body = "<?h1 $ML{'Error'} h1?><?p $e p?>";
     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 = "<?h1 $ML{'.nonexist.name'} h1?><?p " . BML::ml('.nonexist.body',{'user'=>$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 = "<?h1 $ML{'error.purged.name'} h1?><?p $ML{'error.purged.text'} p?>";
     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 = "<?h1 $ML{'error.suspended.name'} h1?><?p " .
                 BML::ml('error.suspended.text', { 'user' => 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 = "<?h1 $ML{'error.deleted.name'} h1?><?p " .
           BML::ml('error.deleted.text',{'user'=>$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 <head>
 my $digest = Digest::SHA1::sha1_hex('mailto:' . $u->{'email'});
 $head .= "<link rel='alternate' type='application/rss+xml' title='RSS' href='$LJ::SITEROOT/$dir/$user/data/rss' />\n";
 $head .= "<link rel='alternate' type='application/atom+xml' title='Atom' href='$LJ::SITEROOT/$dir/$user/data/atom' />\n";
 $head .= "<link rel='alternate' type='application/rdf+xml' title='FOAF' href='$LJ::SITEROOT/$dir/$user/data/foaf' />\n";
 $head .= "<meta name=\"foaf:maker\" content=\"foaf:mbox_sha1sum '$digest'\" />\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 <a href='/openid'>OpenID</a> 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, "<a href='/friends/add.bml?user=$user'><img src='$LJ::IMGPREFIX/btn_addfriend.gif' width='22' height='20' alt='$label' title='$label' align='middle' border='0' /></a>";
     }
     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, "<a href='/update.bml?usejournal=$user'><img src='$LJ::IMGPREFIX/btn_edit.gif' width='22' height='20' alt='$label' title='$label' align='middle' border='0' /></a>";
     }

     $label = $ML{'.label.todo'};
     push @linkele, "<a href='/todo/?user=$user'><img src='$LJ::IMGPREFIX/btn_todo.gif' width='22' height='20' alt='$label' title='$label' align='middle' border='0' /></a>" unless $extid;

     $label = $ML{'.label.memories'};
     push @linkele, "<a href='/tools/memories.bml?user=$user'><img src='$LJ::IMGPREFIX/btn_memories.gif' width='22' height='20' alt='$label' title='$label' align='middle' border='0' /></a>" unless $extid;

     unless ($LJ::DISABLED{'tellafriend'} || $extid) {
         push @linkele, "<a href='/tools/tellafriend.bml?user=$u->{'user'}'><img align='middle' hspace='2' vspace='2' src='$LJ::IMGPREFIX/btn_tellfriend.gif' width='22' height='20' alt='$ML{'.tellafriend'}' title='$ML{'.tellafriend'}' border='0' /></a>";
     }

     unless ($LJ::DISABLED{'feedster_search'} || $extid || $u->{'opt_blockrobots'}) {
         push @linkele, "<a href='/tools/search.bml?journal=$u->{'user'}'><img align='middle' hspace='2' vspace='2' src='$LJ::IMGPREFIX/btn_search.gif' width='22' height='20' alt='$ML{'.label.searchjournal'}' title='$ML{'.label.searchjournal'}' border='0' /></a>";
     }

     if (@linkele) {
         $body .= BML::fill_template("standout", { 
             DATA => join("&nbsp;&nbsp;", @linkele),
         });
     }
 }

 $body .= "<table cellpadding='5' width='100%' border='0'>";
 {
     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 .= "<tr valign='top'><td align='right'><b><a href=/import-faq.bml>Imported</a>:</b></td><td width='100%'>" . LJ::ljuser($u) . "</td>";
       }
       else {
         $body .= "<tr valign='top'><td align='right'><b>OpenID:</b></td><td width='100%'>" . LJ::ljuser($u) . "</td>";
       }
     } else {
         $body .= "<tr valign='top'><td align='right'><b>$ML{'.label.user'}</b></td><td width='100%'><a href='/$dir/$user/'><b>$user</b></a> ($u->{'userid'}) $hook_extra ";
         if ($u->{public_key}) {
             $body .= "<a href='/pubkey.bml?user=$user'>";
             $body .= "<img src='/img/key.gif' width='16' height='16' border='0' alt='View public key' title='View public key' style='vertical-align: middle; border: 0;' /></a>";
         }
         $body .= "</td>\n";
     }
 }
     
### picture

 my $narrow_left = 2;  ## rows with smaller colspan to 2 
 $body .= "<td align='right' rowspan='3'>";
 if ($u->{'defaultpicid'}) {
     my $picid = $u->{'defaultpicid'};
     my %pic;
     LJ::load_userpics(\%pic, [ $u, $picid ]);
     $body .= "<a href='/allpics.bml?user=$user'><img src='$LJ::USERPIC_ROOT/$picid/$userid' width='$pic{$picid}->{'width'}' height='$pic{$picid}->{'height'}' vspace='3' border='0' alt='$user' /></a>";
 } else {
     $body .= "&nbsp;";
 }
 $body .= "</td>";
### /picture

 $body .= "</tr>\n";

 ## journal title
if ($u->{'journaltitle'}) {
    my $span = ($narrow_left-- >= 0) ? 1 : 2;
    $body .= "<tr valign='top'><td align='right'></td><td colspan='$span'>";
    $body .= "<span style='font-size: 1.2em'><b>" . LJ::ehtml($u->{'journaltitle'}) . "</b>";
    if ($u->{'journalsubtitle'}) {
        $body .= "<br /><i>" . LJ::ehtml($u->{'journalsubtitle'}) . "</i>";
    }
    $body .= "</span></td></tr>\n";
}


 ### name or 'syndicated from'
 unless ($synd) {
     unless ($u->underage || $u->{'name'} eq $u->{'journaltitle'}) {
         $narrow_left--;
         $body .= "<tr><td align='right'><b>$ML{'.label.name'}</b></td><td>$u->{'name'}</td></tr>\n";
     }
 } else {
     $narrow_left--;
     my $link;
     if (my $url = $u->{'url'}) {
         $link="<a href='" . LJ::ehtml($url) . "'>$u->{'name'}</a>";
     } else {
         $link=$u->{'name'};
     }
     my $icon="<a href='" . LJ::ehtml($synd->{'synurl'}) . "'>".
              "<img src='$LJ::IMGPREFIX/xml.gif' width='36' height='14' align='middle' border='0' /></a>";
     $body .= "<tr valign='top'><td align='right'><b>$ML{'.label.syndicatedfrom'}</b></td>\n".
              "<td>$link $icon</td></tr>\n";

     # syndication status
     $body .= "<tr valign='top'><td align='right'><b>$ML{'.label.syndicatedstatus'}</b></td><td>\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 .= "<br />$ML{'.syn.parseerror'} " . LJ::ehtml($u->{'rssparseerror'});
     }

     $body .= "<br />$ML{'.syn.nextcheck'} $synd->{'checknext'}";
     $body .= "</td></tr>\n";
     
 }

 ## text message
 if ($u->{'txtmsg_status'} eq "on" && LJ::get_cap($u, "textmessaging")) {
     my $span = ($narrow_left-- >= 0) ? 1 : 2;
     $body .= "<tr valign='top'><td align='right'><b>$ML{'.label.textmessage'}</b></td><td colspan='$span'>" . BML::ml('.sendmessage.body',{'user'=>$u->{'user'}, 'link'=>"/tools/textmessage.bml?user=$u->{'user'}"}) . "</td></tr>";
 }
 
 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 = "<a href='$url'>$urlname</a>";
     $body .= "<tr><td align='right'><b>$ML{'.label.website'}</b></td><td colspan='$span'>$url</td></tr>\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 .= "<tr><td align='right'><b>$ML{'.label.location'}</b></td><td colspan='$span'>";
          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'}} :
                  "<a href='/directory.bml?opt_sort=ut&amp;s_loc=1&amp;loc_cn=$u->{'country'}'>".
                      $countries{$u->{'country'}} . "</a>";
          }
	  
          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 :
                  "<a href='/directory.bml?opt_sort=ut&amp;s_loc=1&amp;loc_cn=".
                      "$u->{'country'}&amp;loc_st=$estate'>$state</a>";
          }

          if ($u->{'city'}) {
              my $ecity = LJ::eurl($u->{'city'});
              $city = LJ::ehtml($u->{'city'});
              if (! $LJ::DISABLED{'directory'} && $u->{'country'}) {
                  $city = "<a href='/directory.bml?opt_sort=ut&amp;s_loc=1&amp;loc_cn=".
                      "$u->{'country'}&amp;loc_st=$estate&amp;loc_ci=$ecity'>$city</a>";
              }
          }

          $body .= join(", ", grep { $_ } ($city, $state, $country));
          $body .= "</td></tr>";
      }

      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 .= "<tr><td align='right'><b>$ML{'.label.birthdate'}</b></td><td colspan='$span'>$bdate</td></tr>\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 = "<table cellpadding='0' cellspacing='0'><tr><td>";
          for (my $i = 0; $i < length($email); $i++) {
              my $letter = substr($email, $i, 1);
              if ($letter eq "\@") { $letter = "</td><td align='center'><i>\@</i></td><td>"; }
              $mret .= $letter;
          }
          $mret .= "</td></tr></table>";
          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 .= "<tr valign='top'><td align='right'><b>$ML{'.label.email'}</b></td><td colspan='$span'>";
          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)
                        : "<a href='mailto:$email'>$email</a><br />";
          }
          $body .= "</td></tr>";
      }
      
      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 .= "<tr><td align='right'><b style='white-space: nowrap;'>$ML{'.label.aolim'}</b></td><td colspan='$span'><img alt='AIM status' src='http://big.oscar.aol.com/$qim?on_url=http://www.aol.com/aim/gr/online.gif&amp;off_url=http://www.aol.com/aim/gr/offline.gif' height='17' width='14' /> $u->{'aolim'} (<b><a href='aim:addbuddy?screenname=$qim'>$ML{'.label.addbuddy'}</a>, <a href='aim:goim?screenname=$qim&amp;message=Hello+there!+How+are+you?'>$ML{'.label.sendmessage'}</a></b>)</td></tr>\n";
      }
      if ($u->{'icq'}) {
          my $span = ($narrow_left-- >= 0) ? 1 : 2;
          $body .= "<tr><td align='right'><b>$ML{'.label.icquin'}</b></td>";
          $body .= "<td colspan='$span'><img alt='ICQ status' src='http://web.icq.com/whitepages/online?icq=$u->{'icq'}&amp;img=5' height='18' width='18' /> ";
          $body .= "$u->{'icq'} (<b><a href='http://wwp.icq.com/$u->{'icq'}'>";
          $body .= "$ML{'.label.userprofile'}</a></b>)";
          $body .= "</td></tr>\n";
      }
      if ($u->{'yahoo'}) {
          my $span = ($narrow_left-- >= 0) ? 1 : 2;
          $body .= "<tr><td align='right'><b style='white-space: nowrap;'>$ML{'.label.yahooid'}</b></td><td colspan='$span'><img alt='Yahoo status' src='http://opi.yahoo.com/online?u=$u->{'yahoo'}&amp;m=g&amp;t=0' width='12' height='12' /> <a href='http://profiles.yahoo.com/$u->{'yahoo'}'>$u->{'yahoo'}</a> (<b><a href='http://edit.yahoo.com/config/set_buddygrp?.src=&amp;.cmd=a&amp;.bg=Friends&amp;.bdl=$u->{'yahoo'}'>$ML{'.label.adduser'}</a>, <a href='http://edit.yahoo.com/config/send_webmesg?.target=$u->{'yahoo'}'>$ML{'.label.sendmessage'}</a></b>) </td></tr>\n";
      }
      if ($u->{'msn'}) {
          my $span = ($narrow_left-- >= 0) ? 1 : 2;
          my $msnname = ($u->{'opt_mangleemail'} eq "Y") ? $mangleaddress->($u->{'msn'}) : $u->{'msn'};
          $body .= "<tr><td align='right'><b>$ML{'.label.msnusername'}</b></td><td colspan='$span'>$msnname</td></tr>\n";
      }
      if ($u->{'jabber'}) {
          my $span = ($narrow_left-- >= 0) ? 1 : 2;
          my $jabber = $mangleaddress->($u->{'jabber'});
          $body .= "<tr><td align='right'><b>$ML{'.label.jabber'}</b></td><td colspan='$span'>$jabber</td></tr>\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 .= "<tr><td align='right' valign='top'><b>$label</b></td><td colspan='$span'>$u->{'bio'}</td></tr>\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 .= "<tr><td align='right' valign='top'><b>$ML{'.label.memories'}</b></td><td colspan='$span'><a href='/tools/memories.bml?user=$user'>$count</a></td></tr>\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 .= "<tr><td align='right' valign='top'><b>$ML{'.label.fbpictures'}</b></td><td colspan='$span'><a href='$LJ::FB_SITEROOT/$user/'>$ct_str</a></td></tr>\n";
     }
 }

 if (@$intu) {
     my $span = ($narrow_left-- > 0) ? 1 : 2;
     $body .= "<tr><td align='right' valign='top'><b><a href='/interests.bml'>$ML{'.label.interests'}</a>:</b></td><td colspan='$span'>";
     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 .= "<b><a href='/interests.bml?int=$eint'>$int->[1]</a></b>, ";
             } else {
                 $intlist .= "<a href='/interests.bml?int=$eint'>$int->[1]</a>, ";
             }
         } 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 .= "<b>$intcount:</b> " . $intlist;
     if ($remote) {
         my $link = "/interests.bml?mode=enmasse";
         $link .= "&fromuser=$user" unless ($remote->{'userid'} == $userid);
         $body .= ". <small>";
         my $mlcode = ($remote->{'userid'} == $userid) ? '.label.interests.removesome'
                                                       : '.label.interests.modifyyours';
         $body .= BML::ml('Actionlink', { 'link' => "<a href='$link'>$ML{$mlcode}</a>" });
         $body .= "</a></small>";
     }
     $body .= "</td></tr>";
 }
 
 ##
 ## 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 .= "<tr><td align='right' valign='top'><b><a href='$LJ::SITEROOT/$dir/$user/friends'>$label</a>:</b></td><td colspan='$span'>";

     unless ($fif) {$friends{'display'} = 0 if $friends{'count'} > $MAX_FRIENDS_SHOW;}
     if ($friends{'count'}) {
         if (!$friends{'loaded'} || !$friends{'display'}) {
             $body .= "<b>" . $friends{'count'} . ":</b> ";
             $body .= "<a href='/directory.bml?s_fro=1&amp;fro_user=$u->{'user'}'> " . ($com ? $ML{'.label.viewmembers'} : $ML{'.label.viewfriends'}) .  " </a>.";
         } 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 = "<a href='/userinfo.bml?user=$f->{'user'}'>$f->{'user'}</a>";
                 $frlink = "<strike>$frlink</strike>" if $status =~ /[DXS]/;
                 $frlink = "<b>$frlink</b>" 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 .= "<table>";
             if ($pfriends) {
                 my $text = LJ::ehtml($ML{'.label.frpeople'});
                 $body .= "<tr><td style='text-align: center;font-weight:bold' nowrap valign='top'>" .
                          "<img src='$LJ::IMGPREFIX/userinfo.gif' title='$text' alt='$text' border='0' align='top' /></td>" .
                          "<td style='text-align: left;font-weight:bold' nowrap valign='top'>$pcount:</td>".
                          "<td>$pfriends</td>";
             }
             if ($cfriends) {
                 my $text = LJ::ehtml($ML{'.label.frcommunity'});
                 $body .= "<tr><td style='text-align: center;font-weight:bold' nowrap valign='top'>" .
                          "<img src='$LJ::IMGPREFIX/community.gif' title='$text' alt='$text' border='0' align='top' /></td>" .
                          "<td style='text-align: left;font-weight:bold' nowrap valign='top'>$ccount:</td>" .
                          "<td>$cfriends</td>";
             }
             if ($yfriends) {
                 my $text = LJ::ehtml($ML{'.label.frsyndication2'});
                 $body .= "<tr><td style='text-align: center;font-weight:bold' nowrap valign='top'>" .
                          "<img src='$LJ::IMGPREFIX/syndicated.gif' title='$text' alt='$text' border='0' align='top' /></td>" .
                          "<td style='text-align: left;font-weight:bold' nowrap valign='top'>$ycount:</td>" .
                          "<td>$yfriends</td>";
             }
             $body .= "</tr></table>";
         } else {
             $body .= "<b>" . $friends{'count'} . ":</b> ";
             foreach my $f (@friends) {
                 my $status = $f->{'statusvis'};
                 my $frlink = "<a href='/userinfo.bml?user=$f->{'user'}'>$f->{'user'}</a>";
                 $frlink = "<strike>$frlink</strike>" if $status =~ /[DXS]/;
                 $frlink = "<b>$frlink</b>" if $remote_friendid{$f->{'userid'}} && $remote->{'userid'} != $u->{'userid'};
                 $body .= $frlink;
                 $body .= ", ";
             }
             chop $body; chop $body;
         }
     } else {
         $body .= $ML{'.label.nofriends'};
     }
     $body .= "</td></tr>\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 .= "<tr><td align='right' valign='top'><b style='white-space: nowrap;'>$label</b>";
             $body .= "</td>";

             my $plus = $friendsof{'load_clipped'} ? "+" : "";
             $body .= "<td colspan='2' valign='top'><b>" . $friendsof{'count_b'} . "$plus:</b> ";
             my $count = 0;
             my $bold_mutual = ! LJ::u_equals($remote, $u);
             foreach (@mutual) {
                 my $frlink = "<a href=\"/userinfo.bml?user=$_->{'user'}\">$_->{'user'}</a>";
                 $frlink = "<b>$frlink</b>" 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 .= "</td></tr>\n";
         }
         if ($friendsof{'display'} && @friend_of) {
             $label = $com ? $ML{'.friendof.comm'} : 
                      ($u->{'opt_showmutualfriends'} ? $ML{'.label.alsofriendof'} : $ML{'.friendof.user'});
             $body .= "<tr><td align='right' valign='top'><b style='white-space: nowrap;'>$label</b>";
             if ($u->{'opt_hidefriendofs'}) {
                 $body  .= "<br /><i>$ML{'.friendof.hidden'}</i>";
             }
             $body .= "</td>";

             my $plus = $friendsof{'load_clipped'} ? "+" : "";
             $body .= "<td colspan='2' valign='top'><b>" . $friendsof{'count'} . "$plus:</b> ";
             my $count = 0;
             foreach (@friend_of) {
                 my $frlink;
                 if ($_->{'journaltype'} eq "P") {
                     $frlink = "<a href=\"/userinfo.bml?user=$_->{'user'}\">$_->{'user'}</a>";
                 } elsif ($_->{'journaltype'} eq "I") {
                     $frlink = "<a href=\"/userinfo.bml?userid=$_->{'userid'}&amp;t=I\">" . LJ::ehtml($_->{'name'}) . "</a>";
                 }
                 $frlink = "<b>$frlink</b>" 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 .= "</td></tr>\n";
         };
         if ($friendsof{'display'} && @member_of) {
             $label = $ML{'.label.memberof'};
             $body .= "<tr><td align='right' valign='top'><b style='white-space: nowrap;'>$label:</b></td><td colspan='2'>";
             my $plus = $friendsof{'load_clipped'} ? "+" : "";
             $body .= "<b>" . $friendsof{'count_m'} . "$plus:</b> ";
             foreach (@member_of) {
                 my $frlink = "<a href='/userinfo.bml?user=$_->{'user'}'>$_->{'user'}</a>";
                 $frlink = "<b>$frlink</b>" if $remote_friendid{$_->{'userid'}};
                 $body .= "$frlink, ";
             }
             chop $body; chop $body;
             $body .= "</td></tr>\n";
         };
     }
# } else {  # Syndication journals are special
#     $body .= "<tr><td align='right' valign='top'><b style='white-space: nowrap;'>$ML{'.friendof.syndreadcount'}:</b></td>";
#     $body .= "<td colspan='2'><i>$friendsof{'count'}</i></td></tr>\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 .= "<tr><td align='right' valign='top'><b style='white-space: nowrap;'>";
     $body .= $row->[0];
     $body .=":</b></td><td colspan='2'>";
     $body .= $row->[1];
     $body .= "</td></tr>\n";
 }
 
 unless ($synd || $GET{'mode'} eq "full") {  # Synd accts are always full, but their full ends early (see below)
     $body .= "</table>\n";
     $body .= "<p align='center'><i><a href='/userinfo.bml?user=$u->{'user'}&amp;mode=full'>$ML{'.label.moredetails'}</a></i></p>";
     $bml_okay = 0;
     return;
 }
 

 ##
 ## interesting times
 ##
 $body .= "<tr><td align='right' nowrap='nowrap'><b>$ML{'.label.datecreated'}</b></td><td colspan='2'>$u->{'timecreate'}</td></tr>";
 $body .= "<tr><td align='right' nowrap='nowrap'><b>$ML{'.label.dateupdated'}</b></td><td colspan='2'>";
 if ($u->{'timeupdate'}) {
     $body .= "$u->{'timeupdate'}, <i>";
     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 .= "</i>";
 } else {
     $body .= $ML{'.date.never'};
 }
 $body .= "</td></tr>";

 if ($synd) { # The rest of the rows are not useful to synd accts
     $body .= "</table>\n";
     $bml_okay = 0;
     return "";
 }

 unless ($LJ::DISABLED{'userinfo_clientusage'}) {
     $body .= "<tr><td align='right' valign='top'><b>" . BML::ml('.label.clientsused',{'siteroot'=>$LJ::SITEROOT}) . "</b></td><td colspan='2'>";
     $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 .= "<br />"; }
             else { 1; }
             $body .= "<b>" . LJ::ehtml($client) ."</b>: ";
             $lastclient = $client;
         }
         $body .= LJ::ehtml($ver) . ", ";
     }
     if ($lastclient) { chop $body; chop $body; }
     $body .= "</td></tr>";
 }

 # 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 .= "<tr><td align='right' nowrap='nowrap'><b>$ML{'.label.journalentrs'}</b></td>" .
         "<td colspan='2'>" . &comma($count) . "</td></tr>";
 }
 
 my $points = $dbr->selectrow_array("SELECT SUM(points) AS 'points' FROM supportpoints WHERE userid=$userid");
 if ($points) {
     $body .= "<tr><td align='right' nowrap='nowrap'><b><a href='/support/'>$ML{'.label.supportpoints'}</a>:</b></td><td colspan='2'>" . &comma($points) . "</td></tr>";
 }
 
 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 .= "<tr><td align='right'><b>$ML{'.label.comments'}</b></td><td colspan='2'>$com_post" .
         $com_got . "</td></tr>";
 }

###
### 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 .= "<tr valign='top'><td align='right'><b>$ML{'.label.shared'}</b></td><td colspan='2'><b>$count</b>: ";
        $body .= join(", ", map { "<a href='userinfo.bml?user=$_->{user}'>$_->{user}</a>" } @accesslist);
        $body .= ", ..." if $chopped;
        $body .= "</td></tr>";
    }
}

$body .= "</table>\n";

# removed until we run graphviz locally
# $body .= "<p><a href=\"/friends/graph.bml?user=$user\"><b>Graph of friends</b></a></p>";

$bml_okay = 0;
return;

_code?><?page
windowtitle=><?_code return $windowtitle; _code?>
title=><?_code return $title; _code?>
body=><?_code return $bml_okay ? $body : BML::noparse($body); _code?>
head=><?_code return $head; _code?>
page?><?_c <LJDEP>
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
</LJDEP> _c?>
