qr/./); # $_[1] is a pre-request scratch area # put variables here so that we can access them later # outside of this _code block my $title = \$_[1]->{'title'}; my $head = \$_[1]->{'head'}; my $body = \$_[1]->{'body'}; my $bodyopts = \$_[1]->{'bodyopts'}; my $onload = \$_[1]->{'onload'}; $$title = $ML{'.title2'}; # invalid text input? unless (LJ::text_in(\%POST)) { $$body = ""; return; } # invalid usejournal if ($GET{usejournal} && !LJ::load_user($GET{usejournal})) { $$body = $ML{'.error.invalidusejournal'}; return; } # get remote and see if they can post right now my $remote = LJ::get_remote(); # Errors that are unlikely to change between starting # to compose an entry and submitting it. if ($remote) { return BML::redirect( LJ::create_url( "/entry/new", cur_args => \%GET, keep_args => 1 ) ) if ! LJ::did_post() && LJ::BetaFeatures->user_in_beta( $remote => "updatepage" ); if ($remote->identity) { $$title = $ML{'Sorry'}; $$body = BML::ml('.error.nonusercantpost', {'sitename' => $LJ::SITENAME}); return; } if (! $remote->can_post ) { $$title = $ML{'.error.cantpost.title'}; $$body = $LJ::MSG_NO_POST || $ML{'.error.cantpost'}; return; } } my %res = (); # see if we need to do any transformations LJ::Hooks::run_hooks("transform_update_$POST{transform}", \%GET, \%POST) if $POST{transform}; LJ::need_res( { priority => $LJ::OLD_RES_PRIORITY }, 'stc/entry.css' ); LJ::need_res('stc/display_none.css', 'stc/lj_base.css', 'js/6alib/inputcomplete.js'); ## figure out times my $now = DateTime->now; # if user has timezone, use it! if ($remote && $remote->prop("timezone")) { my $tz = $remote->prop("timezone"); $tz = $tz ? eval { DateTime::TimeZone->new(name => $tz); } : undef; $now = eval { DateTime->from_epoch(epoch => time(), time_zone => $tz); } if $tz; } my ($year, $mon, $mday, $hour, $min) = ($now->year, sprintf("%02d", $now->month), sprintf("%02d", $now->day), $now->hour, sprintf("%02d", $now->minute)); my $subject = $POST{'subject'} || $GET{'subject'}; my $event = $POST{'event'} || $GET{'event'}; my $tags = $POST{'prop_taglist'} || $GET{'prop_taglist'}; # if a share url was passed in, fill in the fields with the appropriate text if ( $GET{share} && ( my $page = DW::External::Page->new( url => $GET{share} ) ) ) { $subject = LJ::ehtml( $page->title ); $event = '' . ( LJ::ehtml( $page->description ) || $subject || $page->url ) . "\n\n"; } # try to call a hook to fill in the fields my $override_fields = LJ::Hooks::run_hook('update_fields', \%GET); my $opt_preformatted = 0; if ($override_fields) { $event = $override_fields->{'event'} if exists($override_fields->{'event'}); $subject = $override_fields->{'subject'} if exists($override_fields->{'subject'}); $tags = $override_fields->{'tags'} if exists($override_fields->{'tags'}); $opt_preformatted = $override_fields->{'prop_opt_preformatted'} if exists($override_fields->{'prop_opt_preformatted'}); } ### define some bools with common logic ### my $did_post = LJ::did_post() && !$POST{transform}; # transforms aren't posts my $user_is_remote = $remote && $remote->{'user'} eq $POST{'user'}; # user is remote my $auth_as_remote = $remote && (! $GET{'altlogin'} || $user_is_remote); # auth as remote my $auth_missing = $POST{'user'} && ! $POST{'password'} && ! $user_is_remote && ! $POST{'response'}; # user w/o password # which authentication option do we display by default? my $altlogin_display = 'none'; my $remotelogin_display = 'none'; if ($auth_as_remote) { $remotelogin_display = 'block'; } else { $altlogin_display = 'block'; } # Check for errors, store in hash to render later my $errors; my $showform = $POST{'showform'} || $auth_missing; # show entry form my $preview = $POST{'action:preview'}; # are we spellchecking before we post? my $did_spellcheck; my $spellcheck_html; if ($LJ::SPELLER && $POST{'action:spellcheck'}) { $did_spellcheck++; my $s = new LJ::SpellCheck { 'spellcommand' => $LJ::SPELLER, 'color' => '', }; $spellcheck_html = $s->check_html(\$event); $spellcheck_html = "" unless $spellcheck_html ne ""; my $date = LJ::html_datetime_decode({ 'name' => "date_ymd", }, \%POST); ($year, $mon, $mday) = split( /\D/, $date); $hour = $POST{'hour'}; $min = $POST{'min'}; } my $print_entry_form = sub { my $opts = shift; # authentication box my $auth = ''; if ($altlogin_display eq 'none') { $auth.= "

\n"; $auth .= "\n"; $auth .= "" . $remote->{user} . " $ML{'entryform.switchuser'}\n"; $auth .= "

\n\n"; } # table with username/password fields $auth .= "
"; $auth .= "

\n"; $auth .= "\n"; $auth .= LJ::html_text({ 'name' => 'user', 'id' => 'altlogin_username', 'class' => 'text', 'size' => '15', 'maxlength' => '25', 'tabindex' => '5', 'value' => $POST{'user'} || $GET{'user'} }) . "\n"; $auth .= "

\n"; $auth .= "

\n"; $auth .= "\n"; $auth .= LJ::html_text({ 'type' => 'password', 'id' => 'altlogin_password', 'class' => 'text', 'name' => 'password', 'tabindex' => '6', 'size' => '15', 'maxlength' => $LJ::PASSWORD_MAXLENGTH }) . "\n"; # posted with a user, but no password if ($did_post && $auth_missing) { $auth .= "
"; } $auth .= "

\n\n"; $auth .= "
"; # if they submit the form and are spellchecking, remember # their settings from the GET requests my $getextra = '?'; $getextra .= "altlogin=1&" if $GET{'altlogin'}; chop $getextra; # if crossposter values were checked, remember them my %xpost_vals; foreach ( grep { /^prop_xpost_/ } ( keys %POST, keys %GET ) ) { $xpost_vals{ $_ } = $POST{ $_ } || $GET{ $_ }; } my $entry = { 'mode' => "update", 'auth_as_remote' => $auth_as_remote, 'subject' => $subject, 'event' => $event, 'prop_taglist' => $tags, 'datetime' => "$year-$mon-$mday $hour:$min", 'usejournal' => LJ::canonical_username($POST{'usejournal'} || $GET{'usejournal'}), 'auth' => $auth, 'remote' => $remote, 'spellcheck_html' => $spellcheck_html, 'clientversion' => "WebUpdate/2.0.0", 'richtext' => LJ::is_enabled('richtext'), 'richtext_default' => $remote ? $remote->new_entry_editor eq 'rich' ? 1 : 0 # User setting : $LJ::DEFAULT_EDITOR eq 'rich' ? 1 : 0, # Site default 'include_insert_object' => $GET{'insobj'}, 'altlogin' => $GET{altlogin} ? 1 : 0, 'prop_opt_preformatted' => $opt_preformatted ? 1 : 0, %xpost_vals, }; if ($remote) { $entry->{prop_opt_default_noemail} = $remote->prop('opt_gettalkemail'); $entry->{prop_opt_default_nocomments} = $remote->prop('opt_showtalklinks'); $entry->{prop_opt_default_screening} = $remote->prop('opt_whoscreened'); $entry->{prop_last_fm_user} = $remote->prop('last_fm_user'); } if ($did_post) { $entry->{$_} = $POST{$_} foreach keys %POST; # Copy things over from the transform } elsif (LJ::did_post()) { foreach (qw(event_format richtext_default)) { $entry->{$_} = $POST{$_} if defined $POST{$_}; } } # If they got an error, or spellchecked, and we're in rich text mode, enable rich text mode: if ($did_post && $POST{'switched_rte_on'}) { $entry->{richtext_default} = 1; } if (LJ::isu($remote) && (!$did_post || $did_spellcheck) && $remote->readonly) { $$body .= "
"", 'a_close' => ""} ); } else { $$body .= BML::ml('.rowarn', { 'a_open' => '', 'a_close' => ''} ); } $$body .= " warningbar?>
"; } $$body .= "\n\n
\n\n"; $$body .= LJ::form_auth(); $$body .= LJ::entry_form($entry, \$$head, $onload, $errors); $$body .= "
\n"; return; }; my $okay_formauth = !$remote || LJ::check_form_auth(); if ($did_post && !$did_spellcheck && !$showform && !$preview && $okay_formauth && !$POST{'moreoptsbtn'} ) { # what's our authentication scheme for subsequent protocol actions? my $flags = {}; my ($u, $user); if ($POST{'user'} && # user argument given ! $user_is_remote && # user != remote (!$remote || $GET{'altlogin'})) { # user has clicked alt auth $user = $POST{'user'}; $u = LJ::load_user($user); # Verify entered password, if it is present. my $ok = LJ::auth_okay($u, $POST{password}); $flags = { 'noauth' => 1, 'u' => $u } if $ok; } elsif ($remote && LJ::check_referer()) { # assume remote if we have it $flags = { 'noauth' => 1, 'u' => $remote }; $user = $remote->{'user'}; $u = $remote; } # Check if the account they're posting to is read-only my $uj = $POST{'usejournal'} ? LJ::load_user($POST{'usejournal'}) : $u; if ($uj && $uj->readonly) { # Tell the user they can't post since read only $$body .= "$ML{'.error.update'} "; $$body .= $LJ::MSG_READONLY_USER; $$body .= " errorbar?>
"; $print_entry_form->(); return } # do a login action my $login_message; { # build a clientversion string my $clientversion = "Web/2.0.0"; $clientversion .= 's' if $did_spellcheck; # build a request object my %req = ( 'mode' => 'login', 'ver' => $LJ::PROTOCOL_VER, 'clientversion' => $clientversion, 'user' => $user, ); my %res; LJ::do_request(\%req, \%res, $flags); # error logging in ? unless ($res{'success'} eq 'OK') { $errors->{'auth'} = $ML{'.error.login'} . " " . LJ::ehtml($res{'errmsg'}); } # server login message for user? $login_message = LJ::auto_linkify(LJ::ehtml($res{'message'})) if $res{'message'}; } # any messages from the server? if ($login_message) { $$body .= "$ML{'.loggingin'} $ML{'.servermsg'} p?>
$login_message
"; } my %req = ( 'mode' => 'postevent', 'ver' => $LJ::PROTOCOL_VER, 'user' => $user, 'password' => $POST{'password'}, 'usejournal' => $POST{'usejournal'}, 'tz' => 'guess', 'xpost' => '0' ); LJ::entry_form_decode(\%req, \%POST); if ($req{'event'} eq "") { $errors->{'entry'} = $ML{'.error.noentry'}; } my %res; LJ::do_request(\%req, \%res, $flags); # check for spam domains LJ::Hooks::run_hooks('spam_check', $u, \%req, 'entry'); if (!$errors) { # examine response my $protocol_message; if ($res{'success'} eq "OK" && $res{'message'}) { $protocol_message = LJ::auto_linkify(LJ::ehtml($res{'message'})); } if ($res{'success'} ne 'OK') { # update failed? $$body .= "$ML{'.update.status.failed'} "; $$body .= "
$ML{'.error.update'} "; $$body .= LJ::ehtml($res{'errmsg'}) . " errorbar?>"; $$body .= "
p?>"; } else { # update succeeded $$body .= "$ML{'.update.status.succeeded'} "; # persist the default value of the disable auto-formatting option $u->disable_auto_formatting( $POST{event_format} ? 1 : 0 ); # Clear out a draft $remote->set_prop('entry_draft', '') if $remote; # Store what editor they last used unless (!$remote || $remote->prop('entry_editor') =~ /^always_/) { $POST{'switched_rte_on'} ? $remote->set_prop('entry_editor', 'rich') : $remote->set_prop('entry_editor', 'plain'); } $$body .= "
\n\n"; my ($ju, $itemlink); # short bail if this was posted moderated or some other special case (no itemid but a message) if (!defined $res{itemid} && $res{message}) { $$body .= "
$res{message} p?>"; } else { # update success my $updatemessage = '.update.success2'; if ($POST{'usejournal'}) { $ju = LJ::load_user($POST{'usejournal'}); # posting as community } elsif ($user) { $ju = LJ::load_user($user); # posting not as user from form } else { $ju = $remote; # posting as remote }; if ( $ju->is_community ) { # changes the update message if journal is from a community $updatemessage = '.update.success2.community'; } $$body .= BML::ml( $updatemessage, {'aopts' => "href='" . $ju->journal_base . "/'"} ); $$body .= "
$protocol_message" if $protocol_message; my $juser = $ju->{'user'}; my ($itemid, $anum) = ($res{'itemid'}, $res{'anum'}); $itemlink = LJ::item_link($ju, $itemid, $anum); my $orig_itemid = $itemid; $itemid = $itemid * 256 + $anum; my $edititemlink = "/editjournal?journal=$juser&itemid=$itemid"; # crosspost if we're posting to our own journal and have # selected crosspost. if ($ju == $remote && ($POST{prop_xpost_check} || $GET{prop_xpost_check})) { my ($xpost_successes, $xpost_errors) = LJ::Protocol::schedule_xposts($remote, $itemid, 0, sub { my $acctid = (shift)->acctid; ($POST{"prop_xpost_$acctid"} || $GET{"prop_xpost_$acctid"}, {password => $POST{"prop_xpost_password_$acctid"} || $GET{"prop_xpost_password_$acctid"}, auth_challenge => $POST{"prop_xpost_chal_$acctid"} || $GET{"prop_xpost_chal_$acctid"}, auth_response => $POST{"prop_xpost_resp_$acctid"} || $GET{"prop_xpost_resp_$acctid"}}) }); $$body .= "
    \n"; $$body .= join("\n", map { "
  • " . BML::ml('xpost.request.success2', { account => $_->displayname, sitenameshort => $LJ::SITENAMESHORT }) . "
  • " } @{$xpost_successes}); $$body .= join("\n", map { "
  • " . BML::ml('xpost.request.failed', {account => $_->displayname, editurl => $edititemlink }) . "
  • " } @{$xpost_errors}); $$body .= "
\n"; $$body .= "
"; } my @after_entry_post_extra_options = LJ::Hooks::run_hooks('after_entry_post_extra_options', user => $ju, itemlink => $itemlink); my $after_entry_post_extra_options = join('', map {$_->[0]} @after_entry_post_extra_options) || ''; my $security_ml; my $filternames = ''; my $c_or_p = $ju->is_community ? 'c' : 'p'; if ( $req{"security"} eq "private" ) { $security_ml = "post.security.private.$c_or_p"; } elsif ( $req{"security"} eq "usemask" ) { if ( $req{"allowmask"} == 0 ) { # custom security with no group -- essentially private $security_ml = "post.security.private.$c_or_p"; } elsif ( $req{"allowmask"} > 1 ) { # custom group $filternames = $ju->security_group_display( $req{"allowmask"} ); $security_ml = "post.security.custom"; } else { # access list $security_ml = "post.security.access.$c_or_p"; } } else { # public $security_ml = "post.security.public"; } $$body .= " p?> $filternames } ); my $subject = $req{subject}; if ( length $subject > 0 ) { # use the HTML cleaner on the entry subject, # then display it without escaping LJ::CleanHTML::clean_subject( \$subject ); } else { $subject = $ML{'.extradata.subject.no_subject'}; } $$body .= sprintf( " p?>"; } $$body .= "
"; $$body .= "
"; $$body .= LJ::Hooks::run_hook('after_entry_post_extra_html', user => $ju, itemlink => $itemlink, request => \%req); return; } } } $$body .= ""; $$body .= "
"; $print_entry_form->(); $$body .= ""; $$body .= "
"; return; } _code?> {'title'}; _code?> body=> {'body'}; _code?> bodyopts=>{'bodyopts'}; _code?> head<= {'head'}; LJ::need_res(qw( js/6alib/core.js js/6alib/dom.js js/6alib/httpreq.js js/livejournal.js js/entry.js js/poll.js js/browserdetect.js js/md5.js js/xpost.js )); # draft autosave and restore # The $draft variable contains the draft itself. The hash contains the various # fields of the user's draft properties (subject, tags, music, etc.) my $remote = LJ::get_remote(); my $draft = '""'; my %draft_properties; my $draft_subject_raw = ""; if ($remote) { # Here we get the value of the userprop 'draft_properties', containing # a frozen Storable string, which we then thaw into a hash by the same # name. $draft = LJ::ejs_string($remote->prop('entry_draft')); %draft_properties = $remote->prop( 'draft_properties' ) ? %{ Storable::thaw( $remote->prop( 'draft_properties' ) ) } : (); # store raw for later use; will be escaped later $draft_subject_raw = $draft_properties{subject}; %draft_properties = map { $_ => LJ::ejs_string( $draft_properties{$_} ) } qw( subject userpic taglist moodid mood location1 music adultreason commentset commentscr adultcnt ); } my $eMLautosave = LJ::ejs(BML::ml('.draft.autosave', { 'time' => '[[time]]' })); my $eMLrestored = LJ::ejs($ML{'.draft.restored'}); # not enough to just escape the draft_subject, we want to escape the entire thing, just in case the translation text # for.draft.confirm2 contains JS-breaking characters such as apostrophes my $eMLconfirm = LJ::ejs_string( BML::ml( '.draft.confirm2', { subjectline => "\"$draft_subject_raw\"" } ) ); # Setup draft saving and try to restore from a draft # unless we did a post action my $initDraft = ''; if ( $remote && LJ::is_enabled('update_draft') ) { # While transforms aren't considered posts, we don't want to # prompt the user to restore from a draft on a transform if (!LJ::did_post()) { $initDraft = 'initDraft(true);'; } else { $initDraft = 'initDraft(false);'; } } my $pageload = $LJ::SPELLER && $POST{'action:spellcheck'} ? "pageload(0);" : "pageload(1);"; # JS vars for the RTE $ret .= LJ::rte_js_vars($remote); # Turning off BML parsing for the rest of this code block # The draft might contain BML like syntax and cause problems BML::noparse(); $ret .= qq^ ^; my $chalresp_js = qq{ }; $ret .= (! $LJ::REQ_HEAD_HAS{'chalresp_js'}++) ? $chalresp_js : ""; return $ret; } _code?> <=head page?>