1 package LJ
::SiteScheme
;
8 use LJ
::Auth
::Challenge
;
9 use LJ
::Widget
::SGMessages
;
10 use LJ
::User
::FriendInvites
;
12 my %CODE_TO_CLASS_MAP;
14 ### PARENT CLASS FUNCTIONS ###
16 my ( $class, $args ) = @_;
20 if ( $class eq __PACKAGE__
) {
21 $handler = $class->find_handler;
28 my $filename = "$ENV{'LJHOME'}/templates/SiteScheme/"
29 . $handler->template_filename . '.tmpl';
31 LJ
::need_var
( 'scheme' => $handler->code );
33 # cast all keys to lowercase because uppercase everywhere is creepy
34 my $args_normalized = {};
35 foreach my $k ( keys %$args ) {
36 $args_normalized->{ lc $k } = $args->{$k};
39 my $params = $handler->template_params($args_normalized);
41 if ( LJ
::is_web_context
() ) {
42 LJ
::Request
->notes ( using_site_scheme
=> 1 );
43 $params->{'lj_res_in_bottom'} = $args->{'lj_res_in_bottom'} || (LJ
::Request
->get_param('res_bottom') ?
1 : 0);
44 $params->{'lj_res_includes'} = LJ
::res_includes
({ no_sitewide_css
=> $params->{'no_sitewide_css'} });
45 $params->{'lj_res_includes_basic'} = LJ
::res_includes
({ only_needed
=> 1 });
46 $params->{'lj_res_templates'} = LJ
::res_includes
({ only_needed
=> 1, only_tmpl
=> 1 });
47 $params->{'lj_res_includes_css'} = LJ
::res_includes
({ only_css
=> 1, no_sitewide_css
=> $params->{'no_sitewide_css'} });
48 $params->{'lj_res_includes_js'} = LJ
::res_includes
({ only_js
=> 1, no_sitewide_css
=> $params->{'no_sitewide_css'} });
51 my $template = LJ
::HTML
::Template
->new( { 'use_expr' => 1 },
52 'filename' => $filename, );
54 $template->param(%$params);
56 return $template->output;
62 my $usescheme = LJ
::Request
->get_param('usescheme');
64 return $class->handler_from_code('schemius')
65 if LJ
::is_enabled
('schemius');
67 return $class->handler_from_code($usescheme) || $class->handler_from_code('schemius')
68 if LJ
::is_enabled
('schemius_with_usescheme');
70 my @candidate_codes = (
71 LJ
::Request
->notes('bml_use_scheme'),
72 LJ
::run_hook
('force_scheme'),
74 LJ
::Request
->cookie('BMLschemepref'),
75 LJ
::run_hook
('default_scheme'),
79 foreach my $code (@candidate_codes) {
80 next unless defined $code;
82 my $handler = $class->handler_from_code($code);
83 next unless defined $handler;
88 # this shouldn never happen because we always have lynx
89 die 'no scheme found';
92 sub handler_from_code
{
93 my ( $class, $code ) = @_;
95 return undef unless $code;
96 return $CODE_TO_CLASS_MAP{$code};
99 ### PARENT CLASS UTILITY FUNCTIONS ###
101 sub template_param_breadcrumbs
{
104 my @crumbs = LJ
::get_crumb_path
();
105 return [] unless @crumbs;
109 foreach my $crumb (@crumbs) {
110 my ( $name, $link, $parent, $type ) = @
$crumb;
112 # put crumbs together
113 next unless $type; # no blank crumbs
114 if ( $type eq 'dynamic' ) {
115 unshift @ret, { 'is_dynamic' => 1, 'name' => $name };
117 unshift @ret, { 'name' => ml
("crumb.$type"), 'link' => $link };
124 sub show_mobile_link
{
125 return 0 if LJ
::Request
->cookie ('hide_mobile_link');
126 return 1 if LJ
::is_enabled
('view_mobile_link_always');
127 return 1 if Apache
::WURFL
->is_mobile;
131 sub lentaru_branding
{
132 return 1 if LJ
::is_enabled
('show_olympic_games_widget_2014');
133 my $time_start = 1391868000; # 08.02.2014 00:00 MSK
134 my $time_end = 1393164000; # 23.02.2014 23:59 MSK
136 return unless time > $time_start && time < $time_end;
138 if ( LJ
::get_remote
() ) {
139 return LJ
::SUP
->is_remote_sup();
143 my $country = LJ
::GeoLocation
->get_country_info_by_ip();
145 return unless $country;
146 return $country eq 'RU' || $country eq 'UA' || $country eq 'BY';
149 sub common_template_params
{
150 my ( $class, $args ) = @_;
152 my $remote = LJ
::get_remote
();
153 my $uri = LJ
::Request
->uri;
155 my $remote_username = '';
157 $remote_username = $remote->username;
160 my $lj_home = $LJ::SITEROOT
;
163 if ( my $journal = LJ
::get_active_journal
() ) {
164 if ( $journal->is_personal ) {
165 ($favicon) = $journal->userhead;
166 $favicon = $LJ::IMGPREFIX
. "/" . $favicon
167 unless $favicon =~ m{^http://};
169 if ( $journal->username() eq 'lj_singapore') {
170 $lj_home = 'http://www.livejournal.sg';
174 my $ie8_ie7_compatible = 1;
175 if ( defined $args->{'ie8_ie7_compatible'} &&
176 ! $args->{'ie8_ie7_compatible'} )
178 $ie8_ie7_compatible = 0;
181 my $additional_head_content = '';
182 LJ
::run_hooks
( 'head_content', \
$additional_head_content );
184 my $current_lang = LJ
::Lang
::current_language
();
185 my $html_lang = $LJ::LANG_TO_HTML_LANG
{$current_lang} || $current_lang;
188 if ( my @errors = @BMLCodeBlock::errors
) {
190 my $err = LJ
::errobj
($_);
192 my $errstr = $err->as_bullets;
194 } grep { $_ } @errors;
197 my $warning_list = '';
198 if ( my @warnings = @BMLCodeBlock::warnings
) {
199 $warning_list = LJ
::warning_list
(@warnings);
202 my $chalresp_js = '';
203 if ( !LJ
::get_remote
()
205 && !$LJ::USE_SSL_LOGIN
206 && !$LJ::REQ_HEAD_HAS
{'chalresp_js'}++ )
208 $chalresp_js = $LJ::COMMON_CODE
{'chalresp_js'};
211 my $after_bml_title = LJ
::run_hook
('insert_after_bml_title') || '';
213 my $show_mobile_link = $class->show_mobile_link;
214 my $ml_mobile_link = '';
215 if ($show_mobile_link) {
218 $uri .= $LJ::IS_SSL ?
'https://' : 'http://';
219 $uri .= LJ
::Request
->hostname;
220 $uri .= LJ
::Request
->uri;
222 if ( my $args = LJ
::Request
->args ) {
227 "http://m.$LJ::DOMAIN/redirect?from=" . LJ
::eurl
($uri);
230 ml
( 'link.mobile', { 'href' => "href='$mobile_uri'" }, );
233 my $initial_body_html = LJ
::initial_body_html
();
235 my $site_messages_html = '';
236 if ( LJ
::Widget
::SiteMessages
->should_render ) {
237 $site_messages_html = LJ
::Widget
::SiteMessages
->render;
240 my @navbar = LJ
::Nav
->navbar($remote);
242 # apparently our HTML::Template doesn't support __index__,
243 # let's provide one ourselves; lanzelot requires this for
245 $navbar[$_]->{'idx'} = $_ foreach ( 0 .. $#navbar );
247 my $expresslane_html_comment =
248 LJ
::LJcom
::expresslane_html_comment
($remote);
250 my $remote_logged_in = $remote ?
1 : 0;
251 my $remote_personal = 0;
252 my $remote_identity = 0;
254 my $remote_sees_ads = 0;
255 my $logout_link = '';
256 my $remote_sessid = 0;
257 my $remote_userpic_url = '';
258 my $remote_ljuser_display = '';
259 my $remote_display_name = '';
260 my $remote_profile_url = '';
261 my $remote_recent_url = '';
262 my $remote_friends_url = '';
263 my $remote_can_use_esn = 0;
264 my $remote_unread_count = 0;
265 my $remote_wallet_link = 0;
266 my $remote_ljphoto_url = '';
267 my $remote_can_use_ljphoto = 0;
268 my $remote_is_sup = 0;
269 my $remote_invites_count = 0;
270 my $remote_usermsg_count = 0;
273 my $username = $remote->username;
275 if ( my $session = $remote->session ) {
276 $remote_sessid = $session->id;
278 "$LJ::SITEROOT/logout.bml?user=$username&sessid=$remote_sessid";
280 $logout_link = "$LJ::SITEROOT/logout.bml?user=$username";
283 if ( my $upi = $remote->userpic ) {
284 $remote_userpic_url = $upi->url;
287 my $inbox = $remote->notification_inbox;
289 $remote_personal = $remote->is_personal;
290 $remote_identity = $remote->is_identity;
291 $remote_paid = $remote->get_cap('paid');
292 $remote_sees_ads = $remote->get_cap('ads');
293 $remote_ljuser_display = $remote->ljuser_display;
294 $remote_display_name = $remote->display_name;
295 $remote_profile_url = $remote->profile_url;
296 $remote_recent_url = $remote->journal_base . '/';
297 $remote_friends_url = $remote->journal_base . '/friends/';
298 $remote_can_use_esn = $remote->can_use_esn;
299 $remote_unread_count = $inbox->unread_count;
300 $remote_usermsg_count = $inbox->unread_message_count;
301 $remote_wallet_link = LJ
::Pay
::Wallet
->get_wallet_link($remote);
302 $remote_ljphoto_url = $remote->journal_base . '/pics/';
303 $remote_can_use_ljphoto = $remote->can_use_ljphoto ?
1 : 0;
304 $remote_is_sup = LJ
::SUP
->is_remote_sup();
305 $remote_invites_count = LJ
::User
::FriendInvites
->count_recv_invites($remote);
308 my $need_loginform = 0;
310 my $loginform_returnto = '';
311 my $loginform_root = '';
312 my $loginform_challenge = '';
313 my $loginform_need_extra_fields = 0;
314 my $loginform_onclick = '';
316 unless ( $remote || $uri eq '/login.bml' || $uri eq '/logout.bml' ) {
320 # lanzelot doesn't respect need_loginform; i. e. it renders it on
321 # login.bml and logout.bml as well
323 $loginform_returnto = LJ
::Request
->get_param('returnto') || '';
325 if ($LJ::USE_SSL_LOGIN
) {
326 $loginform_root = $LJ::SSLROOT
;
328 $loginform_root = $LJ::SITEROOT
;
329 $loginform_challenge = LJ
::Auth
::Challenge
->generate(300);
330 $loginform_need_extra_fields = 1;
331 $loginform_onclick = "onclick='return sendForm()'";
336 if ($LJ::IS_DEV_SERVER
) {
337 $dev_banner = $LJ::DEV_BANNER
;
340 my $pagestats_obj = LJ
::pagestats_obj
();
341 my $pagestats_html = $pagestats_obj->render;
343 my $before_body_close = '';
344 if ( LJ
::get_active_journal
() ) {
345 LJ
::run_hooks
( 'insert_html_before_journalctx_body_close',
346 \
$before_body_close, );
349 my $final_body_html = LJ
::final_body_html
();
352 my ( $ad_beforecrumbs, $ad_aftertitle, $ad_bottom, $ad_beforetitle ) =
355 unless ($LJ::IS_SSL
) {
357 LJ
::get_ads
( { 'location' => 'look.top.beforecrumbs' } );
360 LJ
::get_ads
( { 'location' => 'look.top.aftertitle' } );
362 $ad_bottom = LJ
::get_ads
( { 'location' => 'look.bottom' } );
365 LJ
::get_ads
( { 'location' => 'look.top.beforetitle' } );
369 my $uri_tos = LJ
::run_hook
("get_tos_uri")
370 || "$LJ::SITEROOT/legal/tos.bml";
372 my $uri_privacy = LJ
::run_hook
("get_privacy_uri")
373 || "$LJ::SITEROOT/legal/privacy.bml";
375 my $uri_advertising = LJ
::run_hook
("get_advertising_url") || "#";
377 my $uri_policy = LJ
::run_hook
('get_policy_uri')
378 || "$LJ::SITEROOT/abuse/policy.bml";
380 my $uri_volunteer = $LJ::HELPURL
{'how_to_help'};
382 my $uri_developers = do {
383 my $lj_dev = LJ
::load_user
('lj_dev');
384 $lj_dev ?
$lj_dev->url : '';
387 my $uri_merchandise = LJ
::run_hook
('get_merchandise_link')
388 || 'https://www.zazzle.com/livejournal*';
390 my $ml_ljlabs_header = ml
(
391 'horizon.footer.ljlabs.header',
392 { 'sitenameabbrev' => $LJ::SITENAMEABBREV
},
396 ml
( 'horizon.footer.ljlabs.aqua',
397 { 'sitenameabbrev' => $LJ::SITENAMEABBREV
},
400 my $ml_ljlabs_dashboard = ml
(
401 'horizon.footer.ljlabs.dashboard',
402 { 'sitenameabbrev' => $LJ::SITENAMEABBREV
},
405 my $version = LJ
::run_hook
('current_version_html');
406 my $ml_copyright_header = ml
(
407 'horizon.footer.copyright.header_current',
408 { 'current_year' => $LJ::CURRENT_YEAR
},
411 ## service page branding (optional)
412 ## see also cgi-bin/LJ/Hooks/Homepage.pm
413 my $branding = LJ
::run_hook
("service_page_branding", { scheme
=> $class->code });
415 my $lentaru_branding = lentaru_branding
();
416 if ($lentaru_branding) {
418 js
/jquery/jquery
.lj
.lentaRu
.js
421 LJ
::need_string
('olympics.widget.full.standings');
422 LJ
::need_res_group
('popupus');
424 my $json = LJ
::API
::LentaRu
->get_olympics();
425 LJ
::need_var
(lentaRu
=> $json->{'result'});
427 $lentaru_branding = 0
428 if ref $json->{'result'}->{'result'}->{'team'} ne 'ARRAY';
432 'html_lang' => $html_lang,
433 'pretitle' => $args->{'pretitle'},
434 'title' => $args->{'title'},
435 'windowtitle' => $args->{'windowtitle'} || $args->{'title'},
436 'meta' => $args->{'meta'},
437 'appstore_meta' => $args->{'appstore_meta'},
438 'head' => $args->{'head'},
439 'bodyopts' => $args->{'bodyopts'},
440 'body' => $args->{'body'},
441 'page_is_ssl' => $LJ::IS_SSL ?
1 : 0,
442 'error_list' => \
@error_list,
443 'warning_list' => $warning_list,
444 'breadcrumbs' => $class->template_param_breadcrumbs,
445 'index_page' => $args->{'index_page'},
446 'chalresp_js' => $chalresp_js,
447 'after_bml_title' => $after_bml_title,
448 'show_mobile_link' => $show_mobile_link,
449 'ml_mobile_link' => $ml_mobile_link,
450 'initial_body_html' => $initial_body_html,
451 'site_messages_html' => $site_messages_html,
452 'navbar' => \
@navbar,
453 'navbar_max_idx' => $#navbar,
454 'server_signature' => $LJ::SERVER_SIGNATURE_BODY
,
455 'dev_banner' => $dev_banner,
456 'pagestats_html' => $pagestats_html,
457 'before_body_close' => $before_body_close,
458 'final_body_html' => $final_body_html,
460 'remote_logged_in' => $remote_logged_in,
461 'remote_personal' => $remote_personal,
462 'remote_identity' => $remote_identity,
463 'remote_paid' => $remote_paid,
464 'remote_sees_ads' => $remote_sees_ads,
465 'remote_username' => $remote_username,
466 'remote_sessid' => $remote_sessid,
467 'logout_link' => $logout_link,
468 'remote_userpic_url' => $remote_userpic_url,
469 'remote_ljuser_display' => $remote_ljuser_display,
470 'remote_display_name' => $remote_display_name,
471 'remote_profile_url' => $remote_profile_url,
472 'remote_recent_url' => $remote_recent_url,
473 'remote_friends_url' => $remote_friends_url,
474 'remote_can_use_esn' => $remote_can_use_esn,
475 'remote_unread_count' => $remote_unread_count,
476 'remote_usermsg_count' => $remote_usermsg_count,
477 'remote_wallet_link' => $remote_wallet_link,
478 'remote_ljphoto_url' => $remote_ljphoto_url,
479 'remote_can_use_ljphoto' => $remote_can_use_ljphoto,
480 'remote_is_sup' => $remote_is_sup,
481 'remote_invites_count' => $remote_invites_count,
483 'need_loginform' => $need_loginform,
484 'loginform_returnto' => $loginform_returnto,
485 'loginform_root' => $loginform_root,
486 'loginform_challenge' => $loginform_challenge,
487 'loginform_need_extra_fields' => $loginform_need_extra_fields,
488 'loginform_onclick' => $loginform_onclick,
490 'ie8_ie7_compatible' => $ie8_ie7_compatible,
491 'additional_head_content' => $additional_head_content,
492 'expresslane_html_comment' => $expresslane_html_comment,
493 'server_signature_title' => $LJ::SERVER_SIGNATURE_TITLE
|| '',
495 'ad_beforecrumbs' => $ad_beforecrumbs,
496 'ad_aftertitle' => $ad_aftertitle,
497 'ad_bottom' => $ad_bottom,
498 'ad_beforetitle' => $ad_beforetitle,
500 'favicon' => $favicon,
502 'uri_tos' => $uri_tos,
503 'uri_privacy' => $uri_privacy,
504 'uri_advertising' => $uri_advertising,
505 'uri_policy' => $uri_policy,
506 'uri_volunteer' => $uri_volunteer,
507 'uri_developers' => $uri_developers,
508 'uri_merchandise' => $uri_merchandise,
509 'ml_ljlabs_header' => $ml_ljlabs_header,
510 'ml_ljlabs_aqua' => $ml_ljlabs_aqua,
511 'ml_ljlabs_dashboard' => $ml_ljlabs_dashboard,
512 'version' => $version,
513 'ml_copyright_header' => $ml_copyright_header,
515 'branding' => $branding,
516 'lentaru_branding' => $lentaru_branding,
517 'random_value' => int(rand(999999999)),
519 'lj_home' => $lj_home,
521 'lj_domain' => $LJ::DOMAIN
,
523 'banner_top' => LJ
::get_ads
({location
=> 'common.banner'}) || '',
527 ### OVERRIDABLE FUNCTIONS ###
529 sub template_filename
{
534 sub code
{ die 'abstract method'; }
535 sub need_res
{ die 'abstract method'; }
536 sub template_params
{ die 'abstract method'; }
542 foreach my $class (@LJ::SUPPORTED_SCHEMES_LIST
) {
543 my $filename = $class;
544 $filename =~ s{::}{/}g;
548 $CODE_TO_CLASS_MAP{ $class->code } = $class;