Committer: ailyin
LJSUP-6137 (FaceBook authorization. Server side): merge the branch to trunk, yayU trunk/bin/maint/clean_caches.pl U trunk/cgi-bin/LJ/Entry.pm U trunk/cgi-bin/LJ/Event/Befriended.pm U trunk/cgi-bin/LJ/HTML/Template.pm A trunk/cgi-bin/LJ/Identity/ D trunk/cgi-bin/LJ/Identity/Jabber.pm A trunk/cgi-bin/LJ/Identity/Jabber.pm D trunk/cgi-bin/LJ/Identity/OpenID.pm A trunk/cgi-bin/LJ/Identity/OpenID.pm U trunk/cgi-bin/LJ/Identity.pm U trunk/cgi-bin/LJ/OpenID.pm U trunk/cgi-bin/LJ/Setting.pm A trunk/cgi-bin/LJ/Talk/ D trunk/cgi-bin/LJ/Talk/Author/ A trunk/cgi-bin/LJ/Talk/Author/ D trunk/cgi-bin/LJ/Talk/Author/Anonymous.pm A trunk/cgi-bin/LJ/Talk/Author/Anonymous.pm D trunk/cgi-bin/LJ/Talk/Author/OpenID.pm A trunk/cgi-bin/LJ/Talk/Author/OpenID.pm D trunk/cgi-bin/LJ/Talk/Author/User.pm A trunk/cgi-bin/LJ/Talk/Author/User.pm D trunk/cgi-bin/LJ/Talk/Author.pm A trunk/cgi-bin/LJ/Talk/Author.pm D trunk/cgi-bin/LJ/Talk/Post.pm A trunk/cgi-bin/LJ/Talk/Post.pm A trunk/cgi-bin/LJ/Talk.pm U trunk/cgi-bin/LJ/Text.pm U trunk/cgi-bin/LJ/User.pm U trunk/cgi-bin/LJ/Widget/CreateAccount.pm U trunk/cgi-bin/LJ/Widget/EntryForm.pm U trunk/cgi-bin/bml/scheme/lynx.look U trunk/cgi-bin/ljdefaults.pl U trunk/cgi-bin/talklib.pl U trunk/cgi-bin/weblib.pl A trunk/htdocs/identity/ D trunk/htdocs/identity/callback-openid.bml A trunk/htdocs/identity/callback-openid.bml D trunk/htdocs/identity/login.bml A trunk/htdocs/identity/login.bml U trunk/htdocs/login.bml U trunk/htdocs/manage/profile/index.bml U trunk/htdocs/manage/settings/index.bml U trunk/htdocs/openid/index.bml U trunk/htdocs/openid/login.bml U trunk/htdocs/talkpost_do.bml U trunk/htdocs/userinfo.bml U trunk/htdocs/userinfo.bml.text A trunk/templates/CommentForm/ D trunk/templates/CommentForm/Author-Anonymous.tmpl A trunk/templates/CommentForm/Author-Anonymous.tmpl D trunk/templates/CommentForm/Author-OpenID.tmpl A trunk/templates/CommentForm/Author-OpenID.tmpl D trunk/templates/CommentForm/Author-User.tmpl A trunk/templates/CommentForm/Author-User.tmpl D trunk/templates/CommentForm/Form.tmpl A trunk/templates/CommentForm/Form.tmpl A trunk/templates/Identity/ D trunk/templates/Identity/Login-openid.tmpl A trunk/templates/Identity/Login-openid.tmpl D trunk/templates/Identity/Login.tmpl A trunk/templates/Identity/Login.tmpl
Modified: trunk/bin/maint/clean_caches.pl =================================================================== --- trunk/bin/maint/clean_caches.pl 2010-08-09 03:27:54 UTC (rev 17094) +++ trunk/bin/maint/clean_caches.pl 2010-08-09 04:04:46 UTC (rev 17095) @@ -164,6 +164,7 @@ print " rows remaining: " . ($xfp_count - $row_ct) . "\n"; } + LJ::run_hooks('extra_cache_clean'); }; 1; Modified: trunk/cgi-bin/LJ/Entry.pm =================================================================== --- trunk/cgi-bin/LJ/Entry.pm 2010-08-09 03:27:54 UTC (rev 17094) +++ trunk/cgi-bin/LJ/Entry.pm 2010-08-09 04:04:46 UTC (rev 17095) @@ -301,6 +301,12 @@ return $self->{security}; } +sub is_public { + my ($self) = @_; + + return $self->security eq 'public'; +} + sub allowmask { my $self = shift; __PACKAGE__->preload_rows([ $self ]) unless $self->{_loaded_row}; @@ -1300,6 +1306,33 @@ return 1; } +sub everyone_can_comment { + my ($self) = @_; + + return 0 unless $self->posting_comments_allowed; + return 0 unless $self->journal->{'opt_whocanreply'} eq 'all'; + + return 1; +} + +sub registered_can_comment { + my ($self) = @_; + + return 1 if $self->everyone_can_comment; + return 1 if $self->journal->{'opt_whocanreply'} eq 'reg'; + + return 0; +} + +sub friends_can_comment { + my ($self) = @_; + + return 1 if $self->registered_can_comment; + return 1 if $self->journal->{'opt_whocanreply'} eq 'friends'; + + return 0; +} + package LJ; use Class::Autouse qw ( Modified: trunk/cgi-bin/LJ/Event/Befriended.pm =================================================================== --- trunk/cgi-bin/LJ/Event/Befriended.pm 2010-08-09 03:27:54 UTC (rev 17094) +++ trunk/cgi-bin/LJ/Event/Befriended.pm 2010-08-09 04:04:46 UTC (rev 17095) @@ -55,7 +55,7 @@ LJ::Lang::get_text_multi($lang, undef, \@_ml_strings_en); my $entries = LJ::is_friend($u, $self->friend) ? "" : " " . LJ::Lang::get_text($lang, 'esn.public', undef); - my $is_open_identity = $self->friend->openid_identity; + my $is_open_identity = $self->friend->is_identity; my $vars = { who => $self->friend->display_username, @@ -67,7 +67,7 @@ }; my $email_body_key = 'esn.befriended.' . - ($u->openid_identity ? 'openid_' : '' ) . 'email_text'; + ($u->is_identity ? 'openid_' : '' ) . 'email_text'; return LJ::Lang::get_text($lang, $email_body_key, undef, $vars) . $self->format_options($is_html, $lang, $vars, Modified: trunk/cgi-bin/LJ/HTML/Template.pm =================================================================== --- trunk/cgi-bin/LJ/HTML/Template.pm 2010-08-09 03:27:54 UTC (rev 17094) +++ trunk/cgi-bin/LJ/HTML/Template.pm 2010-08-09 04:04:46 UTC (rev 17095) @@ -13,6 +13,7 @@ 'lj_imgprefix' => $LJ::IMGPREFIX, 'lj_sitename' => $LJ::SITENAMESHORT, 'lj_sslroot' => $LJ::SSLROOT, + 'lj_jsprefix' => $LJ::JSPREFIX, ); if ($opts->{'use_expr'}) { Deleted: trunk/cgi-bin/LJ/Identity/Jabber.pm =================================================================== --- branches/facebook-integration2/cgi-bin/LJ/Identity/Jabber.pm 2010-08-09 03:27:54 UTC (rev 17094) +++ trunk/cgi-bin/LJ/Identity/Jabber.pm 2010-08-09 04:04:46 UTC (rev 17095) @@ -1,33 +0,0 @@ -package LJ::Identity::Jabber; -use strict; - -sub typeid { 'J' } -sub pretty_type { 'Jabber' } -sub short_code { 'jabber' } -sub url { $LJ::SITEROOT } - -sub initialize_user { - # there's no initialization we need to do -} - -sub display_name { - my ($self, $u) = @_; - return $u->username; -} - -sub ljuser_display_params { - my ($self, $u, $opts) = @_; - - return { - 'journal_url' => $opts->{'journal_url'} || $self->url, - 'journal_name' => $u->display_name, - 'userhead' => 'userinfo.gif', - 'userhead_w' => 17, - }; -} - -sub profile_window_title { - return LJ::Lang::ml('/userinfo.bml.title.jabberprofile'); -} - -1; Copied: trunk/cgi-bin/LJ/Identity/Jabber.pm (from rev 17094, branches/facebook-integration2/cgi-bin/LJ/Identity/Jabber.pm) =================================================================== --- trunk/cgi-bin/LJ/Identity/Jabber.pm (rev 0) +++ trunk/cgi-bin/LJ/Identity/Jabber.pm 2010-08-09 04:04:46 UTC (rev 17095) @@ -0,0 +1,33 @@ +package LJ::Identity::Jabber; +use strict; + +sub typeid { 'J' } +sub pretty_type { 'Jabber' } +sub short_code { 'jabber' } +sub url { $LJ::SITEROOT } + +sub initialize_user { + # there's no initialization we need to do +} + +sub display_name { + my ($self, $u) = @_; + return $u->username; +} + +sub ljuser_display_params { + my ($self, $u, $opts) = @_; + + return { + 'journal_url' => $opts->{'journal_url'} || $self->url, + 'journal_name' => $u->display_name, + 'userhead' => 'userinfo.gif', + 'userhead_w' => 17, + }; +} + +sub profile_window_title { + return LJ::Lang::ml('/userinfo.bml.title.jabberprofile'); +} + +1; Deleted: trunk/cgi-bin/LJ/Identity/OpenID.pm =================================================================== --- branches/facebook-integration2/cgi-bin/LJ/Identity/OpenID.pm 2010-08-09 03:27:54 UTC (rev 17094) +++ trunk/cgi-bin/LJ/Identity/OpenID.pm 2010-08-09 04:04:46 UTC (rev 17095) @@ -1,230 +0,0 @@ -package LJ::Identity::OpenID; -use strict; - -use base qw(LJ::Identity); - -use LJ::OpenID; - -sub typeid { 'O' } -sub pretty_type { 'OpenID' } -sub short_code { 'openid' } - -sub url { - my ($self) = @_; - return $self->value; -} - -# Returns a Consumer object -# When planning to verify identity, needs GET -# arguments passed in -sub consumer { - my ($class, $get_args) = @_; - $get_args ||= {}; - - my $ua; - unless ($LJ::IS_DEV_SERVER) { - $ua = LWPx::ParanoidAgent->new( - timeout => 10, - max_size => 1024*300, - ); - } - - my $cache = undef; - if (! $LJ::OPENID_STATELESS && scalar(@LJ::MEMCACHE_SERVERS)) { - $cache = 'LJ::Identity::OpenID::Cache'; - } - - my $csr = Net::OpenID::Consumer->new( - ua => $ua, - args => $get_args, - cache => $cache, - consumer_secret => sub { - my ($time) = @_; - return LJ::OpenID::server_secret($time - $time % 3600); - }, - debug => $LJ::IS_DEV_SERVER || 0, - required_root => $LJ::SITEROOT, - ); - - return $csr; -} - -# Returns 1 if destination identity server -# is blocked -sub blocked_hosts { - my ($class, $csr) = @_; - - return do { my $dummy = 0; \$dummy; } if $LJ::IS_DEV_SERVER; - - my $tried_local_id = 0; - $csr->ua->blocked_hosts( sub { - my $dest = shift; - - if ($dest =~ /(^|\.)\Q$LJ::DOMAIN\E$/i) { - $tried_local_id = 1; - return 1; - } - return 0; - } ); - return \$tried_local_id; -} - -sub attempt_login { - my ($class, $errs, %opts) = @_; - - $errs ||= []; - my $returl = $opts{'returl'} || $LJ::SITEROOT; - my $returl_fail = $opts{'returl_fail'} || $returl || $LJ::SITEROOT; - - my $csr = $class->consumer; - my $url = LJ::Request->post_param('openid:url'); - - if ($url =~ /[\<\>\s]/) { - push @$errs, "Invalid characters in identity URL."; - return; - } - - my $tried_local_ref = $class->blocked_hosts($csr); - if ($$tried_local_ref) { - push @$errs, "You can't use a LiveJournal OpenID account on LiveJournal — ". - "just <a href='/login.bml'>go login</a> with your actual LiveJournal account."; - return; - } - - my $claimed_id = eval { $csr->claimed_identity($url) }; - if ($@) { - push @$errs, $@; - return; - } - - unless ($claimed_id) { - push @$errs, $csr->err; - return; - } - - my $check_url = $claimed_id->check_url( - return_to => "$LJ::SITEROOT/identity/callback-openid.bml?" . - 'ret=' . LJ::Text->eurl($returl) . '&' . - 'ret_fail=' . LJ::Text->eurl($returl_fail), - trust_root => "$LJ::SITEROOT/", - delayed_return => 1, - ); - - return LJ::Request->redirect($check_url); -} - -sub initialize_user { - my ($self, $u, $extra) = @_; - - $extra ||= {}; - my $vident = $extra->{'vident'}; - - return unless $vident; - - if (ref $vident and $vident->can("display")) { - LJ::update_user($u, { 'name' => $vident->display }); - } elsif (not ref $vident){ - LJ::update_user($u, { 'name' => $vident }); - } -} - -sub display_name { - my ($self, $u) = @_; - - # if name does not have [] .com .ru or https it should be displayed as - # "name [domain.com]"; otherwise - old code - unless ($u->name_orig =~ m!(\w+\.\w{2,4})|(https?://)!){ - my $uri = URI->new( $self->value ); - my $domain = $self->value; - ($domain) = $uri->host =~ /(\w+\.\w{2,4})$/ - if $uri->can('host'); - return $u->name_orig ." [$domain]"; - } - - # - my ($url, $name); - $url = $self->value; - $name = Net::OpenID::VerifiedIdentity::DisplayOfURL($url, - $LJ::IS_DEV_SERVER); - - $name = LJ::run_hook("identity_display_name", $name) || $name; - - ## Decode URL's like below to human-readable names - ## http://blog.k.python.ru/accounts/5/%D0%94%D0%BC%D0%B8 - $name =~ s/%([\dA-Fa-f]{2})/chr(hex($1))/ge; - - return $name; -} - -sub ljuser_display_params { - my ($self, $u, $opts) = @_; - - my $ret = { - 'journal_url' => $opts->{'journal_url'} || $self->url, - 'journal_name' => $u->display_name, - }; - - if (my $head_size = $opts->{'head_size'}) { - $ret->{'userhead'} = "openid_${head_size}.gif"; - $ret->{'userhead_w'} = $head_size; - } elsif ($self->value =~ m/\.fanat\.ru(\/|$)/) { - # Fanat.ru users have a distinct pic - # TODO: move to a hook? - $ret->{'userhead'} = 'openid_fanat-profile.gif'; - $ret->{'userhead_w'} = 16; - } else { - $ret->{'userhead'} = 'openid-profile.gif'; - $ret->{'userhead_w'} = 16; - } - - return $ret; -} - -sub profile_window_title { - return LJ::Lang::ml('/userinfo.bml.title.openidprofile'); -} - -package LJ::Identity::OpenID::Cache; - -my $important = qr/^(?:hassoc|shandle):/; - -sub get { - my ($class, $key) = @_; - - # try memcached first. - my $val = LJ::MemCache::get($key); - return $val if $val; - - # important keys, on miss, try the database. - if ($key =~ /$important/) { - my $dbh = LJ::get_db_writer(); - $val = $dbh->selectrow_array(qq{ - SELECT value FROM blobcache WHERE bckey=? - }, undef, $key); - - return unless $val; - - # put it back in memcache. - LJ::MemCache::set($key, $val); - return $val; - } - - return; -} - -sub set { - my ($class, $key, $val) = @_; - - # important keys go to the database - if ($key =~ /$important/) { - my $dbh = LJ::get_db_writer(); - $dbh->do(qq{ - REPLACE INTO blobcache SET bckey=?, dateupdate=NOW(), value=? - }, undef, $key, $val); - } - - # everything goes in memcache. - LJ::MemCache::set($key, $val); -} - -1; Copied: trunk/cgi-bin/LJ/Identity/OpenID.pm (from rev 17094, branches/facebook-integration2/cgi-bin/LJ/Identity/OpenID.pm) =================================================================== --- trunk/cgi-bin/LJ/Identity/OpenID.pm (rev 0) +++ trunk/cgi-bin/LJ/Identity/OpenID.pm 2010-08-09 04:04:46 UTC (rev 17095) @@ -0,0 +1,230 @@ +package LJ::Identity::OpenID; +use strict; + +use base qw(LJ::Identity); + +use LJ::OpenID; + +sub typeid { 'O' } +sub pretty_type { 'OpenID' } +sub short_code { 'openid' } + +sub url { + my ($self) = @_; + return $self->value; +} + +# Returns a Consumer object +# When planning to verify identity, needs GET +# arguments passed in +sub consumer { + my ($class, $get_args) = @_; + $get_args ||= {}; + + my $ua; + unless ($LJ::IS_DEV_SERVER) { + $ua = LWPx::ParanoidAgent->new( + timeout => 10, + max_size => 1024*300, + ); + } + + my $cache = undef; + if (! $LJ::OPENID_STATELESS && scalar(@LJ::MEMCACHE_SERVERS)) { + $cache = 'LJ::Identity::OpenID::Cache'; + } + + my $csr = Net::OpenID::Consumer->new( + ua => $ua, + args => $get_args, + cache => $cache, + consumer_secret => sub { + my ($time) = @_; + return LJ::OpenID::server_secret($time - $time % 3600); + }, + debug => $LJ::IS_DEV_SERVER || 0, + required_root => $LJ::SITEROOT, + ); + + return $csr; +} + +# Returns 1 if destination identity server +# is blocked +sub blocked_hosts { + my ($class, $csr) = @_; + + return do { my $dummy = 0; \$dummy; } if $LJ::IS_DEV_SERVER; + + my $tried_local_id = 0; + $csr->ua->blocked_hosts( sub { + my $dest = shift; + + if ($dest =~ /(^|\.)\Q$LJ::DOMAIN\E$/i) { + $tried_local_id = 1; + return 1; + } + return 0; + } ); + return \$tried_local_id; +} + +sub attempt_login { + my ($class, $errs, %opts) = @_; + + $errs ||= []; + my $returl = $opts{'returl'} || $LJ::SITEROOT; + my $returl_fail = $opts{'returl_fail'} || $returl || $LJ::SITEROOT; + + my $csr = $class->consumer; + my $url = LJ::Request->post_param('openid:url'); + + if ($url =~ /[\<\>\s]/) { + push @$errs, "Invalid characters in identity URL."; + return; + } + + my $tried_local_ref = $class->blocked_hosts($csr); + if ($$tried_local_ref) { + push @$errs, "You can't use a LiveJournal OpenID account on LiveJournal — ". + "just <a href='/login.bml'>go login</a> with your actual LiveJournal account."; + return; + } + + my $claimed_id = eval { $csr->claimed_identity($url) }; + if ($@) { + push @$errs, $@; + return; + } + + unless ($claimed_id) { + push @$errs, $csr->err; + return; + } + + my $check_url = $claimed_id->check_url( + return_to => "$LJ::SITEROOT/identity/callback-openid.bml?" . + 'ret=' . LJ::Text->eurl($returl) . '&' . + 'ret_fail=' . LJ::Text->eurl($returl_fail), + trust_root => "$LJ::SITEROOT/", + delayed_return => 1, + ); + + return LJ::Request->redirect($check_url); +} + +sub initialize_user { + my ($self, $u, $extra) = @_; + + $extra ||= {}; + my $vident = $extra->{'vident'}; + + return unless $vident; + + if (ref $vident and $vident->can("display")) { + LJ::update_user($u, { 'name' => $vident->display }); + } elsif (not ref $vident){ + LJ::update_user($u, { 'name' => $vident }); + } +} + +sub display_name { + my ($self, $u) = @_; + + # if name does not have [] .com .ru or https it should be displayed as + # "name [domain.com]"; otherwise - old code + unless ($u->name_orig =~ m!(\w+\.\w{2,4})|(https?://)!){ + my $uri = URI->new( $self->value ); + my $domain = $self->value; + ($domain) = $uri->host =~ /(\w+\.\w{2,4})$/ + if $uri->can('host'); + return $u->name_orig ." [$domain]"; + } + + # + my ($url, $name); + $url = $self->value; + $name = Net::OpenID::VerifiedIdentity::DisplayOfURL($url, + $LJ::IS_DEV_SERVER); + + $name = LJ::run_hook("identity_display_name", $name) || $name; + + ## Decode URL's like below to human-readable names + ## http://blog.k.python.ru/accounts/5/%D0%94%D0%BC%D0%B8 + $name =~ s/%([\dA-Fa-f]{2})/chr(hex($1))/ge; + + return $name; +} + +sub ljuser_display_params { + my ($self, $u, $opts) = @_; + + my $ret = { + 'journal_url' => $opts->{'journal_url'} || $self->url, + 'journal_name' => $u->display_name, + }; + + if (my $head_size = $opts->{'head_size'}) { + $ret->{'userhead'} = "openid_${head_size}.gif"; + $ret->{'userhead_w'} = $head_size; + } elsif ($self->value =~ m/\.fanat\.ru(\/|$)/) { + # Fanat.ru users have a distinct pic + # TODO: move to a hook? + $ret->{'userhead'} = 'openid_fanat-profile.gif'; + $ret->{'userhead_w'} = 16; + } else { + $ret->{'userhead'} = 'openid-profile.gif'; + $ret->{'userhead_w'} = 16; + } + + return $ret; +} + +sub profile_window_title { + return LJ::Lang::ml('/userinfo.bml.title.openidprofile'); +} + +package LJ::Identity::OpenID::Cache; + +my $important = qr/^(?:hassoc|shandle):/; + +sub get { + my ($class, $key) = @_; + + # try memcached first. + my $val = LJ::MemCache::get($key); + return $val if $val; + + # important keys, on miss, try the database. + if ($key =~ /$important/) { + my $dbh = LJ::get_db_writer(); + $val = $dbh->selectrow_array(qq{ + SELECT value FROM blobcache WHERE bckey=? + }, undef, $key); + + return unless $val; + + # put it back in memcache. + LJ::MemCache::set($key, $val); + return $val; + } + + return; +} + +sub set { + my ($class, $key, $val) = @_; + + # important keys go to the database + if ($key =~ /$important/) { + my $dbh = LJ::get_db_writer(); + $dbh->do(qq{ + REPLACE INTO blobcache SET bckey=?, dateupdate=NOW(), value=? + }, undef, $key, $val); + } + + # everything goes in memcache. + LJ::MemCache::set($key, $val); +} + +1; Modified: trunk/cgi-bin/LJ/Identity.pm =================================================================== --- trunk/cgi-bin/LJ/Identity.pm 2010-08-09 03:27:54 UTC (rev 17094) +++ trunk/cgi-bin/LJ/Identity.pm 2010-08-09 04:04:46 UTC (rev 17095) @@ -1,40 +1,189 @@ -package LJ::Identity; +=head1 NAME -use strict; +LJ::Identity - a module for handling external identities (like OpenID) +in LiveJournal -use fields ( - 'typeid', # Id number of identity type - 'value', # Identity string - ); +=head1 SYNOPSIS -sub new { - my LJ::Identity $self = shift; - $self = fields::new( $self ) unless ref $self; - my %opts = @_; + # load or create an identity account + my $u = LJ::User::load_identity_user( + 'O', # OpenID + $openid_url, + { 'vident' => $vident }, # OpenID-specific "verified identity" data + ); + warn $u; # 'LJ::User=HASH(0xDEADBEEF)' + + # manipulate the account in an identity-specific way + my $id = $u->identity; + warn $id->pretty_type; # 'OpenID' + + # redirect the remote user to a third-party site for verification, + # requesting that once they log in, they return to the specified site + # page; note that the identity may wish to see some specific form + # submission with the data to process + LJ::Identity::OpenID->attempt_login( + \@errors, # caller-allocated list for storing error messages for the + # user. if undefined, the errors are silently discarded - $self->{typeid} = $opts{'typeid'}; - $self->{value} = $opts{'value'}; + # return to this page on success: + 'returl' => $LJ::SITEROOT, - return $self; + # and to this page in case of a failure: + 'returl_fail' => $LJ::SITEROOT, + ); + +=cut + +package LJ::Identity; +use strict; + +use Carp qw(); + +# initialization code. do not touch this. +my @CLASSES = LJ::ModuleLoader->module_subclasses('LJ::Identity'); +foreach my $class (@CLASSES) { + eval "use $class"; + Carp::confess "Error loading event module '$class': $@" if $@; } -sub pretty_type { - my LJ::Identity $self = shift; - return 'OpenID' if $self->{typeid} == 0; - return 'Invalid identity type'; +my %TYPEMAP = map { $_->typeid => $_ } @CLASSES; +my %TYPEMAP_SHORT_CODES = map { $_->short_code => $_ } @CLASSES; + +# initialization code ends + +=head1 DEFINED METHODS + +=head2 Parent class functions; final + +=over 2 + +=item * + +find_class: find a class with the specified short code; see also the +short_code function. + + warn LJ::Identity->find_class('openid'); # 'LJ::Identity::OpenID' + +=item * + +new: a constructor, constructing an identity object with the proper +class matching the passed 'typeid' and 'value' params. + + warn LJ::Identity->new('typeid' => 'O', 'value' => $url); + # 'LJ::Identity::OpenID=HASH(0xDEADBEEF)' + +You probably should use $u->identity instead, which calls this function. + +=back + +=cut + +sub find_class { + my ($class, $short_code) = @_; + return $TYPEMAP_SHORT_CODES{$short_code}; } -sub typeid { - my LJ::Identity $self = shift; - die("Cannot set new typeid value") if @_; +sub new { + my ($class, %opts) = @_; - return $self->{typeid}; + return bless { + 'value' => $opts{'value'}, + }, $TYPEMAP{$opts{'typeid'}}; } +=head2 Getter(s) + +=over 2 + +=item * + +value: returns the identity-specific identifier for the user, such as +a URL used for OpenID identification. + +=back + +=cut + sub value { - my LJ::Identity $self = shift; - die("Cannot set new identity value") if @_; + my ($self) = @_; + return $self->{'value'}; +} - return $self->{value}; -} +=head2 (Purely) virtual functions, thousands of them + +=over 2 + +=item * + +pretty_type: return a "fancy" identity type description that can be +displayed to a user. Used by ljprotocol.pl in the 'list_friends' method. + + warn $u->identity->pretty_type; # 'OpenID' + +=item * + +typeid: a one character long string containing a code that represents +this identity type in the database. Used by the constructor indirectly. + + warn $u->identity->short_code; # 'O' + +=item * + +short_code: a string containing a "readable" code specific for the +identity type. There are two intended uses: elsewhere in the code +it is more readable to check C<$id->short_code eq 'openid'> than to check +C<$id->typeid eq 'O'>; also, it should be used as a value to a form field +specifying the identity type, so that the form handler can call find_class +to find the identity class. + +=item * + +url: return an identity-specific URL to be used for the "website" field +in the user's profile. Used by sub LJ::User::url. + +=item * + +attempt_login: verify the remote user's identity, redirecting to a +specified page afterwards. See the example in the SYNOPSIS part. +Used by htdocs/identity/login.bml. + +=item * + +initialize_user: initialize the user's profile by the data provided +by the identity provider. Used by sub LJ::User::load_identity_user the +first time the user with a particular identity logs in to the site. + +=item * + +display_name: return a publicly-displayed name of the user. Used by +sub LJ::User::display_name. + +=item * + +ljuser_display_params: return a hashref containing some params +for the E<lt>lj user="username"E<gt> tag display; the params interpreted +are 'profile_url', 'journal_url, 'journal_name', 'userhead','userhead_w', +and 'userhead_h'. Used by sub LJ::ljuser in cgi-bin/LJ/User.pm. Please +refer to the source code of this function for details. + +=item * + +profile_window_title: return a string to be used as a window title +for the profile page of this user. Used in htdocs/userinfo.bml. It is +suggested that implementations use LJ::Lang::ml for i18n. + +=back + +=cut + +sub pretty_type { Carp::confess 'Invalid identity type' } +sub typeid { Carp::confess 'Invalid identity type' } +sub short_code { Carp::confess 'Invalid identity type' } +sub url { Carp::confess 'Invalid identity type' } +sub attempt_login { Carp::confess 'Invalid identity type' } +sub initialize_user { Carp::confess 'Invalid identity type' } +sub display_name { Carp::confess 'Invalid identity type' } +sub ljuser_display_params { Carp::confess 'Invalid identity type' } +sub profile_window_title { Carp::confess 'Invalid identity type' } + 1; Modified: trunk/cgi-bin/LJ/OpenID.pm =================================================================== --- trunk/cgi-bin/LJ/OpenID.pm 2010-08-09 03:27:54 UTC (rev 17094) +++ trunk/cgi-bin/LJ/OpenID.pm 2010-08-09 04:04:46 UTC (rev 17095) @@ -3,7 +3,6 @@ use strict; use Digest::SHA1 qw(sha1 sha1_hex); use LWPx::ParanoidAgent; -use LJ::OpenID::Cache; BEGIN { $LJ::OPTMOD_OPENID_CONSUMER = $LJ::OPENID_CONSUMER ? eval "use Net::OpenID::Consumer; 1;" : 0; @@ -50,38 +49,9 @@ # When planning to verify identity, needs GET # arguments passed in sub consumer { - my $get_args = shift || {}; - - my $ua; - unless ($LJ::IS_DEV_SERVER) { - $ua = LWPx::ParanoidAgent->new( - timeout => 10, - max_size => 1024*300, - ); - } - - my $cache = undef; - if (! $LJ::OPENID_STATELESS && scalar(@LJ::MEMCACHE_SERVERS)) { - $cache = LJ::OpenID::Cache->new; - } - - my $csr = Net::OpenID::Consumer->new( - ua => $ua, - args => $get_args, - cache => $cache, - consumer_secret => \&LJ::OpenID::consumer_secret, - debug => $LJ::IS_DEV_SERVER || 0, - required_root => $LJ::SITEROOT, - ); - - return $csr; + return LJ::Identity::OpenID->consumer(@_); } -sub consumer_secret { - my $time = shift; - return server_secret($time - $time % 3600); -} - sub server_secret { my $time = shift; my ($t2, $secret) = LJ::get_secret($time); @@ -160,43 +130,10 @@ return $rv; } -# From Digest::HMAC -sub hmac_sha1_hex { - unpack("H*", &hmac_sha1); -} -sub hmac_sha1 { - hmac($_[0], $_[1], \&sha1, 64); -} -sub hmac { - my($data, $key, $hash_func, $block_size) = @_; - $block_size ||= 64; - $key = &$hash_func($key) if length($key) > $block_size; - - my $k_ipad = $key ^ (chr(0x36) x $block_size); - my $k_opad = $key ^ (chr(0x5c) x $block_size); - - &$hash_func($k_opad, &$hash_func($k_ipad, $data)); -} - # Returns 1 if destination identity server # is blocked sub blocked_hosts { - my $csr = shift; - - return do { my $dummy = 0; \$dummy; } if $LJ::IS_DEV_SERVER; - - my $tried_local_id = 0; - $csr->ua->blocked_hosts( - sub { - my $dest = shift; - - if ($dest =~ /(^|\.)\Q$LJ::DOMAIN\E$/i) { - $tried_local_id = 1; - return 1; - } - return 0; - }); - return \$tried_local_id; + return LJ::Identity::OpenID->blocked_hosts(@_); } 1; Modified: trunk/cgi-bin/LJ/Setting.pm =================================================================== --- trunk/cgi-bin/LJ/Setting.pm 2010-08-09 03:27:54 UTC (rev 17094) +++ trunk/cgi-bin/LJ/Setting.pm 2010-08-09 04:04:46 UTC (rev 17095) @@ -148,7 +148,8 @@ # LJ__Setting__Example_field (for LJ::Setting::Example) # LJ__Setting__Example__Example2_field (for LJ::Setting::Example::Example2) next unless $k =~ /^LJ__Setting__([a-zA-Z0-9]+)(__[a-zA-Z0-9]+)?_(\w+)$/; - my $class = "LJ::Setting::$1$2"; + my $class = "LJ::Setting::$1"; + $class .= $2 if defined $2; my $key = $3; $class =~ s/__/::/g; $posted{$class}{$key} = $v; @@ -163,6 +164,7 @@ $class->save($u, $post_args); }; if (my $err = $@) { + warn $err; $save_errors = $err->field('map') if ref $err; } } Deleted: trunk/cgi-bin/LJ/Talk/Author/Anonymous.pm =================================================================== --- branches/facebook-integration2/cgi-bin/LJ/Talk/Author/Anonymous.pm 2010-08-09 03:27:54 UTC (rev 17094) +++ trunk/cgi-bin/LJ/Talk/Author/Anonymous.pm 2010-08-09 04:04:46 UTC (rev 17095) @@ -1,33 +0,0 @@ -package LJ::Talk::Author::Anonymous; -use strict; - -use base qw(LJ::Talk::Author); - -sub display_params { - my ($class, $opts) = @_; - - my $remote = LJ::get_remote(); - my $form = $opts->{'form'}; - - my $whocheck; - $whocheck = 1 if $form->{'usertype'} eq 'anonymous'; - $whocheck = 1 if ( !$form->{'usertype'} && !$remote ); - - return { - 'whocheck_anonymous' => $whocheck, - }; -} - -sub want_user_input { - my ($class, $usertype) = @_; - return $usertype eq 'anonymous'; -} - -sub handle_user_input { - # we don't care; the poster is anonymous, which means "undef" as - # the user posting - - return; -} - -1; Copied: trunk/cgi-bin/LJ/Talk/Author/Anonymous.pm (from rev 17094, branches/facebook-integration2/cgi-bin/LJ/Talk/Author/Anonymous.pm) =================================================================== --- trunk/cgi-bin/LJ/Talk/Author/Anonymous.pm (rev 0) +++ trunk/cgi-bin/LJ/Talk/Author/Anonymous.pm 2010-08-09 04:04:46 UTC (rev 17095) @@ -0,0 +1,33 @@ +package LJ::Talk::Author::Anonymous; +use strict; + +use base qw(LJ::Talk::Author); + +sub display_params { + my ($class, $opts) = @_; + + my $remote = LJ::get_remote(); + my $form = $opts->{'form'}; + + my $whocheck; + $whocheck = 1 if $form->{'usertype'} eq 'anonymous'; + $whocheck = 1 if ( !$form->{'usertype'} && !$remote ); + + return { + 'whocheck_anonymous' => $whocheck, + }; +} + +sub want_user_input { + my ($class, $usertype) = @_; + return $usertype eq 'anonymous'; +} + +sub handle_user_input { + # we don't care; the poster is anonymous, which means "undef" as + # the user posting + + return; +} + +1; Deleted: trunk/cgi-bin/LJ/Talk/Author/OpenID.pm =================================================================== --- branches/facebook-integration2/cgi-bin/LJ/Talk/Author/OpenID.pm 2010-08-09 03:27:54 UTC (rev 17094) +++ trunk/cgi-bin/LJ/Talk/Author/OpenID.pm 2010-08-09 04:04:46 UTC (rev 17095) @@ -1,120 +0,0 @@ -package LJ::Talk::Author::OpenID; -use strict; - -use base qw(LJ::Talk::Author); - -sub display_params { - my ($class, $opts) = @_; - - my $remote = LJ::get_remote(); - my $form = $opts->{'form'}; - my $is_identity = $remote - && $remote->is_identity - && $remote->identity->short_code eq 'openid'; - - my $is_trusted_identity = $is_identity && $remote->is_trusted_identity; - - my %whocheck = ( - 'openid' => $form->{'usertype'} eq 'openid', - 'openid_cookie' => $form->{'usertype'} eq 'openid_cookie' - || $is_identity, - ); - - return { - 'openid_enabled' => LJ::OpenID->consumer_enabled, - 'is_identity' => $is_identity, - 'is_trusted_identity' => $is_trusted_identity, - 'openid_url_default' => $is_identity - ? $remote->identity->url - : $form->{'openid:url'}, - 'oiddo_login_checked' => $form->{'oiddo_login'} - ? "checked='checked' " - : '', - - 'whocheck_openid' => $whocheck{'openid'}, - 'whocheck_openid_cookie' => $whocheck{'openid_cookie'}, - - 'helpicon_openid' => LJ::help_icon_html( "openid", " " ), - }; -} - -sub want_user_input { - my ($class, $usertype) = @_; - return $usertype =~ /^(?:openid|openid_cookie)$/; -} - -sub handle_user_input { - my ($class, $form, $remote, $need_captcha, $errret, $init) = @_; - - return if @$errret; - - my $journalu = $init->{'journalu'}; - my $up; # user posting - - unless (LJ::OpenID->consumer_enabled) { - push @$errret, "OpenID consumer support is disabled"; - return; - } - - my $remote_is_openid = $remote && - $remote->is_identity && - $remote->identity->short_code eq 'openid'; - - if ($remote_is_openid) { - return LJ::get_remote(); - } - - # First time through - my $csr = LJ::OpenID::consumer(); - my $exptype = 'short'; - my $ipfixed = 0; - my $etime = 0; - - # parse inline login opts - unless ($form->{'openid:url'}) { - push @$errret, "No OpenID identity URL entered"; - return; - } - - # Store the entry - my $pendcid = LJ::alloc_user_counter($journalu, "C"); - - unless ($pendcid) { - push @$errret, "Unable to allocate pending id"; - return; - } - - # Since these were gotten from the openid:url and won't - # persist in the form data - $form->{'exptype'} = $exptype; - $form->{'etime'} = $etime; - $form->{'ipfixed'} = $ipfixed; - my $penddata = Storable::nfreeze($form); - - unless ($journalu->writer) { - push @$errret, - "Unable to get database handle to store pending comment"; - return; - } - - $journalu->do(qq{ - INSERT INTO pendcomments - SET jid = ?, pendcid = ?, data = ?, datesubmit = UNIX_TIMESTAMP() - }, undef, $journalu->id, $pendcid, $penddata); - - if ($journalu->err) { - push @$errret, $journalu->errstr; - return; - } - - my $returl = "$LJ::SITEROOT/talkpost_do.bml?" . - 'jid=' . $journalu->id . '&' . - "pendcid=$pendcid"; - - LJ::Identity::OpenID->attempt_login($errret, - 'returl' => $returl, - 'returl_fail' => $returl . '&failed=1', - ); -} - -1; Copied: trunk/cgi-bin/LJ/Talk/Author/OpenID.pm (from rev 17094, branches/facebook-integration2/cgi-bin/LJ/Talk/Author/OpenID.pm) =================================================================== --- trunk/cgi-bin/LJ/Talk/Author/OpenID.pm (rev 0) +++ trunk/cgi-bin/LJ/Talk/Author/OpenID.pm 2010-08-09 04:04:46 UTC (rev 17095) @@ -0,0 +1,120 @@ +package LJ::Talk::Author::OpenID; +use strict; + +use base qw(LJ::Talk::Author); + +sub display_params { + my ($class, $opts) = @_; + + my $remote = LJ::get_remote(); + my $form = $opts->{'form'}; + my $is_identity = $remote + && $remote->is_identity + && $remote->identity->short_code eq 'openid'; + + my $is_trusted_identity = $is_identity && $remote->is_trusted_identity; + + my %whocheck = ( + 'openid' => $form->{'usertype'} eq 'openid', + 'openid_cookie' => $form->{'usertype'} eq 'openid_cookie' + || $is_identity, + ); + + return { + 'openid_enabled' => LJ::OpenID->consumer_enabled, + 'is_identity' => $is_identity, + 'is_trusted_identity' => $is_trusted_identity, + 'openid_url_default' => $is_identity + ? $remote->identity->url + : $form->{'openid:url'}, + 'oiddo_login_checked' => $form->{'oiddo_login'} + ? "checked='checked' " + : '', + + 'whocheck_openid' => $whocheck{'openid'}, + 'whocheck_openid_cookie' => $whocheck{'openid_cookie'}, + + 'helpicon_openid' => LJ::help_icon_html( "openid", " " ), + }; +} + +sub want_user_input { + my ($class, $usertype) = @_; + return $usertype =~ /^(?:openid|openid_cookie)$/; +} + +sub handle_user_input { + my ($class, $form, $remote, $need_captcha, $errret, $init) = @_; + + return if @$errret; + + my $journalu = $init->{'journalu'}; + my $up; # user posting + + unless (LJ::OpenID->consumer_enabled) { + push @$errret, "OpenID consumer support is disabled"; + return; + } + + my $remote_is_openid = $remote && + $remote->is_identity && + $remote->identity->short_code eq 'openid'; + + if ($remote_is_openid) { + return LJ::get_remote(); + } + + # First time through + my $csr = LJ::OpenID::consumer(); + my $exptype = 'short'; + my $ipfixed = 0; + my $etime = 0; + + # parse inline login opts + unless ($form->{'openid:url'}) { + push @$errret, "No OpenID identity URL entered"; + return; + } + + # Store the entry + my $pendcid = LJ::alloc_user_counter($journalu, "C"); + + unless ($pendcid) { + push @$errret, "Unable to allocate pending id"; + return; + } + + # Since these were gotten from the openid:url and won't + # persist in the form data + $form->{'exptype'} = $exptype; + $form->{'etime'} = $etime; + $form->{'ipfixed'} = $ipfixed; + my $penddata = Storable::nfreeze($form); + + unless ($journalu->writer) { + push @$errret, + "Unable to get database handle to store pending comment"; + return; + } + + $journalu->do(qq{ + INSERT INTO pendcomments + SET jid = ?, pendcid = ?, data = ?, datesubmit = UNIX_TIMESTAMP() + }, undef, $journalu->id, $pendcid, $penddata); + + if ($journalu->err) { + push @$errret, $journalu->errstr; + return; + } + + my $returl = "$LJ::SITEROOT/talkpost_do.bml?" . + 'jid=' . $journalu->id . '&' . + "pendcid=$pendcid"; + + LJ::Identity::OpenID->attempt_login($errret, + 'returl' => $returl, + 'returl_fail' => $returl . '&failed=1', + ); +} + +1; Deleted: trunk/cgi-bin/LJ/Talk/Author/User.pm =================================================================== --- branches/facebook-integration2/cgi-bin/LJ/Talk/Author/User.pm 2010-08-09 03:27:54 UTC (rev 17094) +++ trunk/cgi-bin/LJ/Talk/Author/User.pm 2010-08-09 04:04:46 UTC (rev 17095) @@ -1,171 +0,0 @@ -package LJ::Talk::Author::User; -use strict; - -use base qw(LJ::Talk::Author); - -sub display_params { - my ( $class, $opts ) = @_; - - my $remote = LJ::get_remote(); - my $form = $opts->{'form'}; - my $journalu = $opts->{'journalu'}; - my $entry = LJ::Entry->new( $journalu, - ditemid => $opts->{ditemid} ); - my $is_friend = LJ::is_friend( $journalu, $remote ); - my $remote_can_comment = $entry->registered_can_comment - or ( $remote and $is_friend ); - - my %whocheck; - - $whocheck{'remote'} = 1 - if $form->{'usertype'} eq 'cookieuser'; - - $whocheck{'remote'} = 1 - if $form->{'userpost'} eq $form->{'cookieuser'}; - - if ($remote_can_comment) { - $whocheck{'ljuser'} = 1 - if $form->{'userpost'} - && $form->{'userpost'} ne $form->{'cookieuser'} - && $form->{'usertype'} ne 'anonymous'; - - $whocheck{'ljuser'} = 1 - if $form->{'usertype'} eq 'user' && !$form->{'userpost'}; - } else { - $whocheck{'ljuser'} = 1; - } - - my $ljuser_def = ""; - if ($remote && $remote->is_person) { - if ( $form->{userpost} ne $form->{cookieuser} - && $form->{usertype} ne 'anonymous' ) - { - $ljuser_def = LJ::ehtml( $form->{userpost} ); - } - else { - $ljuser_def = $remote->username; - } - } - $ljuser_def = "" unless $remote_can_comment; - - return { - 'css_ljuser_row_id' => 'ljuser_row' - . ( $remote_can_comment ? '' : '_cannot' ), - 'username_default' => $ljuser_def, - - 'whocheck_remote' => $whocheck{'remote'}, - 'whocheck_ljuser' => $whocheck{'ljuser'}, - }; -} - -sub want_user_input { - my ($class, $usertype) = @_; - return $usertype =~ /^(?:user|cookieuser)$/; -} - -sub handle_user_input { - my ($class, $form, $remote, $need_captcha, $errret, $init) = @_; - - my $journalu = $init->{'journalu'}; - my $up; # user posting - - if ($form->{'usertype'} eq "cookieuser") { - unless ($remote && $remote->username eq $form->{'cookieuser'}) { - push @$errret, - LJ::Lang::ml("/htdocs/talkpost_do.bml.error.lostcookie"); - return; - } - - $init->{'cookie_auth'} = 1; - return LJ::get_remote(); - } - - # starting from here, we're provided that $form->{'usertype'} eq "user" - # (because want_user_input would return false otherwise) - - # test accounts may only comment on other test accounts. - if ( (grep { $form->{'userpost'} eq $_ } @LJ::TESTACCTS) - && !(grep { $journalu->username eq $_ } @LJ::TESTACCTS) - && !$LJ::IS_DEV_SERVER ) - { - push @$errret, - LJ::Lang::ml("/htdocs/talkpost_do.bml.error.testacct"); - return; - } - - unless ($form->{'userpost'}) { - push @$errret, - LJ::Lang::ml("/htdocs/talkpost_do.bml.error.nousername"); - return; - } - - # parse inline login opts - my ($exptype, $ipfixed); - if ($form->{'userpost'} =~ s/[!<]{1,2}$//) { - $exptype = 'long' if index($&, "!") >= 0; - $ipfixed = LJ::get_remote_ip() if index($&, "<") >= 0; - } - - $up = LJ::load_user($form->{'userpost'}); - unless ($up) { - push @$errret, - LJ::Lang::ml("/htdocs/talkpost_do.bml.error.badusername2", { - 'sitename' => $LJ::SITENAMESHORT, - 'aopts' => "href='$LJ::SITEROOT/lostinfo.bml'", - }); - return; - } - - unless ($up->is_person) { - push @$errret, - LJ::Lang::ml("/htdocs/talkpost_do.bml.error.postshared"); - return; - } - - # if ecphash present, authenticate on that - if ($form->{'ecphash'}) { - my $calc_ecp = LJ::Talk::ecphash( int $init->{'itemid'}+0, - $form->{'parenttalkid'}, - $up->password ); - if ($form->{'ecphash'} eq $calc_ecp) { - $init->{'used_ecp'} = 1; - } else { - push @$errret, - LJ::Lang::ml("/htdocs/talkpost_do.bml.error.badpassword2", { - 'aopts' => "href='$LJ::SITEROOT/lostinfo.bml'", - }); - return; - } - # otherwise authenticate on username/password - } else { - my $ok; - - if ($form->{'response'}) { - $ok = LJ::challenge_check_login( $up, $form->{'chal'}, - $form->{'response'} ); - } else { - $ok = LJ::auth_okay( $up, $form->{'password'}, - $form->{'hpassword'} ); - } - - unless ($ok) { - push @$errret, - LJ::Lang::ml("/htdocs/talkpost_do.bml.error.badpassword2", { - 'aopts' => "href='$LJ::SITEROOT/lostinfo.bml'", - }); - return; - } - } - - # if the user chooses to log in, do so - if ($form->{'do_login'} && ! @$errret) { - $init->{'didlogin'} = $up->make_login_session($exptype, $ipfixed); - } else { - # record their login session anyway - LJ::Session->record_login($up); - } - - return $up; -} - -1; Copied: trunk/cgi-bin/LJ/Talk/Author/User.pm (from rev 17094, branches/facebook-integration2/cgi-bin/LJ/Talk/Author/User.pm) =================================================================== --- trunk/cgi-bin/LJ/Talk/Author/User.pm (rev 0) +++ trunk/cgi-bin/LJ/Talk/Author/User.pm 2010-08-09 04:04:46 UTC (rev 17095) @@ -0,0 +1,171 @@ +package LJ::Talk::Author::User; +use strict; + +use base qw(LJ::Talk::Author); + +sub display_params { + my ( $class, $opts ) = @_; + + my $remote = LJ::get_remote(); + my $form = $opts->{'form'}; + my $journalu = $opts->{'journalu'}; + my $entry = LJ::Entry->new( $journalu, + ditemid => $opts->{ditemid} ); + my $is_friend = LJ::is_friend( $journalu, $remote ); + my $remote_can_comment = $entry->registered_can_comment + or ( $remote and $is_friend ); + + my %whocheck; + + $whocheck{'remote'} = 1 + if $form->{'usertype'} eq 'cookieuser'; + + $whocheck{'remote'} = 1 + if $form->{'userpost'} eq $form->{'cookieuser'}; + + if ($remote_can_comment) { + $whocheck{'ljuser'} = 1 + if $form->{'userpost'} + && $form->{'userpost'} ne $form->{'cookieuser'} + && $form->{'usertype'} ne 'anonymous'; + + $whocheck{'ljuser'} = 1 + if $form->{'usertype'} eq 'user' && !$form->{'userpost'}; + } else { + $whocheck{'ljuser'} = 1; + } + + my $ljuser_def = ""; + if ($remote && $remote->is_person) { + if ( $form->{userpost} ne $form->{cookieuser} + && $form->{usertype} ne 'anonymous' ) + { + $ljuser_def = LJ::ehtml( $form->{userpost} ); + } + else { + $ljuser_def = $remote->username; + } + } + $ljuser_def = "" unless $remote_can_comment; + + return { + 'css_ljuser_row_id' => 'ljuser_row' + . ( $remote_can_comment ? '' : '_cannot' ), + 'username_default' => $ljuser_def, + + 'whocheck_remote' => $whocheck{'remote'}, + 'whocheck_ljuser' => $whocheck{'ljuser'}, + }; +} + +sub want_user_input { + my ($class, $usertype) = @_; + return $usertype =~ /^(?:user|cookieuser)$/; +} + +sub handle_user_input { + my ($class, $form, $remote, $need_captcha, $errret, $init) = @_; + + my $journalu = $init->{'journalu'}; + my $up; # user posting + + if ($form->{'usertype'} eq "cookieuser") { + unless ($remote && $remote->username eq $form->{'cookieuser'}) { + push @$errret, + LJ::Lang::ml("/htdocs/talkpost_do.bml.error.lostcookie"); + return; + } + + $init->{'cookie_auth'} = 1; + return LJ::get_remote(); + } + + # starting from here, we're provided that $form->{'usertype'} eq "user" + # (because want_user_input would return false otherwise) + + # test accounts may only comment on other test accounts. + if ( (grep { $form->{'userpost'} eq $_ } @LJ::TESTACCTS) + && !(grep { $journalu->username eq $_ } @LJ::TESTACCTS) + && !$LJ::IS_DEV_SERVER ) + { + push @$errret, + LJ::Lang::ml("/htdocs/talkpost_do.bml.error.testacct"); + return; + } + + unless ($form->{'userpost'}) { + push @$errret, + LJ::Lang::ml("/htdocs/talkpost_do.bml.error.nousername"); + return; + } + + # parse inline login opts + my ($exptype, $ipfixed); + if ($form->{'userpost'} =~ s/[!<]{1,2}$//) { + $exptype = 'long' if index($&, "!") >= 0; + $ipfixed = LJ::get_remote_ip() if index($&, "<") >= 0; + } + + $up = LJ::load_user($form->{'userpost'}); + unless ($up) { + push @$errret, + LJ::Lang::ml("/htdocs/talkpost_do.bml.error.badusername2", { + 'sitename' => $LJ::SITENAMESHORT, + 'aopts' => "href='$LJ::SITEROOT/lostinfo.bml'", + }); + return; + } + + unless ($up->is_person) { + push @$errret, + LJ::Lang::ml("/htdocs/talkpost_do.bml.error.postshared"); + return; + } + + # if ecphash present, authenticate on that + if ($form->{'ecphash'}) { + my $calc_ecp = LJ::Talk::ecphash( int $init->{'itemid'}+0, + $form->{'parenttalkid'}, + $up->password ); + if ($form->{'ecphash'} eq $calc_ecp) { + $init->{'used_ecp'} = 1; + } else { + push @$errret, + LJ::Lang::ml("/htdocs/talkpost_do.bml.error.badpassword2", { + 'aopts' => "href='$LJ::SITEROOT/lostinfo.bml'", + }); + return; + } + # otherwise authenticate on username/password + } else { + my $ok; + + if ($form->{'response'}) { + $ok = LJ::challenge_check_login( $up, $form->{'chal'}, + $form->{'response'} ); + } else { + $ok = LJ::auth_okay( $up, $form->{'password'}, + $form->{'hpassword'} ); + } + + unless ($ok) { + push @$errret, + LJ::Lang::ml("/htdocs/talkpost_do.bml.error.badpassword2", { + 'aopts' => "href='$LJ::SITEROOT/lostinfo.bml'", + }); + return; + } + } + + # if the user chooses to log in, do so + if ($form->{'do_login'} && ! @$errret) { + $init->{'didlogin'} = $up->make_login_session($exptype, $ipfixed); + } else { + # record their login session anyway + LJ::Session->record_login($up); + } + + return $up; +} + +1; Deleted: trunk/cgi-bin/LJ/Talk/Author.pm =================================================================== --- branches/facebook-integration2/cgi-bin/LJ/Talk/Author.pm 2010-08-09 03:27:54 UTC (rev 17094) +++ trunk/cgi-bin/LJ/Talk/Author.pm 2010-08-09 04:04:46 UTC (rev 17095) @@ -1,132 +0,0 @@ -=head1 NAME - -LJ::Talk::Author - a set of classes to handle various commenting choices, -including logged-in users, anonymous commenters, and identities. - -=head1 SYNOPSIS - - foreach my $author_class (LJ::Talk::Author->all) { - warn $author_class; # 'LJ::Talk::Author::OpenID' - warn $author_class->short_code; # 'OpenID' - warn $author_class->display_params($opts); # 'HASH(0xDEADBEEF)' - } - - my $author_class = LJ::Talk::Author->get_handler('openid'); - die unless $author_class; - warn $author_class->handle_user_input(...); # 'LJ::User=HASH(0xDEADBEEF)' - -=cut - -package LJ::Talk::Author; -use strict; - -use Carp qw(); - -my %code_map; - -=head1 METHODS - -=head2 Base class / final - -=head3 all - -List all of the supported author choices. Used by LJ::Talk::talkform -and LJ::Talk::Post::init. - -=head3 get_handler - -Get the handler for the given 'usertype' form field value. See also: -want_user_input. Used by LJ::Talk::Post::init. - -=cut - -sub all { - return map { "LJ::Talk::Author::$_" } @LJ::TALK_METHODS_ORDER; -} - -sub get_handler { - my ($class, $usertype) = @_; - - foreach my $author_class($class->all) { - return $author_class if $author_class->want_user_input($usertype); - } - - return; -} - -=head2 (Purely) virtual - -=head3 short_code - -Return the "short code" for this author choice. It is used by the -templates/CommentForm/Form.tmpl template to find the corresponding -templates/CommentForm/Author-${short_code}.tmpl template. - -=cut - -sub short_code { - my ($class) = @_; - $class =~ s/^LJ::Talk::Author:://; - return $class; -} - -=head3 display_params($opts) - -Return a hashref with the form params for the same template. The $opts -argument is the same argument that gets passed to LJ::Talk::talkform. -Used by LJ::Talk::talkform. - -=cut - -sub display_params { - my ($class, $opts) = @_; - - my $remote = LJ::get_remote(); - - return {}; -} - -=head3 want_user_input($usertype) - -Return a boolean value indicating that the provided 'usertype' form -field value in the commenting form corresponds to this author class. -Used by get_handler. - -=head3 handle_user_input(...) - - my $up = $author_class->handle_user_input( - $form, - $remote, - $need_captch, - $errret, - $init, - ); - -Handle the user input in the form fields as appropriate with this -commenting choice. The parameters passed are the same parameters that -are passed to LJ::Talk::Post::init, plus an $init hashref that can be -written to to alter the initialization results. - -Returns an LJ::User object that is supposed to be the comment author, or -undef in case the comment is supposed to be posted anonymously. In case -of an error, $errret listref is populated with errors, and the return -value should be discarded. - -Used by LJ::Talk::Post::init. - -=cut - -sub want_user_input { 0 } -sub handle_user_input { - my ($class, $form, $remote, $need_captcha, $errret, $init) = @_; -} - -# initialization code here -foreach my $method (@LJ::TALK_METHODS_ORDER) { - my $package = "LJ::Talk::Author::$method"; - eval "use $package"; - die $@ if $@; - $code_map{$package->short_code} = $package; -} - -1; Copied: trunk/cgi-bin/LJ/Talk/Author.pm (from rev 17094, branches/facebook-integration2/cgi-bin/LJ/Talk/Author.pm) =================================================================== --- trunk/cgi-bin/LJ/Talk/Author.pm (rev 0) +++ trunk/cgi-bin/LJ/Talk/Author.pm 2010-08-09 04:04:46 UTC (rev 17095) @@ -0,0 +1,132 @@ +=head1 NAME + +LJ::Talk::Author - a set of classes to handle various commenting choices, +including logged-in users, anonymous commenters, and identities. + +=head1 SYNOPSIS + + foreach my $author_class (LJ::Talk::Author->all) { + warn $author_class; # 'LJ::Talk::Author::OpenID' + warn $author_class->short_code; # 'OpenID' + warn $author_class->display_params($opts); # 'HASH(0xDEADBEEF)' + } + + my $author_class = LJ::Talk::Author->get_handler('openid'); + die unless $author_class; + warn $author_class->handle_user_input(...); # 'LJ::User=HASH(0xDEADBEEF)' + +=cut + +package LJ::Talk::Author; +use strict; + +use Carp qw(); + +my %code_map; + +=head1 METHODS + +=head2 Base class / final + +=head3 all + +List all of the supported author choices. Used by LJ::Talk::talkform +and LJ::Talk::Post::init. + +=head3 get_handler + +Get the handler for the given 'usertype' form field value. See also: +want_user_input. Used by LJ::Talk::Post::init. + +=cut + +sub all { + return map { "LJ::Talk::Author::$_" } @LJ::TALK_METHODS_ORDER; +} + +sub get_handler { + my ($class, $usertype) = @_; + + foreach my $author_class($class->all) { + return $author_class if $author_class->want_user_input($usertype); + } + + return; +} + +=head2 (Purely) virtual + +=head3 short_code + +Return the "short code" for this author choice. It is used by the +templates/CommentForm/Form.tmpl template to find the corresponding +templates/CommentForm/Author-${short_code}.tmpl template. + +=cut + +sub short_code { + my ($class) = @_; + $class =~ s/^LJ::Talk::Author:://; + return $class; +} + +=head3 display_params($opts) + +Return a hashref with the form params for the same template. The $opts +argument is the same argument that gets passed to LJ::Talk::talkform. +Used by LJ::Talk::talkform. + +=cut + +sub display_params { + my ($class, $opts) = @_; + + my $remote = LJ::get_remote(); + + return {}; +} + +=head3 want_user_input($usertype) + +Return a boolean value indicating that the provided 'usertype' form +field value in the commenting form corresponds to this author class. +Used by get_handler. + +=head3 handle_user_input(...) + + my $up = $author_class->handle_user_input( + $form, + $remote, + $need_captch, + $errret, + $init, + ); + +Handle the user input in the form fields as appropriate with this +commenting choice. The parameters passed are the same parameters that +are passed to LJ::Talk::Post::init, plus an $init hashref that can be +written to to alter the initialization results. + +Returns an LJ::User object that is supposed to be the comment author, or +undef in case the comment is supposed to be posted anonymously. In case +of an error, $errret listref is populated with errors, and the return +value should be discarded. + +Used by LJ::Talk::Post::init. + +=cut + +sub want_user_input { 0 } +sub handle_user_input { + my ($class, $form, $remote, $need_captcha, $errret, $init) = @_; +} + +# initialization code here +foreach my $method (@LJ::TALK_METHODS_ORDER) { + my $package = "LJ::Talk::Author::$method"; + eval "use $package"; + die $@ if $@; + $code_map{$package->short_code} = $package; +} + +1; Deleted: trunk/cgi-bin/LJ/Talk/Post.pm =================================================================== --- branches/facebook-integration2/cgi-bin/LJ/Talk/Post.pm 2010-08-09 03:27:54 UTC (rev 17094) +++ trunk/cgi-bin/LJ/Talk/Post.pm 2010-08-09 04:04:46 UTC (rev 17095) @@ -1,912 +0,0 @@ -package LJ::Talk::Post; -use strict; - -use LJ::EventLogRecord::NewComment; - -sub indent { - my $a = shift; - my $leadchar = shift || " "; - require Text::Wrap; - $Text::Wrap::columns = 76; - return Text::Wrap::fill("$leadchar ", "$leadchar ", $a); -} - -sub blockquote { - my $a = shift; - return "<blockquote style='border-left: #000040 2px solid; margin-left: 0px; margin-right: 0px; padding-left: 15px; padding-right: 0px'>$a</blockquote>"; -} - -sub generate_messageid { - my ($type, $journalu, $did) = @_; - # $type = {"entry" | "comment"} - # $journalu = $u of journal - # $did = display id of comment/entry - - my $jid = $journalu->{userid}; - return "<$type-$jid-$did\@$LJ::DOMAIN>"; -} - -sub enter_comment { - my ($journalu, $parent, $item, $comment, $errref) = @_; - - my $partid = $parent->{talkid}; - my $itemid = $item->{itemid}; - - my $err = sub { - $$errref = join(": ", @_); - return 0; - }; - - return $err->("Invalid user object passed.") - unless LJ::isu($journalu); - - LJ::run_hooks('update_comment_props', $j... (truncated)