LJSUP-17669: Login.bml form refactoring
[livejournal.git] / htdocs / userinfo.bml
blob3b51d28bee88e0f636ffb40d76e5e59183bce7b4
1 <?_code
3     use strict;
4     use LJ::TimeUtil;
5     use LJ::PersonalStats::DB;
6     use LJ::Setting::Music;
7     use LJ::Setting::Music::Trava;
9     use vars qw($title $windowtitle $body $head $bml_okay %GET);
11     BML::set_language_scope('/userinfo.bml');
13     LJ::Request->notes("codepath" => "bml.userinfo");
15     $bml_okay = 1;
16     $title = $ML{'.title'};
17     $body = "";
18     $head = "";
19     $windowtitle = "";
21     # Initialize some javascript variables
22     my $authtoken = LJ::Auth->ajax_auth_token(LJ::get_remote(), "/_widget");
23     $authtoken = LJ::ejs($authtoken);
24     $body .= "<script>";
25     $body .= "Aliases.authToken = \"$authtoken\";";
26 #    $body .= "AddAlias.link = \$('vg_cat_" . $get->{cat} . "');" if ($get->{cat});
27     $body .= "</script>";
29     # Deal with bots
30     my $sep  = "**";
31     my $pre  = "<!-- \n" . ($sep x 40 . "\n") x 2 . "$sep\n" x 10 . $sep;
32     my $post = "\n" . "$sep\n" x 10 . ($sep x 40 . "\n") x 2 . " -->";
33     $body .= LJ::run_hook("bot_director", $pre, $post);
35     if ($LJ::SERVER_DOWN) {
36         $title = $ML{'Sorry'};
37         $body = LJ::server_down_html();
38         return;
39     }
41     # if new-style URLs, get the GET{user} arg from the request notes,
42     # which was set by LiveJournal.pm
43     unless ($GET{'user'}) {
44         $GET{'user'} = LJ::Request->notes("_journal");
45     }
47     my $remote = LJ::get_remote();
48     if ($GET{'user'} eq "" && $GET{'userid'} eq "" && !$remote) {
49         $body = "<?needlogin?>";
50         return;
51     }
53     my $sth;
54     my %countries = ();
55     LJ::load_codes({ "country" => \%countries});
57     my $error = sub {
58         my $e = shift;
59         $body = "<?h1 $ML{'Error'} h1?><?p $e p?>";
60         return;
61     };
63     my $user = LJ::canonical_username($GET{'user'});
64     if ($GET{'user'} && ! $user) {
65         $body = $ML{'.error.malfname'};
66         return;
67     }
68     if ($user eq "" && $remote) {
69         $user = $remote->{'user'};
70     }
72     my $dbr = LJ::get_db_reader();
73     return $error->($ML{'error.nodb'}) unless $dbr;
75     my $userid = $GET{'userid'};
76     my $u;
77     $userid += 0;
79     {
80         if ($userid) {
81             $u = LJ::load_userid($userid);
82         } else {
83             $u = LJ::load_user($user);
84         }
86         return $error->($ML{'.label.reqfinduser'})
87             if $userid && ! LJ::check_priv($remote, "finduser") && ! ($GET{t} eq "I" && $u && $u->{journaltype} eq "I");
89         # fix accidentally broken ext_nnnn URLs for identity users
90         if ($u && $u->{journaltype} eq "I" && ! $userid) {
91             return BML::redirect("$LJ::SITEROOT/userinfo.bml?userid=$u->{'userid'}&t=I");
92         }
94         $user = $u->{'user'} if $u;
95         $userid = $u->{'userid'}+0 if $u;
97         LJ::text_out(\$u->{'name'}) if $u;
98         if ($u) {
99             $u->{'timeupdate'} = $u->timeupdate;
100             $u->{'timecreate'} = $u->timecreate;
101             $u->{'secondsold'} = time() - $u->{'timeupdate'};
102         }
103     }
105     unless ($u) {
106         LJ::Request->pnotes ('error' => 'baduser');
107         LJ::Request->pnotes ('remote' => LJ::get_remote());
108         BML::return_error_status(404);
109         $title = $ML{'Error'};
110         $body = "<?h1 $ML{'.nonexist.name'} h1?><?p " . BML::ml('.nonexist.body',{'user'=>$user}) . " p?>";
111         return;
112     }
114     LJ::set_active_journal($u);
116     my $remote_isowner = $remote && $remote->{'user'} eq $u->{'user'};
118     # account purged?
119     if ($u->is_expunged) {
120         LJ::Request->pnotes ('error' => 'expunged');
121         LJ::Request->pnotes ('remote' => LJ::get_remote());
122         BML::return_error_status(410);
123         return;
124     }
126     my $domain = BML::get_client_header("Host");
127     if ($LJ::ONLY_USER_VHOSTS && $u->{journaltype} ne "I") {
128         my $url = $u->journal_base . "/profile";
129         $url .= '?mode=full' if $GET{mode};
131         my $good_domain = $url;
132         $good_domain =~ s!^http://!!;
133         $good_domain =~ s!/.*!!;
134         if ($domain ne $good_domain) {
135             return BML::redirect($url);
136         }
137     }
139     my $dbcr = LJ::get_cluster_reader($u);
140     return $error->($ML{'error.nodb'}) unless $dbcr;
142     # make the profilepage model for this user.  this is the data
143     # provider for all the tricky stuff like
144     # friends/of/mutual/sorting/etc.  all the data loading/caching logic
145     # that shouldn't be in a BML page.
146     my $pm = LJ::M::ProfilePage->new($u);
148     my $remote_isfriend = LJ::is_friend($u, $remote);
149     my $com   = $u->{'journaltype'} eq "C" ? 1 : 0;
150     my $extid = $u->{'journaltype'} eq "I" ? $u->identity : undef;
152     my $synd;
153     if ($u->{'journaltype'} eq "Y") {
154         $synd = $u->get_syndicated;
155     }
157     if (!$u->is_visible || $u->should_block_robots) {
158         $head .= LJ::robot_meta_tags();
159     }
161     if ($u->{'journaltype'} eq "R" && $u->{'renamedto'}) {
162         my $extra = $GET{'mode'} eq 'full' ? "&mode=full" : '';
163         return BML::redirect("$LJ::SITEROOT/userinfo.bml?user=$u->{'renamedto'}$extra");
164     }
166     my %friends = ('load'=>1, 'loaded'=>0, 'display'=>1, 'count' => 0);
167     my %friendsof = ('load'=>1, 'loaded'=>0, 'display'=>1);
169     if ($com) {
170         $title = $ML{'.title.communityprofile'};
171     } elsif ($u->is_person) {
172         $title = $ML{'.title.userprofile'};
173     } elsif ($synd) {
174         $title = $ML{'.title.syndicatedprofile'};
175         $u->{'opt_whatemailshow'} = "N";  # don't show email
176         $friends{'load'} = $friends{'display'} = 0;
177     } elsif ($extid) {
178         $title = $extid->profile_window_title($u);
179     }
181     $windowtitle = $u->display_name . " - $title";
183     $friends{'load'} = $friendsof{'load'} = 0 if $com && $u->prop('dont_load_members');
185     # do they have the viewall priv?
186     # there are no entries on this page, so we just check if they have any viewall, so viewsome
187     # applies here too.  we can't see info they've hidden anyway, but we can see the page.
188     my $viewall = 0;
189     if ($GET{'viewall'} && LJ::check_priv($remote, "canview", "suspended")) {
190       $viewall = LJ::check_priv($remote, 'canview', '*');
191       LJ::statushistory_add($u->{'userid'}, $remote->{'userid'},
192                             "viewall", "userinfo: $u->{'user'}, statusvis: " . $u->statusvis);
193     } else {
195         if ($u->is_suspended) {
196             LJ::Request->pnotes ('error' => 'suspended');
197             LJ::Request->pnotes ('remote' => LJ::get_remote());
198             BML::return_error_status(403);
199             return;
200         }
201         if ($u->is_deleted) {
202             LJ::Request->pnotes ('error' => 'deleted');
203             LJ::Request->pnotes ('remote' => LJ::get_remote());
204             BML::return_error_status(404);
205             return;
206         }
207     }
209     $user = $u->{'user'};
210     $userid = $u->{'userid'};
212     $u->{'bio'} = LJ::get_bio($u);
213     LJ::text_out(\$u->{'bio'});
215     # arrayref of interests rows:  [ intid, intname, intcount ]
216     my $intu = LJ::get_interests($u);
218     my %remote_interest;
219     if ($remote && $remote->{'userid'} != $userid) {
220         if (my $rint = LJ::get_interests($remote, { justids => 1 })) {
221             $remote_interest{$_} = 1 foreach @$rint;
222         }
223     }
225     if ($u->{'opt_hidefriendofs'} && ! $pm->remote_isowner) {
226         # at this point, load should be on if viewall is on or if the user
227         # wants to show their mutual friends
228         $friendsof{'load'} = $u->show_mutualfriends || $viewall;
229         $friendsof{'display'} = $viewall;
230     }
232     my $jbase = $u->journal_base;
234     # Add metadata links to <head>
235     $head .= $pm->head_meta_tags;
237     my $app_store_meta = "";
238     $head .= LJ::run_hooks ("s2_head_content_extra_2", \$app_store_meta, $u, LJ::Request::request());
240     my @friends;    # ($u, $u, $u,....)  truncated to max_friends_show
241     my %is_friend;  # uid -> 1  (not truncated)
243     # TAG:FR:userinfo:loadfriends
244     if ($friends{'load'}) {
245         my @ids = $u->friend_uids;
246         $friends{'count'} = @ids;
247         $is_friend{$_} = 1 foreach @ids;
248         if (@ids > $pm->max_friends_show) {
249             @ids = splice(@ids, 0, $pm->max_friends_show);
250         }
251         my %fr;
252         LJ::load_userids_multiple([ map { $_ => \$fr{$_} } @ids ]);
253         push @friends, sort { $a->display_name cmp $b->display_name } grep {$_} values %fr;
254         $friends{'loaded'} = 1;
255     }
257     # TAG:FR:userinfo:loadfriendofs
258     use LJ::M::FriendsOf;
259     my $fro_m = LJ::M::FriendsOf->new($u,
260                                       sloppy => 1, # approximate if no summary info
261                                       mutuals_separate => $u->show_mutualfriends,
262                                       # TODO: lame that we have to pass this in, but currently
263                                       # it's not cached on the $u singleton
264                                       friends => \%is_friend,
265                                       hide_test_cb => sub {
266                                           return $pm->should_hide_friendof($_[0]);
267                                       },
268                                       );
270     # FIXME: can continue cleaning this stuff away.  might have callers later.
271     if ($friendsof{'load'}) {
272         $friendsof{'loaded'} = 1;
273     }
275     $u->{'name'} = LJ::ehtml($u->{'name'});
277     # TAG:FR:userinfo:remotefriends
278     # who does the remote user list as a friend?
279     my %remote_friendid;
280     if ($remote && $friends{'loaded'}) {
281         if ($remote->{'userid'} == $u->{'userid'}) {
282             foreach (@friends) { $remote_friendid{$_->{'userid'}} = 1; }
283         } else {
284             my $frs = LJ::get_friends($remote) || {};
285             $remote_friendid{$_} = 1 while $_ = each %$frs;
286         }
287     }
289     # BML helpers.  we do BML by hand in this page, so we don't force BML
290     # to evaluate this huge page looking for non-existent BML.  this
291     # makes it quicker, and prevents us from having to clean out BML in
292     # the HTML cleaner too.
293     my $h1 = sub {
294         return BML::fill_template("h1", { DATA => $_[0] });
295     };
296     my $p = sub {
297         return BML::fill_template("p", { DATA => $_[0] });
298     };
300     # Subs
301     # returns if user is in an "invisible" state (deleted/suspended)
302     my $is_invisible = sub {
303         my $user = shift() or return 1;
304         return 1 if $user->is_deleted || $user->is_expunged || $user->is_suspended;
305         return 0;
306     };
308     # returns whether or not to show deleted, expunged and suspended users
309     my $show_user = sub {
310         my $user = shift() or return 0;
311         return 1;
312     };
314     # Prints out a list of users with links to their
315     # userinfo pages. Apply strikethru and bolding
316     # for deleted journals and friends of user.
317     # As of 09/22/07 this is only used for printing
318     # maints, mods, and members of communities. - DR
319     my $listusers = sub {
320         my $users = shift;
321         my $type = shift; # Currently maint, mod, or member
322         my $ret;
323         my $dochop = 0;
324         foreach my $f (@$users) {
325             next unless $show_user->($f);
327             # XFN relationships
328             my $rel = '';
329             if ($type eq 'member') {
330                 $rel = " rel='member'";
331             }
333             my $uilink = "<a href='" . $f->profile_url . "'$rel>" . $f->display_name . "</a>";
334             $uilink = "<strike>$uilink</strike>" if $is_invisible->($f);
335             $uilink = "<b>$uilink</b>" if $remote_friendid{$f->{'userid'}} &&
336                 $remote->{'userid'} != $u->{'userid'};
337             $ret .= $uilink;
338             $ret .= ', ';
339             $dochop = 1;
340         }
342         # remove trailing ", " if needed
343         if ($dochop) {
344             chop $ret; chop $ret;
345         }
346         return $ret;
347     };
349     my $arrowimg = sub {
350         my $section = shift;
351         return "<img id='${section}_arrow' src='$LJ::IMGPREFIX/profile_icons/arrow-down.gif?v=14408' align='absmiddle' alt='' />";
352     };
353     # End Subs
355     $body .= "<div id='profile_page'>";
357     my $url = LJ::Request->uri();
358     # Page version switcher
359     if (LJ::is_enabled('profile_controller') && $remote) {
360         $body .= "<form class='b-profile-switchver' method='POST'><button class='b-profile-switchver-button' type='submit' name='new_version' value='1' ><span class='b-profile-switchver-inner'>".LJ::Lang::ml('profile.switch.to.new.version')."</span></button> " .LJ::Lang::ml('profile.switch.to.version.post'). "</form>";
361         if (LJ::did_post() && LJ::Request->post_param('new_version')) {
362             $remote->set_prop('profile_ver', 2);
363             return LJ::Request->redirect($u->profile_url(), LJ::Request::HTTP_MOVED_TEMPORARILY);
364         }
365     }
367     if ($com) {
368         my $pt;
369         my $userinfo_join_community;
370         LJ::run_hooks("userinfo_join_community", {
371             'u' => $u,
372             'ret' => \$userinfo_join_community,
373         });
374         $pt .= $userinfo_join_community if ($userinfo_join_community);
375         $body .= $p->($pt);
376     }
378     $body .= "<div id='profile_top'>";
380     ### Box Ad
381     my $boxad = LJ::get_ads({ location => 'bml.userinfo', journalu => $u }) .
382                 LJ::get_ads({ location => 'bml.userinfo.sponsored', journalu => $u });
384     if ($boxad) {
385         $body .= "<div class='profile_right_ad'>";
386         $body .= $boxad;
387         $body .= "</div>";
388     }
390     ### Username
391     my $new_margin = $boxad ? " style='margin-right: 320px;'" : '';
392     my $user_alias = LJ::ljuser_alias($u->{user}, {side_alias => 1});
393     my $user_alias_sp;
394     $user_alias_sp = "<span class='alias-value'> &mdash; ".LJ::ehtml($user_alias)."</span>" if $user_alias;
395     $body .= "<div class='username'$new_margin>" . $u->ljuser_display({side_alias => 1});
396     if ($u->{public_key}) {
397         $body .= " <a href='$LJ::SITEROOT/pubkey.bml?user=$user'>";
398         $body .= "<img src='$LJ::IMGPREFIX/key.gif?v=6803' width='16' height='16' border='0' alt=\"$ML{'.pubkey.alt'}\" title=\"$ML{'.pubkey.alt'}\" style='vertical-align: middle; border: 0;' /></a>";
399     }
400     $body .= "</div>";
402     ### Action Links
403     $body .= "<div class='actions'>";
404     $body .= "<ul>";
406     my ($url, $text, $li_title);
408     # join/leave community
409     if ($u->is_community) {
410         if ($remote && $u->has_friend($remote)) {
411             $url = "$LJ::SITEROOT/community/leave.bml?comm=$user";
412             $text = $ML{'.optionlinks.leavecomm'};
413             $li_title = $ML{'.optionlinks.leavecomm.title'};
414             $body .= "<li class='profile_leave' title=\"$li_title\"><a href='$url'><img src='$LJ::IMGPREFIX/profile_icons/leave-comm.gif?v=14658' alt='' />$text</a></li>";
415         } else {
416             my @comm_settings = LJ::get_comm_settings($u);
418             $url = "$LJ::SITEROOT/community/join.bml?comm=$user";
419             $text = $ML{'.optionlinks.joincomm'};
420             if ($comm_settings[0] eq "closed" || !$remote || !$u->is_visible) {
421                 $li_title = $comm_settings[0] eq "closed" ? $ML{'.optionlinks.joincomm.title.closed'} : $ML{'.optionlinks.joincomm.title.loggedout'};
422                 $li_title = $ML{'.optionlinks.joincomm.title.cantjoin'} if $remote && $remote->is_identity;
423                 $body .= "<li class='profile_join_disabled' title=\"$li_title\"><img src='$LJ::IMGPREFIX/profile_icons/join-comm-disabled.gif?v=14658' alt='' />$text</li>";
424             } else {
425                 $li_title = $ML{'.optionlinks.joincomm.title.open'};
426                 $body .= "<li class='profile_join' title=\"$li_title\"><a href='$url'><img src='$LJ::IMGPREFIX/profile_icons/join-comm.gif?v=14658' alt='' />$text</a></li>";
427             }
428         }
429     }
432     # add friend
433     $url = "$LJ::SITEROOT/friends/add.bml?user=$user";
434     if ($u->is_community) {
435         my $remote_hasfriend = $remote && $remote->has_friend($u) ? 1 : 0;
436         $text = $remote_hasfriend ? $ML{'.optionlinks.modifywatch'} : $ML{'.optionlinks.watch'};
437         if ($remote && ($remote_hasfriend || $u->is_visible)) {
438             $li_title = $remote_hasfriend ? $ML{'.optionlinks.modifywatch.title'} : $ML{'.optionlinks.watch.title'};
439             $body .= "<li class='profile_watch' title=\"$li_title\"><a href='$url'><img src='$LJ::IMGPREFIX/profile_icons/watch-comm.gif?v=14658' alt='' />$text</a></li>";
440         } else {
441             $li_title = $ML{'.optionlinks.watch.title.loggedout'};
442             $body .= "<li class='profile_watch_disabled' title=\"$li_title\"><img src='$LJ::IMGPREFIX/profile_icons/watch-comm-disabled.gif?v=14658' alt='' />$text</li>";
443         }
444     } elsif ($u->is_syndicated) {
445         my $remote_hasfriend = $remote && $remote->has_friend($u) ? 1 : 0;
446         $text = $remote_hasfriend ? $ML{'.optionlinks.modifysub'} : $ML{'.optionlinks.sub'};
447         if ($remote && ($remote_hasfriend || $u->is_visible)) {
448             $li_title = $remote_hasfriend ? $ML{'.optionlinks.modifysub.title'} : $ML{'.optionlinks.sub.title'};
449             $body .= "<li class='profile_addfeed' title=\"$li_title\"><a href='$url'><img src='$LJ::IMGPREFIX/profile_icons/add-feed.gif?v=14658' alt='' />$text</a></li>";
450         } else {
451             $li_title = $ML{'.optionlinks.sub.title.loggedout'};
452             $body .= "<li class='profile_addfeed_disabled' title=\"$li_title\"><img src='$LJ::IMGPREFIX/profile_icons/add-feed-disabled.gif?v=14658' alt='' />$text</li>";
453         }
454     } else {
455         # has_friend doesn't work right if you are viewing your own profile
456         my $remote_hasfriend = $remote && LJ::get_groupmask($remote->userid, $u->userid) ? 1 : 0;
457         $text = $remote_hasfriend ? $ML{'.optionlinks.modifyfriend'} : $ML{'.optionlinks.addfriend'};
458         if ($remote && ($remote_hasfriend || $u->is_visible)) {
459             if ($remote->equals($u)) {
460                 $li_title = $remote_hasfriend ? $ML{'.optionlinks.modifyfriend.title.self'} : $ML{'.optionlinks.addfriend.title.self'};
461             } else {
462                 $li_title = $remote_hasfriend ? $ML{'.optionlinks.modifyfriend.title.other'} : $ML{'.optionlinks.addfriend.title.other'};
463             }
464             $body .= "<li class='profile_addfriend' title=\"$li_title\"><a href='$url'><img src='$LJ::IMGPREFIX/profile_icons/add-friend.png?v=21382' alt='' />$text</a></li>";
465         } else {
466             $li_title = $ML{'.optionlinks.addfriend.title.loggedout'};
467             $body .= "<li class='profile_addfriend_disabled' title=\"$li_title\"><img src='$LJ::IMGPREFIX/profile_icons/add-friend-disabled.png?v=21382' alt='' />$text</li>";
468         }
469     }
471     # add alias
472         $url = "$LJ::SITEROOT/manage/notes.bml";
473         $text = $user_alias ne '' ? $ML{'.editalias.title'} : $ML{'.addalias.title'};
474         $li_title = ($remote && $remote->get_cap('aliases')) ? $ML{'.useralias.title'} : "$ML{'.useralias.title.disabled'}";
475         if ($remote && $remote->get_cap('aliases') && $remote->userid ne $u->userid) {
477         my $add_style = $user_alias eq ''
478             ? ""
479             : "display:none";
480         my $edit_style = $user_alias eq ''
481             ? "display:none"
482             : "";
484                 $body .= qq|<li class='profile_addalias' title="$li_title" style="$add_style"><a onclick='return addAlias(this, "$ML{'.addalias.title'}", "$u->{user}", "")'  href='$url'>|;
485                 $body .= "<img src='$LJ::IMGPREFIX/profile_icons/alias.gif?v=7428' alt='' /><span>$ML{'.addalias.title'}</span></a></li>";
487                 $body .= qq|<li class='profile_addalias' title="$li_title" style="$edit_style"><a onclick='return addAlias(this, "$ML{'.editalias.title'}", "$u->{user}", "|.LJ::ehtml(LJ::ejs($user_alias)).qq|")'  href='$url'>|;
488                 $body .= "<img src='$LJ::IMGPREFIX/profile_icons/alias.gif?v=7428' alt='' /><span>$ML{'.editalias.title'}</span></a></li>";
490         } elsif($remote && $remote->userid eq $u->userid) {
491             # noop. User can't set alias for himself
492         } else {
493                 $body .= "<li class='profile_addalias_disabled' title=\"$li_title\"><img src='$LJ::IMGPREFIX/profile_icons/alias_disabled.gif?v=7428' alt='' /><span>$text</span></li>";
494         }
496     # post entry
497     $url = "$LJ::SITEROOT/update.bml?usejournal=$user";
498     if ($pm->remote_can_post) {
499         if ($u->is_community) {
500             $text = $ML{'.optionlinks.post'};
501             $li_title = $ML{'.optionlinks.post.title'};
502         } else {
503             $text = $ML{'.optionlinks.postentry'};
504             $li_title = $ML{'.optionlinks.postentry.title'};
505         }
506         $body .= "<li class='profile_postentry' title=\"$li_title\"><a href='$url'><img src='$LJ::IMGPREFIX/profile_icons/post-entry.gif?v=14658' alt='' />$text</a></li>";
507     } elsif ($u->is_community) {
508         $text = $ML{'.optionlinks.post'};
509         $li_title = $remote ? $ML{'.optionlinks.post.title.cantpost'} : $ML{'.optionlinks.post.title.loggedout'};
510         $body .= "<li class='profile_postentry_disabled' title=\"$li_title\"><img src='$LJ::IMGPREFIX/profile_icons/post-entry-disabled.gif?v=14658' alt='' />$text</li>";
511     }
513     # track user
514     if (LJ::is_enabled("esn")) {
515         $url = "$LJ::SITEROOT/manage/subscriptions/user.bml?journal=$user";
516         $text = $ML{'.optionlinks.trackuser'};
517         $li_title = $ML{'.optionlinks.trackuser.title'};
518         if ($remote && $u->equals($remote)) {
519             $text = $ML{'.optionlinks.tracking'};
520             $li_title = $ML{'.optionlinks.tracking.title'};
521         } elsif ($u->is_community) {
522             $text = $ML{'.optionlinks.track'};
523             $li_title = $ML{'.optionlinks.track.title'};
524         } elsif ($u->is_syndicated) {
525             $text = $ML{'.optionlinks.tracksyn'};
526             $li_title = $ML{'.optionlinks.tracksyn.title'};
527         }
528         if ($remote && $remote->can_use_esn) {
529             $body .= "<li class='profile_trackuser' title=\"$li_title\"><a href='$url'><img src='$LJ::IMGPREFIX/profile_icons/track.gif?v=14658' alt='' />$text</a></li>";
530         } else {
531             $li_title = $remote ? $ML{'.optionlinks.trackuser.title.cantuseesn'} : $ML{'.optionlinks.trackuser.title.loggedout'};
532             $body .= "<li class='profile_trackuser_disabled' title=\"$li_title\"><img src='$LJ::IMGPREFIX/profile_icons/track-disabled.gif?v=14658' alt='' />$text</li>";
533         }
534     }
536     # send message
537     if (($u->is_personal || $u->is_identity) && !$u->equals($remote)) {
538         $url = "$LJ::SITEROOT/inbox/compose.bml?user=$user";
539         $text = $ML{'.optionlinks.sendmessage'};
540         $li_title = $ML{'.optionlinks.sendmessage.title'};
541         if ($remote && $u->can_receive_message($remote)) {
542             $body .= "<li class='profile_sendmessage' title=\"$li_title\"><a href='$url'><img src='$LJ::IMGPREFIX/profile_icons/send-message.gif?v=14658' alt='' />$text</a></li>";
543         } else {
544             $li_title = $remote ? $ML{'.optionlinks.sendmessage.title.cantsendmessage'} : $ML{'.optionlinks.sendmessage.title.loggedout'};
545             $body .= "<li class='profile_sendmessage_disabled' title=\"$li_title\"><img src='$LJ::IMGPREFIX/profile_icons/send-message-disabled.gif?v=14658' alt='' />$text</li>";
546         }
547     }
549     # extra
550     $body .= LJ::run_hook("userinfo_extra_user_options", user => $u, remote => $remote);
552     $body .= "</ul>";
553     $body .= "</div>";
555     ### User Details
556     my $new_width = $boxad ? " style='width: 45%;'" : '';
557     $body .= "<div class='user_details'$new_width>";
559     # picture
560     $body .= "<div class='userpicdiv'>";
561     if ($synd) {
562         $body .= "<img src='$LJ::IMGPREFIX/profile_icons/feed.gif?v=14273' class='user_pic' alt=\"$ML{'.userpic.alt'}\" />";
563     } else {
564         my $default_userpic_img;
565         if ($u->{defaultpicid}) {
566             my %pic;
567             my $picid = $u->{defaultpicid};
568             LJ::load_userpics(\%pic, [ $u, $picid ]);
569             $default_userpic_img = "<img src='$LJ::USERPIC_ROOT/$picid/$userid' width='$pic{$picid}->{'width'}' height='$pic{$picid}->{'height'}' border='0' class='user_pic' alt=\"$ML{'.userpic.alt'}\" />";
570         } elsif ($u->is_person) {
571             $default_userpic_img = "<img src='$LJ::IMGPREFIX/profile_icons/user.gif?v=14273' class='user_pic' alt=\"$ML{'.userpic.alt'}\" />";
572         } elsif ($com) {
573             $default_userpic_img = "<img src='$LJ::IMGPREFIX/profile_icons/comm.png?v=24097' class='user_pic' alt=\"$ML{'.userpic.alt'}\" />";
574         } elsif ($u->is_identity) {
575             # Fanat.ru users have special icon
576             my $value = $u->identity->value;
577             my $img = ($value =~ m#^http://\w+\.fanat\.ru(\/|$)$#)
578                         ? 'openid_fanat.png?v=15782'
579                         : 'openid.gif?v=14273';
581             $default_userpic_img = "<img src='$LJ::IMGPREFIX/profile_icons/$img' class='user_pic' alt=\"$ML{'.userpic.alt'}\" />";
582         }
584         if ($remote && $remote->can_manage($u)) {
585             if (LJ::userpic_count($u)) {
586                 $body .= "<a href='$LJ::SITEROOT/allpics.bml?user=$user'>$default_userpic_img</a><br />";
587                 $body .= "<span class='user_pic_caption'>";
588                 $body .= "[<a href='$LJ::SITEROOT/editpics.bml?authas=$user'>$ML{'.section.edit'}</a>]";
589                 $body .= "</span>";
590             } else {
591                 $body .= "<a href='$LJ::SITEROOT/editpics.bml?authas=$user'>$default_userpic_img</a><br />";
592                 $body .= "<a href='$LJ::SITEROOT/editpics.bml?authas=$user' class='user_pic_caption'>$ML{'.userpic.upload'}</a>";
593             }
594         } else {
595             if (LJ::userpic_count($u)) {
596                 $body .= "<a href='$LJ::SITEROOT/allpics.bml?user=$user'>$default_userpic_img</a>";
597             } else {
598                 $body .= $default_userpic_img;
599             }
600         }
601     }
602     $body .= "</div>";
604     $body .= "<div class='user_details_inner'>";
606     # journal titles
607     my $title = $u->{journaltitle} ? LJ::ehtml($u->{journaltitle}) : BML::ml('.details.title', { user => $u->display_username });
608     my $subtitle = $u->{journalsubtitle} ?  LJ::ehtml($u->{journalsubtitle}) : '';
609     $body .= "<div class='details_journal'>";
610     $body .= "<h2 class='journal_title'>$title</h2>";
611     $body .= "<h3 class='journal_subtitle'>$subtitle</h3>" if $subtitle;
612     $body .= "</div>";
614     ## journal warnings
615     my $journal_warnings;
617     if ($u->is_locked) {
618         $journal_warnings .= "<p class='statusvis_msg'><img src='$LJ::IMGPREFIX/profile_icons/warning.gif?v=14405' align='absmiddle' alt='' /> $ML{'statusvis_message.locked'}</p>";
619     } elsif ($u->is_memorial) {
620         $journal_warnings .= "<p class='statusvis_msg'><img src='$LJ::IMGPREFIX/profile_icons/warning.gif?v=14405' align='absmiddle' alt='' /> $ML{'statusvis_message.memorial'}</p>";
621     } elsif ($u->is_readonly) {
622         $journal_warnings .= "<p class='statusvis_msg'><img src='$LJ::IMGPREFIX/profile_icons/warning.gif?v=14405' align='absmiddle' alt='' /> $ML{'statusvis_message.readonly'}</p>";
623     }
625     unless ($u->is_identity) {
626         if ($u->adult_content_calculated eq 'explicit') {
627             $journal_warnings .= "<p class='journal_adult_warning'><img src='$LJ::IMGPREFIX/profile_icons/warning.gif?v=14405' align='absmiddle' alt='' /> $ML{'.details.warning.explicit'}</p>";
628         } elsif ($u->adult_content_calculated eq 'concepts') {
629             $journal_warnings .= "<p class='journal_adult_warning'><img src='$LJ::IMGPREFIX/profile_icons/warning.gif?v=14405' align='absmiddle' alt='' /> $ML{'.details.warning.concepts'}</p>";
630         }
631     }
633     ## stats
634     my $lastupdated = substr(LJ::TimeUtil->mysql_time($u->timeupdate), 0, 10);
635     my $ago_text = LJ::TimeUtil->ago_text($u->{secondsold});
637     my $search_link;
638     $search_link = "[<a href='$LJ::SITEROOT/tools/search.bml?journal=$user'>$ML{'.details.search'}</a>]"
639         if LJ::is_enabled("offsite_journal_search") && $pm->has_journal;
640     my $nudge_link;
641     $nudge_link = "[<a href='$LJ::SITEROOT/friends/nudge.bml?user=$user'>$ML{'.details.nudge'}</a>]"
642         if $remote && $u->can_be_nudged_by($remote);
644     my $num_comments_received = $u->num_comments_received( dbh => $dbcr );
645     my $num_comments_posted = $u->num_comments_posted( dbh => $dbcr );
647     my $supportpoints = $u->support_points_count;
649     my $timecreate = LJ::TimeUtil->mysql_time($u->timecreate);
650     my $createdate = "<span class='tooltip' title=\"$timecreate\">" . substr($timecreate, 0, 10) . "</span>";
652     $body .= "<div class='details_stats'>";
653     $body .= $journal_warnings;
655     $body .= "<p class='account_level'>";
656     $body .= LJ::run_hook("userinfo_extra_user_details", user => $u);
658     $body .= BML::ml('.details.createdon2', { createdate => $timecreate }) . " (#" . $u->id . ")";
659     unless ($u->is_identity) {
660         if ($u->timeupdate) {
661             $body .= ", " . BML::ml('.details.lastupdated2', { timestamp => "<span class='tooltip' title=\"$ago_text\">$lastupdated</span>" }) . " $nudge_link";
662         } else {
663             $body .= ", $ML{'.details.lastupdated.never2'} $nudge_link";
664         }
665     }
666     $body .= "</p>";
667     $body .= "</div>";
669     #LJSUP-10988: Add position and social capital to user profile
670     #==============================================================
671     if ($u->is_personal || $u->is_comm) {
672         my ($position, $ua_position, $diagram_image, $href_rating, $ua_href_rating, $soc_image, $soc_capital);
674         #LJSUP-11197: If user is in two ratings (common and UA) display two strings in profile
675         #-------------------------------------------------------------------------------------
676         my $view_ua_ratings = 0;
677         if (LJ::is_enabled('personal_stats_ua')) {
678             my $country = LJ::GeoLocation->get_country_info_by_ip;
679             $country = $u->prop('country') if $u && $country ne 'UA';
680             if ($country eq 'UA') {
681                 $ua_position = LJ::PersonalStats::DB->fetch_raw('ratings', {
682                         func => 'get_value',
683                         what => $u->journaltype eq 'C' ? 'communities' : 'users',
684                         journal_id => $u->userid,
685                         by => 'friends_weight',
686                         type => 0,
687                         filter => 'UA',
688                 });
689             }
690         }
691         #-------------------------------------------------------------------------------------
693         $position = LJ::PersonalStats::DB->fetch_raw('ratings', {
694             func => 'get_value',
695             what => $u->journaltype eq 'C' ? 'communities' : 'users',
696             journal_id => $u->userid,
697             by => 'friends_weight',
698             type => 0,
699             sup =>  LJ::SUP->is_sup_enabled($u) ? 1 : 0,
700         });
702         if ((ref $ua_position eq 'HASH') || (ref $position eq 'HASH')) {
703             $diagram_image = "<img src='$LJ::IMGPREFIX/profile_icons/diagram.png?v=11372'/> ";
704             $href_rating = $u->journaltype eq 'C' ? 'ljcom.userinfo.community_rating' : 'ljcom.userinfo.account_rating';
705             $ua_href_rating = $u->journaltype eq 'C' ? 'ljcom.userinfo.ua_community_rating' : 'ljcom.userinfo.ua_account_rating';
706         }
708         $body .= "<ul class='rating-details'>";
710         if (ref $position eq 'HASH' && ( $u->journaltype eq 'C' || LJ::SUP->is_sup_enabled($u) )) {
711                 $soc_image = "<img src='$LJ::IMGPREFIX/profile_icons/" . ($position->{result}->{position}!=0 ? 'social-capital.png?v=17298' : 'korona.png?v=17319') . "'/>";
712                 my $country  = LJ::SUP->is_sup_enabled($u) ? 'cyr' : 'noncyr';
713                 $body .= "<li class='rating-place'>" .
714                          $diagram_image .
715                          LJ::Lang::ml($href_rating, {rating_place => LJ::commafy($position->{result}->{position}+1),
716                                                      url_rating => $LJ::SITEROOT . "/ratings/" . ($u->journaltype eq 'C' ? 'community' : 'users') .
717                                                      "?country=$country&askname=" . $u->username . "#ask_position"}) .
718                          "</li>";
719         }
720         if (ref $ua_position eq 'HASH') {
721                 $soc_image = "<img src='$LJ::IMGPREFIX/profile_icons/" . ($ua_position->{result}->{position}!=0 ? 'social-capital.png?v=17298' : 'korona.png?v=17319') . "'/>";
722                 $body .= "<li class='rating-place'>" .
723                          $diagram_image .
724                          LJ::Lang::ml($ua_href_rating, {rating_place => LJ::commafy($ua_position->{result}->{position}+1),
725                                                         url_rating => $LJ::SITEROOT . "/ratings/" . ($u->journaltype eq 'C' ? 'community' : 'users') .
726                                                         "?country=ua&askname=" . $u->username . "#ask_position"}) .
727                          "</li>";
728         }
730         my $soc_capital = LJ::User::display_soccap($u->get_social_capital());
731         $soc_image ||= "<img src='$LJ::IMGPREFIX/profile_icons/social-capital.png?v=17298'/>";
733         if ($u->journaltype eq 'C' || LJ::SUP->is_sup_enabled($u)) {
734                 $body .= "<li class='rating-social-capital'>" .
735                          $soc_image .
736                          LJ::Lang::ml('ljcom.userinfo.social_capital',{soc_capital => $soc_capital}) . ' ' .
737                          LJ::help_icon_html("profile_faq") .
738                          "</li>";
739         }
741         $body .= "</ul>";
743     }
744     #==============================================================
746     my @view_links_l;
747     my @view_links_r;
748     my $entry_count = $u->number_of_posts;
749     my $tagcount = scalar keys %{$u->tags};
750     my $memcount = LJ::Memories::count($userid) || 0;
751     my $userpiccount = LJ::userpic_count($u);
753     push @view_links_l, '<li>' . BML::ml('.details.entries3', { num_raw => $entry_count, num_comma => LJ::commafy($entry_count), aopts => "href='" . $u->journal_base . "'" }) . '</li>'
754         unless $u->is_identity;
755     push @view_links_l, '<li>'. BML::ml('.details.comments.received2', { num_raw => $num_comments_received, num_comma => LJ::commafy($num_comments_received) }). '</li>' unless $u->is_identity;
757     push @view_links_l, '<li>' . BML::ml('.details.comments.posted2', { num_raw => $num_comments_posted, num_comma => LJ::commafy($num_comments_posted) }) . '</li>' if LJ::is_enabled("show-talkleft") && ($u->is_personal || $u->is_identity);
759     push @view_links_l, '<li>' . BML::ml('.details.tags2', { num_raw => $tagcount, num_comma => LJ::commafy($tagcount), aopts => "href='" . $u->journal_base . "/tag/'" }) . '</li>'
760         unless $u->is_identity || $u->is_syndicated;
761     push @view_links_l, '<li>' . BML::ml('.details.supportpoints2', { aopts => "href='$LJ::SITEROOT/support/'", num => LJ::commafy($supportpoints), num_raw => $supportpoints }) . '</li>' if $supportpoints;
762     push @view_links_r, '<li>' . BML::ml('.details.memories2', { num_raw => $memcount, num_comma => LJ::commafy($memcount), aopts => "href='$LJ::SITEROOT/tools/memories.bml?user=$user'" }) . '</li>'
763         unless $u->is_syndicated;
765     if ( my $photos_count = LJ::Pics->get_photos_count($u) ) {
766         my $photos_count_display = LJ::commafy($photos_count);
767         push @view_links_r, '<li>' .
768             LJ::Lang::ml( '/userinfo.bml.details.pics', {
769                 'num_raw'   => $photos_count,
770                 'num_comma' => $photos_count_display,
771                 'link'      => $u->journal_base . '/pics/catalog',
772             } ) .
773             '</li>';
774     }
776     push @view_links_r, '<li>' . BML::ml('.details.userpics', { num_raw => $userpiccount, num_comma => LJ::commafy($userpiccount), aopts => "href='$LJ::SITEROOT/allpics.bml?user=$user'" }) . '</li>'
777         unless $u->is_syndicated;
779     LJ::run_hook("userinfo_modify_view_links", user => $u, viewlinksref => \@view_links_r);
781     #my @details_links = $ML{'.details.viewlinkssep'};
782     $body .= "<div class='details_links'>";
783     $body .= "<ul>" . join ( ' ', @view_links_l) . "</ul>";
785     $body .= "<ul>" . join ( ' ', @view_links_r) . "</ul>";
786     $body .= "</div>";
787     {
788         my $userinfo_add = '';
789         LJ::run_hooks('userinfo_modify_details', journal => $u, ret => \$userinfo_add);
790         $body .= $userinfo_add if $userinfo_add;
791     }
793     $body .= "</div>";
795     $body .= "</div>";
797     $body .= "</div>";
799     my $html_by_journal;
800     LJ::run_hook("userinfo_html_by_journal", { ret => \$html_by_journal, u => $u, with_header => 1 });
801     $body .= $html_by_journal;
803     # Display Name
804     my $display_name;
805     if ($synd) {
806         my $link;
807         if (my $url = $u->{'url'}) {
808             $link = "<a href='" . LJ::ehtml($url) . "'>$u->{'name'}</a>";
809         } else {
810             $link = $u->{'name'};
811         }
813         my $icon = "<a href='" . LJ::ehtml($synd->{'synurl'}) . "'><img src='$LJ::IMGPREFIX/xml.gif?v=6803' width='36' height='14' align='absmiddle' border='0' alt=\"$ML{'.syn.xml'}\" /></a>";
815         $display_name .= "<tr><th>$ML{'.label.syndicatedfrom'}</th><td>$link $icon</td></tr>\n";
816     } else {
817         unless ($u->underage || $u->{'name'} eq $u->{'journaltitle'}) {
818             $display_name .= "<tr><th>$ML{'.label.name'}</th><td>$u->{'name'}</td></tr>\n";
819         }
820     }
822     my $birthday;
823     my $location;
824     my $website;
825     unless ($synd) {
826         # Birthday
827         if ($u->bday_string && ($u->can_share_bday || $viewall)) {
828             if ($u->{'bdate'} && !$com && $u->{'bdate'} ne "0000-00-00") {
829                 $birthday .= "<tr><th>$ML{'.label.birthdate'}</th><td>" . $u->bday_string . "</td></tr>\n";
830             }
831         }
833         # Location
834         if (($u->can_show_location || $viewall) &&
835             ($u->{'city'} || $u->{'state'} || $u->{'country'})) {
836             $location .= "<tr><th>$ML{'.label.location'}</th><td>";
837             my $ecity = LJ::eurl($u->{'city'});
838             my $ecountry = LJ::eurl($u->{'country'});
839             my $estate = "";
841             my ($country, $city, $state);
843             if ($u->{'country'}) {
844                 $country = $LJ::DISABLED{'directory'} ? "<span class='country-name'>$countries{$u->{'country'}}</span>" :
845                     "<a href='$LJ::SITEROOT/directory.bml?opt_sort=ut&amp;s_loc=1&amp;loc_cn=$ecountry' class='country-name'>".
846                         $countries{$u->{'country'}} . "</a>";
847             }
849             if ($u->{'state'}) {
850                 my %states;
852                 my $states_type = $LJ::COUNTRIES_WITH_REGIONS{$u->{'country'}}->{'type'};
853                 LJ::load_codes({ $states_type => \%states }) if defined $states_type;
855                 $state = LJ::ehtml($u->{'state'});
856                 $state = $states{$state} if $states_type && $states{$state};
857                 $estate = LJ::eurl($state);
858                 $state = (!$country || $LJ::DISABLED{'directory'}) ? "<span class='region'>$state</span>" :
859                     "<a href='$LJ::SITEROOT/directory.bml?opt_sort=ut&amp;s_loc=1&amp;loc_cn=".
860                     "$ecountry&amp;loc_st=$estate' class='region'>" . LJ::ehtml($state) . "</a>";
861             }
863             if ($u->{'city'}) {
864                 my $ecity = LJ::eurl($u->{'city'});
865                 $city = LJ::ehtml($u->{'city'});
866                 unless (!$country || $LJ::DISABLED{'directory'}) {
867                     $city = "<a href='$LJ::SITEROOT/directory.bml?opt_sort=ut&amp;s_loc=1&amp;loc_cn=".
868                         "$ecountry&amp;loc_st=$estate&amp;loc_ci=$ecity' class='locality'>$city</a>";
869                 } else {
870                     $city = "<span class='locality'>$city</span>";
871                 }
872             }
874             $location .= join(", ", grep { $_ } ($city, $state, $country));
875             $location .= "</td></tr>";
876         }
878         # Website URL
879         if ($u->{'url'}) {
880             my $url = LJ::ehtml($u->{'url'});
881             unless ($url =~ /^https?:\/\//) {
882                 $url =~ s/^http\W*//;
883                 $url = "http://$url";
884             }
885             my $urlname = LJ::ehtml($u->{'urlname'} || $url);
886             $url = "<a href='$url' class='url' rel='me'>$urlname</a>";
887             $website .= "<tr><th>$ML{'.label.website'}</th><td>$url</td></tr>\n" if ($u->{'url'});
888         }
889     }
891     my $mangleaddress = sub {
892         my ($email, $first) = @_;
893         $first ||= "";
894         my $mret = "<span>$first";
895         for (my $i = 0; $i < length($email); $i++) {
896             my $letter = substr($email, $i, 1);
897             if ($letter eq "\@") { $letter = "</span><span><i>&#64;</i></span>"; }
898             $mret .= $letter;
899         }
900         return $mret;
901     };
903     # Contact
904     my @contacts;
905     if (($u->is_personal || $u->is_identity) && $remote && !$u->equals($remote) && $u->can_receive_message($remote)) {
906         push @contacts, "<a href='$LJ::SITEROOT/inbox/compose.bml?user=$u->{'user'}'>$ML{'.contact.pm'}</a>";
907     }
909     if (!$synd && $u->share_contactinfo($remote) || $viewall) {
910         my @emails = $u->emails_visible($remote);
911         foreach my $email (@emails) {
912             if ($u->{'opt_mangleemail'} eq "Y" || $email =~ /\@livejournal\.com$/) {
913                 push @contacts, $mangleaddress->($email);
914             } else {
915                 push @contacts, "<a href='mailto:$email' class='email'>$email</a>";
916             }
917         }
918     }
920     if (!$synd && $u->{'txtmsg_status'} eq 'on' && $u->can_be_text_messaged_by($remote)) {
921         push @contacts, "<a href='$LJ::SITEROOT/tools/textmessage.bml?user=$u->{'user'}'>$ML{'.contact.txtmsg'}</a>";
922     }
924     my $contact = join("<br />\n", @contacts);
926     # Community Membership and Posting Access
927     my $comm_settings;
928     if ($com) {
929         my ($membership, $postlevel) = LJ::get_comm_settings($u);
931         my $membership_string = $ML{'.commsettings.membership.open'};
932         if ($membership eq "moderated") {
933             $membership_string = $ML{'.commsettings.membership.moderated'};
934         } elsif ($membership eq "closed") {
935             $membership_string = $ML{'.commsettings.membership.closed'};
936         }
938         my $postlevel_string = $ML{'.commsettings.postlevel.members'};
939         if ($postlevel eq "select") {
940             $postlevel_string = $ML{'.commsettings.postlevel.select'};
941         } elsif ($u->prop('nonmember_posting')) {
942             $postlevel_string = $ML{'.commsettings.postlevel.anybody'};
943         }
945         $postlevel_string .= $ML{'.commsettings.postlevel.moderated'}
946             if $u->prop('moderated') && 'N' ne $u->prop('moderated');
948         $comm_settings .= "<tr><th>$ML{'.commsettings.membership.header'}</th><td>$membership_string</td></tr>";
949         $comm_settings .= "<tr><th>$ML{'.commsettings.postlevel.header'}</th><td>$postlevel_string</td></tr>";
950     }
952     # Community Theme
953     my $comm_theme;
954     if ($com && $u->prop('comm_theme')) {
955         $comm_theme .= "<tr><th>$ML{'.commdesc.header'}</th><td>" . LJ::ehtml($u->prop('comm_theme')) . "</td></tr>";
956     }
958     # Syndication Status
959     my $syn_status;
960     if ($synd) {
961         # syndication status
962         $syn_status .= "<tr valign='top'><th>$ML{'.label.syndicatedstatus'}</th><td>";
963         $syn_status .= "$ML{'.syn.lastcheck'} ";
964         $syn_status .= $synd->{'lastcheck'} || $ML{'.syn.last.never'};
965         my $status = {
966             'parseerror' => "Parse error",
967             'notmodified' => "Not modified",
968             'toobig' => "Too big",
969             'posterror' => "Posting error",
970             'ok' => "",     # no status line necessary
971             'nonew' => "",  # no status line necessary
972         }->{$synd->{'laststatus'}};
973         $syn_status .= " ($status)" if $status;
975         if ($synd->{'laststatus'} eq "parseerror") {
976            $syn_status .= "<br />$ML{'.syn.parseerror'} " . LJ::ehtml($u->{'rssparseerror'});
977         }
979         $syn_status .= "<br />$ML{'.syn.nextcheck'} $synd->{'checknext'}";
980         $syn_status .= "</td></tr>\n";
981     }
983     # Syndication Readers
984     my $syn_readers;
985     if ($synd) {
986         $syn_readers .= "<tr><th>$ML{'.label.syndreadcount'}</th></td>";
987         $syn_readers .= "<td>" . $fro_m->reader_count . "</td></tr>\n";
988     }
990     ### Basic Info
991     if ($display_name || $birthday || $location || $website || $comm_settings || $comm_theme || $syn_status || $syn_readers || $contact) {
992         $body .= "<div class='ljclear'></div>";
993         $body .= "<div class='section'><span class='expandcollapse on' id='basics_header'>" . $arrowimg->("basics") . " $ML{'.basicinfo.header'}</span>";
994         $body .= " <span class='section_link'>[<a href='$LJ::SITEROOT/manage/profile/?authas=" . $u->user . "'>$ML{'.section.edit'}</a>]</span>" if $remote && $remote->can_manage($u);
995         $body .= "</div>";
996         $body .= "<div class='section_body' id='basics_body'>\n";
998         $body .= "<div class='userinfo'>";
999         $body .= "<table cellpadding='0' cellspacing='3'>";
1000         $body .= $display_name;
1001         if ($com) {
1002             $body .= "$location$website$comm_settings$comm_theme";
1003         } elsif ($synd) {
1004             $body .= "$syn_status$syn_readers";
1005         } else {
1006             $body .= "$birthday$location$website";
1007         }
1008         $body .= "</table>";
1009         $body .= "</div>";
1011         if ($contact) {
1012             $body .= "<div class='contact'>";
1013             $body .= "<p class='section_body_title'>$ML{'.contact.header'}</p>";
1014             $body .= $contact;
1015             $body .= "</div>";
1016         }
1018         $body .= "</div>";
1019     }
1021     $body .= LJ::run_hook("profile_between_basicinfo_and_bio", $u);
1023     ### Bio
1024     if ($u->{'has_bio'} eq "Y") {
1025         $body .= "<div class='ljclear'></div>";
1026         my $label = $u->is_person || $u->is_identity ? $ML{'.bio.header'} : $ML{'.about.header'};
1028         LJ::CleanHTML::clean_userbio(\$u->{'bio'}, poster => $u);
1030         LJ::EmbedModule->expand_entry($u, \$u->{'bio'});
1031         $body .= "<div class='section'><span class='expandcollapse on' id='bio_header'>" . $arrowimg->("bio") . " $label</span>";
1032         $body .= " <span class='section_link'>[<a href='$LJ::SITEROOT/manage/profile/?authas=" . $u->user . "#bio'>$ML{'.section.edit'}</a>]</span>" if $remote && $remote->can_manage($u);
1033         $body .= "</div>\n";
1034         $body .= "<div class='section_body' id='bio_body'>$u->{'bio'}</div>\n";
1035     }
1036     ### End Bio
1038     ### Interests
1039     my $intlist;
1040     my $intcount = 0;
1041     if (@$intu) {
1042         foreach my $int (@$intu) {
1043             next if $intcount++ > 150;
1044             LJ::text_out(\$int->[1]); # 1==interest
1045             my $eint = LJ::eurl($int->[1]);
1046             if ($int->[2] > 1) {  # 2==intcount
1047                 my $intline;
1048                 if ($remote && $remote->get_cap("directory")) {
1049                     $intline = "<a href='$LJ::SITEROOT/directory.bml?int_like=$eint&opt_pagesize=100&start_search=1'>$int->[1]</a>";
1050                 } else {
1051                     $intline = "<a href='$LJ::SITEROOT/interests.bml?int=$eint'>$int->[1]</a>";
1052                 }
1053                 $intline = "<b>$intline</b>" if $remote_interest{$int->[0]};  # 0==intid
1055                 $intlist .= "$intline, ";
1056             } else {
1057                 $intlist .= "$int->[1], ";
1058             }
1059         }
1060         chop $intlist; chop $intlist;  # remove trailing ", "
1061         if ($intcount > 150) {
1062             my $notshown = $intcount - 150;
1063             $intlist .= BML::ml('.label.intsnotshown',{'intnotshown'=>$notshown});
1064         }
1065     }
1066     # End Interests
1068     # Instant Message
1069     my $instant_message;
1070     if ($u->is_personal && ($u->share_contactinfo($remote) || $viewall)) {
1071         my $instant_message_xtra = LJ::run_hook('userinfo_instant_message_extra', user => $u, remote => $remote, mangleaddress => $mangleaddress );
1072         $instant_message .= $instant_message_xtra;
1074         if ($u->{'aolim'}) {
1075             my $aol = my $qim = LJ::ehtml($u->{'aolim'});
1076             my $aol_alt = $ML{'.im.aol'};
1077             my $aolstatus_alt = $ML{'.im.aol.status'};
1078             $qim =~ s/ //g;
1079             $instant_message .= "<tr class='im_aim'><td class='im_icon'><img src='$LJ::IMGPREFIX/profile_icons/aim.gif?v=14658' alt=\"$aol_alt\" title=\"$aol_alt\" /></td><td>$aol</td><td class='im_status'><img alt=\"$aolstatus_alt\" title=\"$aolstatus_alt\" 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='13' width='11' /></td></tr>\n";
1080         }
1082         if ($u->{'icq'}) {
1083             my $icq = LJ::ehtml($u->{'icq'});
1084             my $icq_alt = $ML{'.im.icq'};
1085             my $icqstatus_alt = $ML{'.im.icq.status'};
1086             $instant_message .= "<tr class='im_icq'><td class='im_icon'><img src='$LJ::IMGPREFIX/profile_icons/icq.gif?v=14273' alt=\"$icq_alt\" title=\"$icq_alt\" /></td><td><a href='http://wwp.icq.com/$icq'>$icq</a></td><td class='im_status'><img alt=\"$icqstatus_alt\" title=\"$icqstatus_alt\" src='http://web.icq.com/whitepages/online?icq=$icq&amp;img=5' height='18' width='18' /></td></tr>\n";
1087         }
1088         if ($u->{'yahoo'}) {
1089             my $yim = LJ::ehtml($u->{'yahoo'});
1090             my $yim_alt = $ML{'.im.yim'};
1091             my $yimstatus_alt = $ML{'.im.yim.status'};
1092             $instant_message .= "<tr class='im_yahoo'><td class='im_icon'><img src='$LJ::IMGPREFIX/profile_icons/yahoo.gif?v=14273' alt=\"$yim_alt\" title=\"$yim_alt\" /></td><td><a href='http://profiles.yahoo.com/$yim'>$yim</a></td><td class='im_status'><img alt=\"$yimstatus_alt\" title=\"$yimstatus_alt\" src='http://opi.yahoo.com/online?u=$yim&amp;m=g&amp;t=0' width='12' height='12' /></td></tr>\n";
1093         }
1094         if ($u->{'msn'}) {
1095             my $msnname = $mangleaddress->(LJ::ehtml($u->{'msn'}));
1096             my $msn_alt = $ML{'.im.msn'};
1097             my $msn_status = $ML{'.im.msn.status'};
1098             $instant_message .= "<tr class='im_msn'><td class='im_icon'><img src='$LJ::IMGPREFIX/profile_icons/wlm.gif?v=7405' alt=\"$msn_alt\" title=\"$msn_alt\" /></td><td>$msnname</td><td class='msn_status'><span id='mlm-status' class='offline' title='$msn_status offline'>$msn_status offline</span></td></tr>\n";
1099         }
1100         if ($u->{'jabber'}) {
1101             my $jabber = $mangleaddress->(LJ::ehtml($u->{'jabber'}));
1102             my $jabber_alt = $ML{'.im.jabber'};
1103             $instant_message .= "<tr class='im_jabber'><td class='im_icon'><img src='$LJ::IMGPREFIX/profile_icons/jabber.gif?v=14273' alt=\"$jabber_alt\" title=\"$jabber_alt\" /></td><td colspan='2'>$jabber</td></tr>\n";
1104         }
1105         if ($u->{'google_talk'}) {
1106             my $google = $mangleaddress->(LJ::ehtml($u->{'google_talk'}));
1107             my $gtalk_alt = $ML{'.im.gtalk'};
1108             $instant_message .= "<tr class='im_google'><td class='im_icon'><img src='$LJ::IMGPREFIX/profile_icons/gtalk.gif?v=14273' alt=\"$gtalk_alt\" title=\"$gtalk_alt\" /></td><td colspan='2'>$google</td></tr>\n";
1109         }
1110         if ($u->{'skype'}) {
1111             my $skimg;
1112             my $colspan = " colspan='2'";
1113             if ($u->{skype} =~ /^[\w\.\-]+$/) {
1114                 my $skypestatus_alt = $ML{'.im.skype.status'};
1115                 $skimg = "<td class='im_status'><img alt=\"$skypestatus_alt\" title=\"$skypestatus_alt\" width='16' height='16' src='http://mystatus.skype.com/smallicon/$u->{skype}' /></td>";
1116                 $colspan = "";
1117             }
1118             my $skype = $mangleaddress->(LJ::ehtml($u->{'skype'}));
1119             my $skype_alt = $ML{'.im.skype'};
1120             $instant_message .= "<tr class='im_skype'><td class='im_icon'><img src='$LJ::IMGPREFIX/profile_icons/skype.gif?v=14273' alt=\"$skype_alt\" title=\"$skype_alt\" /></td><td$colspan>$skype</td>$skimg</tr>\n";
1121         }
1122         if (my $gizmo = $u->gizmo_account) {
1123             $gizmo = $mangleaddress->(LJ::ehtml($gizmo));
1124             my $gizmo_alt = $ML{'.im.gizmo'};
1125             $instant_message .= "<tr class='im_gizmo'><td class='im_icon'><img src='$LJ::IMGPREFIX/profile_icons/gizmo.gif?v=14273' alt=\"$gizmo_alt\" title=\"$gizmo_alt\" /></td><td colspan='2'>$gizmo</td></tr>\n";
1126         }
1127         if ($u->{'last_fm_user'}) {
1128             my $lastfm_url = $LJ::LAST_FM_USER_URL;
1129             my $url_escaped_last_fm_user = LJ::eurl($u->{'last_fm_user'});
1130             $lastfm_url =~ s/%username%/$url_escaped_last_fm_user/g;
1132             my $lastfm = "<a href='$lastfm_url'>" . LJ::ehtml($u->{'last_fm_user'}) . "</a>";
1133             my $lastfm_alt = $ML{'.im.lastfm'};
1134             $instant_message .= "<tr class='im_lastfm'><td class='im_icon'><img src='$LJ::IMGPREFIX/profile_icons/lastfm.gif?v=14402' alt=\"$lastfm_alt\" title=\"$lastfm_alt\" /></td><td colspan='2'>$lastfm</td></tr>\n";
1135         }
1136     }
1138     # Schools
1139     my $schools_list;
1140     if (!$synd && ($u->should_show_schools_to($remote) || (LJ::is_enabled("schools") && $viewall))) {
1141         my $schools = LJ::Schools::get_attended($u);
1143         # Show if there are schools defined
1144         if ($schools && %$schools) {
1145             my @links;
1146             foreach my $sid (sort { $schools->{$a}->{year_start} <=> $schools->{$b}->{year_start} ||
1147                                     $schools->{$a}->{year_end} <=> $schools->{$b}->{year_end} ||
1148                                     $schools->{$a}->{name} cmp $schools->{$b}->{name} } keys %$schools) {
1149                 my $link = "<a href='$LJ::SITEROOT/schools/" .
1150                     "?ctc=" . LJ::eurl($schools->{$sid}->{country}) .
1151                     "&sc=" . LJ::eurl($schools->{$sid}->{state}) .
1152                     "&cc=" . LJ::eurl($schools->{$sid}->{city}) .
1153                     "&sid=" . $sid .
1154                     "'>" . LJ::ehtml($schools->{$sid}->{name}) . "</a>";
1155                 $link .= " - " . $schools->{$sid}->{city};
1156                 $link .= $schools->{$sid}->{state} ? ", $schools->{$sid}->{state}" : "";
1157                 if ($schools->{$sid}->{country} ne 'US') {
1158                     my %countries;
1159                     LJ::load_codes({ country => \%countries });
1160                     $link .= ", $countries{$schools->{$sid}->{country}}";
1161                 }
1163                 if (defined $schools->{$sid}->{year_start}) {
1164                     $link .= " (" . $schools->{$sid}->{year_start};
1166                     if ($schools->{$sid}->{year_start} != $schools->{$sid}->{year_end}) {
1167                         $link .= " - " . ($schools->{$sid}->{year_end} || $ML{'.schools.presentyear'});
1168                     }
1170                     $link .= ")";
1171                 }
1173                 push @links, "<span class='schools_item'>$link</span>";
1174             }
1175             $schools_list .= join("<br />\n", @links);
1176         }
1177     }
1179     ### Connect
1180     if ($intlist || $instant_message || $schools_list) {
1181         $body .= "<div class='ljclear'></div>";
1182         $body .= "<div class='section'><span class='expandcollapse on' id='interests_header'>" . $arrowimg->("interests") . " $ML{'.label.connect'}</span></div>";
1183         $body .= "<div class='section_body' id='interests_body'>";
1184         if ($intlist) {
1185             $body .= "<p class='inner_section_header first'>$ML{'.label.interests'} ($intcount):";
1186             $body .= " <span class='inner_section_header_link'>[<a href='$LJ::SITEROOT/manage/profile/?authas=" . $u->user . "#playlist'>$ML{'.section.edit'}</a>]</span>" if $remote && $remote->can_manage($u);
1187             if ($remote) {
1188                 my $enmasse_link = "$LJ::SITEROOT/interests.bml?mode=enmasse";
1189                 $enmasse_link .= "&fromuser=$user" unless $remote->id == $userid;
1190                 my $enmasse_text = $remote->id == $userid ? $ML{'.label.interests.removesome2'} : $ML{'.label.interests.modifyyours2'};
1192                 $body .= " <span class='inner_section_header_link'>[<a href='$enmasse_link'>$enmasse_text</a>]</span>";
1193             }
1194             $body .= "</p><div class='inner_section_body'>$intlist</div>";
1195         }
1196         if ($instant_message) {
1197             my $new_im_margin;
1198             $new_im_margin = " style='margin-top: 0;'" unless $intlist;
1199             $body .= "<div class='external_services'$new_im_margin>";
1200             $body .= "<p class='inner_section_header'$new_im_margin>$ML{'.im.header2'}";
1201             $body .= " <span class='inner_section_header_link'>[<a href='$LJ::SITEROOT/manage/profile/?authas=" . $u->user . "#iminfo'>$ML{'.section.edit'}</a>]</span>" if $remote && $remote->can_manage($u);
1202             $body .= "</p>";
1203             $body .= "<table cellpadding='0' cellspacing='3'>$instant_message</table>";
1204             $body .= "</div>";
1205         }
1206         if ($schools_list) {
1207             my $new_schools_margin;
1208             $new_schools_margin = " style='margin-top: 0;'" unless $intlist;
1209             $body .= "<div class='schools'$new_schools_margin>";
1210             $body .= "<p class='inner_section_header'$new_schools_margin>$ML{'.schools.header'}";
1211             $body .= " <span class='inner_section_header_link'>[<a href='$LJ::SITEROOT/schools/manage.bml?authas=$user'>$ML{'.schools.manage'}</a>]</span>" if $remote && $remote->can_manage($u);
1212             $body .= "</p>";
1213             $body .= $schools_list;
1214             $body .= "</div>";
1215         }
1216         $body .= "</div>";
1217     }
1219     ## community maintainers and moderators
1220     ##
1221     if ($com) {
1222         # get the list of maintainers and moderators (userid only)
1223         my $maintainers = LJ::load_rel_user_cache($userid, 'A') || [];
1224         my $super_maintainers = LJ::load_rel_user_cache($userid, 'S') || [];
1225         my $moderators;
1226         $moderators = (LJ::load_rel_user_cache($userid, 'M') || [])
1227             if $u->{'moderated'};
1229         if (scalar @$super_maintainers || scalar @$maintainers || ($u->{'moderated'} && scalar @$moderators)) {
1230             # now load all the usernames.
1231             my %userhash;
1232             LJ::load_userids_multiple([ map { $_, \$userhash{$_} }
1233                                         @$super_maintainers, @$maintainers, @$moderators ]);
1235             my @maintlist = sort { $a->{'user'} cmp $b->{'user'} }
1236                             map { $userhash{$_} } @$maintainers;
1238             $body .= "<div class='ljclear'></div>";
1239             $body .= "<div class='section'>$ML{'.admins.header'}";
1240             $body .= " <span class='section_link'>[<a href='$LJ::SITEROOT/community/members.bml?authas=" . $u->user . "'>$ML{'.section.edit'}</a>]</span>" if $remote && $remote->can_manage($u);
1241             $body .= "</div>";
1242             $body .= "<div class='section_body'>";
1244             my $poll_id = $u->prop('election_poll_id');
1245             my $show_owner = 0;
1246             if ($poll_id) {
1247                 my $poll = LJ::Poll->new ($poll_id);
1248                 my @q = $poll->questions;
1249                 my @items = @q ? $q[0]->items : ();
1250                 foreach my $item (@items) {
1251                     $show_owner = 1 if $remote && ($item->{item} =~ m#<lj user='$remote->{user}'>#);
1252                 }
1253             }
1254             if (($poll_id && $show_owner ) || scalar @$super_maintainers) {
1255                 $body .= "<p class='inner_section_header first'><span class='expandcollapse on' id='smaints_header'>" . $arrowimg->("smaints") .
1256                          " $ML{'.label.super_maintainers'}:</span></p>";
1257                 $body .= "<div class='inner_section_body' id='smaints_body'>";
1258                 if (scalar @$super_maintainers) {
1259                     $body .= $listusers->([map { $userhash{$_} } @$super_maintainers], 'smaint')
1260                 } elsif ($show_owner) {
1261                     $body .= LJ::Lang::ml('userinfo.admins.owner.election.link', {
1262                                     href => "href='$LJ::SITEROOT/community/election.bml?authas=$u->{user}'"
1263                             });
1264                 }
1265                 $body .= "</div>";
1266             }
1268             $body .= "<p class='inner_section_header'><span class='expandcollapse on' id='maints_header'>" . $arrowimg->("maints") .
1269                      " $ML{'.label.maintainers'} (" . scalar @maintlist .
1270                      "):</span></p>";
1271             $body .= "<div class='inner_section_body' id='maints_body'>" . $listusers->(\@maintlist, 'maint') . "</div>";
1273             # moderators
1274             if ($u->{'moderated'} && scalar @$moderators) {
1275                 my @modlist = sort { $a->{'user'} cmp $b->{'user'} }
1276                               map { $userhash{$_} } @$moderators;
1278                 if (scalar @modlist) {
1279                     $body .= "<p class='inner_section_header'><span class='expandcollapse on' id='mods_header'>" . $arrowimg->("mods") .
1280                              " $ML{'.label.moderators'} (" . scalar @modlist .
1281                              "):</span></p>";
1282                     $body .= "<div class='inner_section_body' id='mods_body'>" . $listusers->(\@modlist, 'mod') . "</div>";
1283                 }
1284             }
1286             $body .= "</div>";
1287         }
1288     }
1290     my $mutual;  # Mutual friends
1291     my $fofs;    # Friends of
1292     my $mofs;    # Member of
1293     my $posting; # Posting access
1294     # friend of and mutual friends display
1295     # there are two options that will affect what gets shown below: opt_hidefriendofs, opt_showmutualfriends
1296     # if the option to show mutual friends is on, then what was known as the friend of list is broken down
1297     # into two lists: mutual friends (people you list and who also list you back) and 'also friend of', which
1298     # lists the people you don't also list as friends.  you can hide your friend of list, and leave just
1299     # your mutual friends list showing, or you can not split them and have both be hidden.
1300     unless ($synd) {
1301         if ($friendsof{'loaded'}) {
1302             my $label;
1303             if ($u->show_mutualfriends && (my $n_friends = $fro_m->mutual_friends)) {
1304                 $label = $ML{'.friends.mutual'};
1305                 my $count = 1;
1306                 my $bold_mutual = ! LJ::u_equals($remote, $u);
1307                 my $clipped = 0; # bool
1308                 my $list;
1309                 foreach my $mf ($fro_m->mutual_friends) {
1310                     if ($count > $pm->max_friendof_show && $GET{'mode'} ne "full") {
1311                         $clipped = 1;
1312                         last;
1313                     }
1314                     my $frlink = "<a href='" . $mf->profile_url . "' rel='friend'>" . $mf->display_name . "</a>";
1315                     $frlink = "<b>$frlink</b>" if $bold_mutual && $remote_friendid{$mf->{'userid'}};
1316                     $list .= "$frlink, ";
1317                     $count++;
1318                 }
1319                 chop $list; chop $list;
1320                 $mutual .= "<p class='inner_section_header'><span class='expandcollapse on' id='mutual_header'>" . $arrowimg->("mutual");
1321                 $mutual .= " $label ($n_friends):</span></p>";
1322                 $mutual .= "<div class='inner_section_body' id='mutual_body'>$list";
1323                 if ($clipped) {
1324                     my $profile_url = $u->profile_url( full => 1 );
1325                     $mutual .= ", <a href='$profile_url'>...</a>";
1326                 }
1327                 $mutual .= "</div>\n";
1328             }
1329             if ($friendsof{'display'} && (my $n_friends = $fro_m->friend_ofs)) {
1330                 $label = $com ? $ML{'.members.watchedby'} :
1331                          ($u->show_mutualfriends ? $ML{'.friends.alsofriendof'} : $ML{'.friends.friendof'});
1332                 my $count = 1;
1333                 my $clipped = 0; # bool
1334                 my $list;
1335                 foreach my $fr ($fro_m->friend_ofs) {
1336                     if ($count > $pm->max_friendof_show && $GET{'mode'} ne "full") {
1337                         $clipped = 1;
1338                         last;
1339                     }
1340                     my $frlink;
1341                     my $nofollow = $remote_friendid{$fr->{'userid'}} ? "" : " rel='nofollow'";
1342                     if ($fr->{'journaltype'} eq "P") {
1343                         $frlink = "<a$nofollow href='" . $fr->profile_url . "'>$fr->{'user'}</a>";
1344                     } elsif ($fr->{'journaltype'} eq "I") {
1345                         $frlink = "<a$nofollow href=\"$LJ::SITEROOT/userinfo.bml?userid=$fr->{'userid'}&amp;t=I\">" . LJ::ehtml($fr->display_name) . "</a>";
1346                     }
1347                     $frlink = "<b>$frlink</b>" if $remote_friendid{$fr->{'userid'}};
1348                     $list .= "$frlink, ";
1349                     $count++;
1350                 }
1351                 chop $list; chop $list;
1352                 $fofs .= "<p class='inner_section_header'><span class='expandcollapse on' id='fofs_header'>" . $arrowimg->("fofs") . " $label ($n_friends):</span>";
1353                 if ($u->{'opt_hidefriendofs'}) {
1354                     $fofs  .= " <i>$ML{'.friendof.hidden'}</i>";
1355                 }
1356                 $fofs .= "</p>";
1357                 $fofs .= "<div class='inner_section_body' id='fofs_body'>$list";
1358                 if ($clipped) {
1359                     my $profile_url = $u->profile_url( full => 1 );
1360                     $fofs .= ", <a href='$profile_url'>...</a>";
1361                 }
1362                 $fofs .= "</div>\n";
1363             }
1364             if ($friendsof{'display'} && (my $n_friends = $fro_m->member_of)) {
1365                 $label = $ML{'.comms.memberof'};
1366                 my @memberof = $fro_m->member_of;
1367                 my (@alt_memberof, @alt2_memberof);
1368                 my ($alt_clabel, $alt2_clabel);
1369                 LJ::run_hook("userinfo_alt_cfriends", \@memberof, \@alt_memberof, \$alt_clabel, \@alt2_memberof, \$alt2_clabel, labels => 1);
1370                 my $list;
1371                 foreach my $cu (@memberof) {
1372                     my $frlink = "<a href='" . $cu->profile_url . "' rel='group'>$cu->{'user'}</a>";
1373                     $frlink = "<b>$frlink</b>" if $remote_friendid{$cu->{'userid'}};
1374                     $list .= "$frlink, ";
1375                 }
1376                 chop $list; chop $list;
1378                 $mofs .= "<p class='inner_section_header'><span class='expandcollapse on' id='mofs_header'>" . $arrowimg->("mofs") . " $label (" . (scalar @memberof + scalar @alt_memberof + scalar @alt2_memberof) . "):</span>";
1379                 if ($u->{'opt_hidefriendofs'}) {
1380                     $mofs  .= " <i>$ML{'.friendof.hidden'}</i>";
1381                 }
1382                 $mofs .= "</p><div class='inner_section_body' id='mofs_body'>$list\n";
1384                 $list = undef;
1385                 foreach my $cu (@alt_memberof) {
1386                     my $frlink = "<a href='" . $cu->profile_url . "' rel='group'>$cu->{'user'}</a>";
1387                     $frlink = "<b>$frlink</b>" if $remote_friendid{$cu->{'userid'}};
1388                     $list .= "$frlink, ";
1389                 }
1390                 chop $list; chop $list;
1391                 $mofs .= "<p class='alt_friends'><span class='inner_section_header'>$alt_clabel (" . scalar @alt_memberof ."):</span> <span class='inner_section_body'>$list</span></p>\n"
1392                     if scalar @alt_memberof;
1394                 $list = undef;
1395                 foreach my $cu (@alt2_memberof) {
1396                     my $frlink = "<a href='" . $cu->profile_url . "' rel='group'>$cu->{'user'}</a>";
1397                     $frlink = "<b>$frlink</b>" if $remote_friendid{$cu->{'userid'}};
1398                     $list .= "$frlink, ";
1399                 }
1400                 chop $list; chop $list;
1401                 $mofs .= "<p class='alt_friends'><span class='inner_section_header'>$alt2_clabel (" . scalar @alt2_memberof ."):</span> <span class='inner_section_body'>$list</span></p>\n"
1402                     if scalar @alt2_memberof;
1404                 $mofs .= "</div>";
1405             }
1406         }
1408         ###
1409         ### posting access
1410         ###
1411         # Display if logged-in and one of the following:
1412         # - Viewing own profile
1413         # - Viewing a community you admin
1414         # - Has support priv and mode=full in query string
1415         if ($remote && (($remote && $remote_isowner) ||
1416             ($com && LJ::can_manage_other($remote, $u)) ||
1417              ($GET{'mode'} eq "full" &&
1418               (LJ::check_priv($remote, "supportviewscreened") ||
1419                LJ::check_priv($remote, "supporthelp")) ) ) ) {
1420             my $list;
1421             my $label;
1422             if ($com || $u->{'journaltype'} eq 'S') {
1423                 # load user who can post to this community
1424                 $list = LJ::load_rel_user($u, 'P');
1425                 $label = $ML{'.members.postingaccess'};
1426             } else {
1427                 # load communities/accounts this user can post to
1428                 $list = LJ::load_rel_target($u, 'P');
1429                 $label = $ML{'.comms.postingaccess'};
1430             }
1431             my %u;
1432             my @ids = @$list;
1433             my $count = @ids;
1434             my $chopped = 0;
1435             my $CHOP_POINT = 500;
1436             if (@ids > $CHOP_POINT) {
1437                 @ids = splice(@ids, 0, $CHOP_POINT);
1438                 $chopped = 1;
1439             }
1440             LJ::load_userids_multiple([ map { $_ => \$u{$_} } @ids ]);
1441             my @accesslist = sort { $a->{user} cmp $b->{user} } grep { $_->is_visible } values %u;
1442             my (@alt_access, @alt2_access);
1443             my ($alt_label, $alt2_label);
1445             LJ::run_hook("userinfo_alt_cfriends", \@accesslist, \@alt_access, \$alt_label, \@alt2_access, \$alt2_label, labels => 1);
1447             if (my $vcount = @accesslist) {
1448                 $count = $vcount if $count < $CHOP_POINT;
1450                 my @accesslist_strings;
1451                 foreach my $au (@accesslist) {
1452                     my $frlink = "<a href='" . $au->profile_url . "'>" . $au->display_username . "</a>";
1453                     $frlink = "<b>$frlink</b>" if $remote_friendid{$au->id};
1454                     push @accesslist_strings, $frlink;
1455                 }
1457                 $posting .= "<p class='inner_section_header'><span class='expandcollapse on' id='posting_header'>" . $arrowimg->("posting") . " $label (" . ($count + scalar @alt_access + scalar @alt2_access) . "):</span>";
1458                 $posting .= " <i>$ML{'.friendof.hidden'}</i></p>";
1459                 $posting .= "<div class='inner_section_body' id='posting_body'>";
1460                 $posting .= join(", ", @accesslist_strings);
1461                 $posting .= ", ..." if $chopped;
1462             }
1464             $list = undef;
1465             foreach my $cu (@alt_access) {
1466                 my $frlink = "<a href='" . $cu->profile_url . "' rel='group'>$cu->{'user'}</a>";
1467                 $frlink = "<b>$frlink</b>" if $remote_friendid{$cu->{'userid'}};
1468                 $list .= "$frlink, ";
1469             }
1470             chop $list; chop $list;
1471             $posting .= "<p class='alt_friends'><span class='inner_section_header'>$alt_label (" . scalar @alt_access ."):</span> <span class='inner_section_body'>$list</span></p>\n"
1472                 if scalar @alt_access;
1474             $list = undef;
1475             foreach my $cu (@alt2_access) {
1476                 my $frlink = "<a href='" . $cu->profile_url . "' rel='group'>$cu->{'user'}</a>";
1477                 $frlink = "<b>$frlink</b>" if $remote_friendid{$cu->{'userid'}};
1478                 $list .= "$frlink, ";
1479             }
1480             chop $list; chop $list;
1481             $posting .= "<p class='alt_friends'><span class='inner_section_header'>$alt2_label (" . scalar @alt2_access ."):</span> <span class='inner_section_body'>$list</span></p>\n"
1482                 if scalar @alt2_access;
1484             $posting .= "</div>" if @accesslist;
1485         }
1487     }
1489     ##
1490     ## friends
1491     ##
1492     my $comms;
1493     my $feeds;
1494     my $friend_edit_link;
1495     if ($remote && $remote->can_manage($u)) {
1496         if ($u->is_community) {
1497             $friend_edit_link = " <span class='section_link'>[<a href='$LJ::SITEROOT/community/members.bml?authas=" . $u->user . "'>$ML{'.section.edit'}</a>]</span>";
1498         } else {
1499             $friend_edit_link = " <span class='section_link'>[<a href='$LJ::SITEROOT/friends/edit.bml'>$ML{'.section.edit'}</a>]</span>";
1500         }
1501     }
1503     unless ($synd || $LJ::FORCE_EMPTY_FRIENDS{$userid}) {
1504         $body .= "<div class='ljclear'></div>";
1505         my $label;
1506         if ($com) {
1507             $label = $ML{'.members.header'};
1508             $body .= "<div class='section'>$label$friend_edit_link <span class='section_link'>[<a href='" . $u->journal_base . "/friends'>$ML{'.friends.viewentries'}</a>]</span></div>";
1509             $body .= "<div class='section_body'>";
1510         } else {
1511             $label = $ML{'.friends.header'};
1512             $body .= "<div class='section'><img src='$LJ::IMGPREFIX/userinfo.gif?v=17080' alt='' /> $label$friend_edit_link <span class='section_link'>[<a href='" . $u->journal_base . "/friends?show=P'>$ML{'.friends.viewentries'}</a>]</span></div>";
1513             $body .= "<div class='section_body'>";
1514         }
1516         $friends{'display'} = 0 if $friends{'count'} > $pm->max_friends_show;
1517         my $should_show_friends = $friends{'loaded'} && $friends{'display'};
1518         my $viewall_url = "$LJ::SITEROOT/tools/friendlist.bml?user=$user&nopics=1";
1520         if ($u->is_person || $u->is_shared || $u->is_identity) {
1521             # personal/shared journals have a special way of showing their friends list, it breaks it down into
1522             # three sublists: personal/shared/identity, community/news, syndication
1523             my (@pfriends, @cfriends, @yfriends);
1524             my $friend_link = sub {
1525                 my $f = shift;
1526                 return unless $show_user->($f);
1528                 # Add XFN markup
1529                 my $rel = '';
1530                 if ($f->is_person || $f->is_shared || $f->is_identity) {
1531                     $rel = " rel='friend'";
1532                 } elsif ($f->is_community || $f->is_news) {
1533                     $rel = " rel='group'";
1534                 }
1536                 my $frlink = "<a href='" . $f->profile_url . "'$rel>" . LJ::ehtml($f->display_name) . "</a>";
1537                 $frlink = "<strike>$frlink</strike>" if $is_invisible->($f);
1538                 $frlink = "<b>$frlink</b>" if $remote_friendid{$f->{'userid'}} && $remote->{'userid'} != $u->{'userid'};
1539                 return $frlink;
1540             };
1542             foreach my $f (@friends) {
1543                 push @pfriends, $f if $f->is_person or $f->is_shared or $f->is_identity;
1544                 push @cfriends, $f if $f->is_community or $f->is_news;
1545                 push @yfriends, $f if $f->is_syndicated;
1546             }
1548             my (@alt_cfriends, @alt2_cfriends);
1549             my ($alt_clabel, $alt2_clabel);
1550             # Run hook for xtra special community category
1551             LJ::run_hook("userinfo_alt_cfriends", \@cfriends, \@alt_cfriends, \$alt_clabel, \@alt2_cfriends, \$alt2_clabel, labels => 1);
1553             # Make into friend links
1554             foreach my $list (\@pfriends, \@cfriends, \@yfriends, \@alt_cfriends, \@alt2_cfriends) {
1555                $list = [] unless ref $list;
1556                @$list = map { $friend_link->($_) } @$list;
1557             }
1559             my $pfriends = join ', ', @pfriends;
1560             my $yfriends = join ', ', @yfriends;
1561             my $cfriends = join ', ', @cfriends;
1562             my $alt_cfriends = join ', ', @alt_cfriends;
1563             my $alt2_cfriends = join ', ', @alt2_cfriends;
1565             my $viewall_string = $remote && $remote->equals($u) ?
1566                     BML::ml('.friends.viewall.self', { num => $friends{count}, aopts => "href='$viewall_url'" }) :
1567                     BML::ml('.friends.viewall.other', { num => $friends{count}, aopts => "href='$viewall_url'" });
1569             # now spit out the HTML
1571             my $text = $ML{'.friends.friends'};
1572             $body .= "<p class='inner_section_header first'><span class='expandcollapse on' id='friends_header'>" . $arrowimg->("friends") . " $text";
1573             $body .= " (" . scalar @pfriends . ")" if $should_show_friends;
1574             if (!$should_show_friends) {
1575                 $body .= ":</span></p><div class='inner_section_body' id='friends_body'>$viewall_string</div>";
1576             } elsif ($pfriends) {
1577                 $body .= ":</span></p><div class='inner_section_body' id='friends_body'>$pfriends</div>";
1578             } else {
1579                 $body .= "</span></p>";
1580             }
1581             $body .= $mutual if ($mutual);
1582             $body .= $fofs if ($fofs);
1584             my $text = $ML{'.comms.watching'};
1585             $comms .= "<p class='inner_section_header first'><span class='expandcollapse on' id='watching_header'>" . $arrowimg->("watching") . " $text";
1586             $comms .= " (" . (scalar @cfriends + scalar @alt_cfriends + scalar @alt2_cfriends) . ")" if $should_show_friends;
1587             if (!$should_show_friends) {
1588                 $comms .= ":</span></p><div class='inner_section_body' id='watching_body'>$viewall_string</div>";
1589             } elsif ($cfriends || $alt_cfriends || $alt2_cfriends) {
1590                 $comms .= ":</span></p><div class='inner_section_body' id='watching_body'>$cfriends";
1591                 $comms .= "<p class='alt_friends'><span class='inner_section_header'>$alt_clabel (" . scalar @alt_cfriends . "):</span> <span class='inner_section_body'>$alt_cfriends</span></p>"
1592                     if $alt_cfriends;
1593                 $comms .= "<p class='alt_friends'><span class='inner_section_header'>$alt2_clabel (" . scalar @alt2_cfriends . "):</span> <span class='inner_section_body'>$alt2_cfriends</span></p>"
1594                     if $alt2_cfriends;
1595                 $comms .= "</div>";
1596             } else {
1597                 $comms .= "</span></p>";
1598             }
1600             my $text = $ML{'.syn.watching'};
1601             $feeds .= "<p class='inner_section_header first'><span class='expandcollapse on' id='watchingfeeds_header'>" . $arrowimg->("watchingfeeds") . " $text";
1602             $feeds .= " (" . scalar @yfriends . ")" if $should_show_friends;
1603             if (!$should_show_friends) {
1604                 $feeds .= ":</span></p><div class='inner_section_body' id='watchingfeeds_body'>$viewall_string</div>";
1605             } elsif ($yfriends) {
1606                 $feeds .= ":</span></p><div class='inner_section_body' id='watchingfeeds_body'>$yfriends</div>";
1607             } else {
1608                 $feeds .= "</span></p>";
1609             }
1611         } else {
1612             $body .= "<p class='inner_section_header first'><span class='expandcollapse on' id='members_header'>" . $arrowimg->("members") . " $ML{'.members.members'}";
1613             $body .= " (" . $friends{'count'} . ")" if $should_show_friends;
1615             if (!$should_show_friends) {
1616                 $body .= ":</span></p><div class='inner_section_body' id='members_body'>" . BML::ml('.friends.viewall.comm2', { aopts => "href='$viewall_url'" }) . "</div>";
1617             } elsif ($friends{count}) {
1618                 $body .= ":</span></p><div class='inner_section_body' id='members_body'>" . $listusers->(\@friends, 'member') . "</div>";
1619             } else {
1620                 $body .= "</span></p>";
1621             }
1622             $body .= $fofs if ($fofs);
1623             $body .= $posting if ($posting);
1624         }
1625         $body .= "</div>";
1627         unless ($com) {
1628             $comms .= "$mofs" if ($mofs);
1629             $comms .= "$posting" if ($posting);
1630             next unless $comms;
1631             $body .= "<div class='ljclear'></div>";
1632             $body .= "<div class='section'><img src='$LJ::IMGPREFIX/community.gif?v=556' alt='' /> $ML{'.comms.header'}$friend_edit_link <span class='section_link'>[<a href='" . $u->journal_base . "/friends?show=C'>$ML{'.friends.viewentries'}</a>]</span></div>";
1633             $body .= "<div class='section_body'>$comms</div>";
1634             if ($feeds) {
1635                 $body .= "<div class='ljclear'></div><div class='section'><img src='$LJ::IMGPREFIX/syndicated.gif?v=6283' alt='' /> $ML{'.syn.header'}$friend_edit_link <span class='section_link'>[<a href='" . $u->journal_base . "/friends?show=Y'>$ML{'.friends.viewentries'}</a>]</span></div>";
1636                 $body .= "<div class='section_body'>$feeds</div>";
1637             }
1638         }
1639     }
1641     if (LJ::is_enabled('userapps') && ($u->is_personal || $u->is_identity)) {
1642         my $apps_list = LJ::JSON->from_json($u->prop('userapps_authorized')||'{}');
1643         my @userapps;
1645         foreach (sort keys %$apps_list) {
1646             my $app = LJ::UserApps->get_application( id => $_ );
1647             next unless $app && $app->can_show_restricted && $app->{type} ne 'E'; 
1648             my $app_img;
1649             if ($app->icon) {
1650                 $app_img = '<img src='.$app->icon.' width="16" height="16" alt="' . $app->name . '" /> ';
1651             }
1652             my $app_string = '<li>'.$app_img.'<a href="'.$app->href.'">'. $app->name.'</a></li>';
1653             push @userapps, $app_string;
1654         }
1656         my $text = $ML{'.apps.installed'};
1657         my $apps = "<div class='section_body'><p class='inner_section_header first'><span class='expandcollapse on' id='apps_header'>".$arrowimg->("apps")." $text (".scalar(@userapps).")</span></p>";
1658         $apps .= '<div id="apps_body" class="inner_section_body">';
1659         $apps .= '<ul class="b-app-user-list">';
1660         $apps .= join("", @userapps);
1661         $apps .= '</ul>';
1662         $apps .= LJ::Widget::ApplicationsViewsLayout->render(view_id => 'PROFILE', owner => $u, viewer => $remote, GET => \%GET);
1663         $apps .= '</div>';
1664         $apps .= '</div>';
1666         $body .= "<div class='ljclear'></div>";
1667         $body .= "<div class='section' id='apps'><img src='$LJ::IMGPREFIX/application.gif?v=10093' alt='' /> $ML{'.apps.header'} ";
1668         $body .= "<span class='section_link'>[<a href='$LJ::SITEROOT/manage/settings/?cat=userapps'>$ML{'.section.edit'}</a>]</span> " if $remote && $remote->can_manage($u);
1669         $body .= "<span class='section_link'>[<a href='$LJ::SITEROOT/games/info.bml?user=".$u->username."'>$ML{'.section.view_all'}</a>]</span></div>";
1670         $body .= $apps;
1671     }
1673     # Music
1674     my $playlist_id = $u->prop('playlist_id');
1676     if ( LJ::Setting::Music::Trava::good_ip() &&
1677          LJ::is_enabled('userplaylist') &&
1678          ($u->is_personal || $u->is_identity) &&
1679          (( $remote && $remote->can_manage($u) && LJ::Setting::Music->should_show_playlist($u) ) ||
1680           $playlist_id)
1681        ) {
1682         my $res = '';
1684         if ( $playlist_id > -1 ) {
1685             my $key = $LJ::TRAVA_API_KEY;
1686             $res .= qq~<object width="450" height="158" data="http://trava.ru/swfs/TravaPlaylistWidget2.swf" type="application/x-shockwave-flash">
1687                 <param name="movie" value="http://trava.ru/swfs/TravaPlaylistWidget2.swf" />
1688                 <param value="transparent" name="wmode">
1689                 <param name="FlashVars" value="playlistId=$playlist_id&partnerKey=$key">
1690                 <param value="true" name="allowfullscreen">
1691             </object>~
1692         }
1693         else {
1694             $res .= $ML{'.playlist.not_selected'};
1695         }
1697         $body .= "<div class='ljclear'></div>";
1698         $body .= "<div class='section' id='apps'><span class='expandcollapse on' id='playlist_header'>" . $arrowimg->("playlist") . "$ML{'.playlist.header'}</span> ";
1699         $body .= "<span class='section_link'>[<a href='$LJ::SITEROOT/manage/profile/?authas=" . $u->user . "#userplaylist'>$ML{'.section.edit'}</a>]</span> " if $remote && $remote->can_manage($u);
1700         $body .= "</div>";
1701         $body .= "<div class='section_body' id='playlist_body'>\n";
1702         $body .= $res;
1703     }
1705     $body .= LJ::get_ads({ location => 'bml.userinfo.bottom', journalu => $u });
1707     $body .= "</div>";
1709     $body .= LJ::Widget::SettingWindow->render;
1711     $bml_okay = 0;
1712     return;
1714 _code?><?page
1715 windowtitle=><?_code return $windowtitle; _code?>
1716 title=><?_code return $title; _code?>
1717 body=><?_code return $bml_okay ? $body : BML::noparse($body); _code?>
1718 head<=
1719 <?_code
1721     LJ::need_res('stc/profile.css', 'js/profile.js',
1722        'js/ippu.js',
1723        'js/lj_ippu.js',
1724        'js/httpreq.js',
1725        'js/ljwidget.js',
1726        'js/ljwidget_ippu.js',
1727        'js/widget_ippu/vgiftsmspay.js',
1728        'js/inputcomplete.js',
1729        'stc/widgets/applicationsviewslayout.css'
1731     );
1732     return $head;
1734 _code?>
1735 <=head
1736 page?>