Add the ability to apply a minsecurity for each remote account you can 
crosspost to. Behaves the same way as local minsecurity, and retains the 
minsecurity on edit (if you set a minsecurity of access-only, if you edit an 
entry to public here the security will remain friends-only on the other site. 
If you edit an entry to private here, the security will be changed to private 
on the other site.).

        Patch by allen. 

diffs (413 lines):

diff -r 65a29c20761c -r df531c62cb65 bin/upgrading/update-db-general.pl
--- a/bin/upgrading/update-db-general.pl        Mon Sep 20 22:09:58 2010 +0800
+++ b/bin/upgrading/update-db-general.pl        Tue Sep 21 17:03:48 2010 +0800
@@ -2821,6 +2821,7 @@ CREATE table externalaccount (
     serviceurl varchar(128),
     xpostbydefault enum('1','0') NOT NULL default '0',
     recordlink enum('1','0') NOT NULL default '0',
+    options blob,
     primary key (userid, acctid),
     index (userid)
 )
@@ -3925,6 +3926,11 @@ EOF
         }
         set_dbnote( "unsplit_stats_timestamps", 1 )
     }
+
+    unless ( column_type( 'externalaccount', 'options' ) ) {
+        do_alter( 'externalaccount',
+                  "ALTER TABLE externalaccount ADD COLUMN options blob");
+    }
 });
 
 
diff -r 65a29c20761c -r df531c62cb65 cgi-bin/DW/External/Account.pm
--- a/cgi-bin/DW/External/Account.pm    Mon Sep 20 22:09:58 2010 +0800
+++ b/cgi-bin/DW/External/Account.pm    Tue Sep 21 17:03:48 2010 +0800
@@ -30,9 +30,9 @@ sub _memcache_stored_props          {
 sub _memcache_stored_props          {
     # first element of props is a VERSION
     # next - allowed object properties
-    return qw/ 2
+    return qw/ 3
                userid acctid
-               siteid username password servicename servicetype serviceurl 
xpostbydefault recordlink
+               siteid username password servicename servicetype serviceurl 
xpostbydefault recordlink options
                /;
 }
 sub _memcache_hashref_to_object {
@@ -81,7 +81,7 @@ sub get_external_accounts {
         return @accounts;
     }
 
-    my $sth = $u->prepare("SELECT userid, acctid, siteid, username, password, 
servicename, servicetype, serviceurl, xpostbydefault, recordlink FROM 
externalaccount WHERE userid=?");
+    my $sth = $u->prepare( "SELECT userid, acctid, siteid, username, password, 
servicename, servicetype, serviceurl, xpostbydefault, recordlink, options FROM 
externalaccount WHERE userid=?" );
     $sth->execute($u->userid);
     LJ::throw($u->errstr) if $u->err;
 
@@ -107,7 +107,7 @@ sub get_external_account {
         return $cached_value;
     }
 
-    my $sth = $u->prepare("SELECT userid, siteid, acctid, username, password, 
servicename, servicetype, serviceurl, xpostbydefault, recordlink FROM 
externalaccount WHERE userid=? and acctid=?");
+    my $sth = $u->prepare( "SELECT userid, siteid, acctid, username, password, 
servicename, servicetype, serviceurl, xpostbydefault, recordlink, options FROM 
externalaccount WHERE userid=? and acctid=?" );
     $sth->execute($u->userid, $acctid);
     LJ::throw($u->err) if ($u->err);
 
@@ -164,7 +164,7 @@ sub xpost_string_to_hash {
 # instance methods
 sub absorb_row {
     my ($self, $row) = @_;
-    for my $f (qw(username siteid password servicename servicetype serviceurl 
xpostbydefault recordlink)) {
+    for my $f ( qw( username siteid password servicename servicetype 
serviceurl xpostbydefault recordlink options ) ) {
         $self->{$f} = $row->{$f};
     }
     return $self;
@@ -184,7 +184,10 @@ sub create {
     my $protocol = DW::External::XPostProtocol->get_protocol($protocol_id);
     my $encryptedpassword = $protocol->encrypt_password($opts->{password});
 
-    $u->do("INSERT INTO externalaccount (userid, acctid, siteid, username, 
password, servicename, servicetype, serviceurl, xpostbydefault, recordlink) 
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", undef, $u->{userid}, $acctid, 
$opts->{siteid}, $opts->{username}, $encryptedpassword, $opts->{servicename}, 
$opts->{servicetype}, $opts->{serviceurl}, $opts->{xpostbydefault} ? '1' : '0', 
$opts->{recordlink} ? '1' : '0' );
+    # convert the options hashref to a single field
+    my $options_blob = $class->xpost_hash_to_string( $opts->{options} );
+
+    $u->do( "INSERT INTO externalaccount ( userid, acctid, siteid, username, 
password, servicename, servicetype, serviceurl, xpostbydefault, recordlink, 
options ) values ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )", undef, $u->{userid}, 
$acctid, $opts->{siteid}, $opts->{username}, $encryptedpassword, 
$opts->{servicename}, $opts->{servicetype}, $opts->{serviceurl}, 
$opts->{xpostbydefault} ? '1' : '0', $opts->{recordlink} ? '1' : '0', 
$options_blob );
     
     LJ::throw($u->errstr) if $u->err;
 
@@ -396,6 +399,17 @@ sub recordlink {
     return $_[0]->{recordlink};
 }
 
+# returns the (protocol-specific) options as a hash ref
+sub options {
+    my $self = $_[0];
+    unless ( $self->{options_map} ) {
+        my $options_map = DW::External::Account->xpost_string_to_hash( 
$self->{options} );
+        $self->{options_map} = $options_map;
+    }
+
+    return $self->{options_map};
+}
+
 # if there is an external site configured, returns it; otherwise returns undef
 sub externalsite {
     return undef unless $_[0]->{siteid};
@@ -496,4 +510,26 @@ sub set_password {
     return 1;
 }
 
+# sets the (protocol-specific) options.  takes a hashref as the options
+# argument.
+sub set_options {
+    my ( $self, $options ) = @_;
+
+    my $u = $self->owner;
+
+    # convert the hash to a string.
+    my $newvalue = DW::External::Account->xpost_hash_to_string( $options );
+    
+    $u->do( "UPDATE externalaccount SET options=? WHERE userid=? AND 
acctid=?", undef, $newvalue, $u->{userid}, $self->acctid );
+    LJ::throw($u->errstr) if $u->err;
+
+    # set options to the new value and clear options_map
+    $self->{options} = $newvalue;
+    $self->{options_map} = undef;
+    
+    $self->_remove_from_memcache($self->_memcache_id);
+
+    return 1;
+}
+
 1;
diff -r 65a29c20761c -r df531c62cb65 cgi-bin/DW/External/Site.pm
--- a/cgi-bin/DW/External/Site.pm       Mon Sep 20 22:09:58 2010 +0800
+++ b/cgi-bin/DW/External/Site.pm       Tue Sep 21 17:03:48 2010 +0800
@@ -144,4 +144,10 @@ sub pre_crosspost_hook {
     return $_[1];
 }
 
+# returns the servicetype
+sub servicetype {
+    return $_[0]->{servicetype};
+}
+
+
 1;
diff -r 65a29c20761c -r df531c62cb65 cgi-bin/DW/External/XPostProtocol.pm
--- a/cgi-bin/DW/External/XPostProtocol.pm      Mon Sep 20 22:09:58 2010 +0800
+++ b/cgi-bin/DW/External/XPostProtocol.pm      Tue Sep 21 17:03:48 2010 +0800
@@ -164,4 +164,9 @@ sub supports_challenge {
     return 0;
 }
 
+# returns the options for this protocol
+sub protocol_options {
+    return ();
+}
+
 1;
diff -r 65a29c20761c -r df531c62cb65 
cgi-bin/DW/External/XPostProtocol/LJXMLRPC.pm
--- a/cgi-bin/DW/External/XPostProtocol/LJXMLRPC.pm     Mon Sep 20 22:09:58 
2010 +0800
+++ b/cgi-bin/DW/External/XPostProtocol/LJXMLRPC.pm     Tue Sep 21 17:03:48 
2010 +0800
@@ -292,6 +292,16 @@ sub entry_to_req {
         }
     }
 
+    # check minsecurity if set
+    if ( my $minsecurity = $extacct->options->{minsecurity} ) {
+        if ( $minsecurity eq "private" ) {
+            $req->{security} = "private";
+        } elsif ( ( $minsecurity eq "friends" ) && ( $req->{security} eq 
"public" ) ) {
+            $req->{security} = 'usemask';
+            $req->{allowmask} = 1;
+        }
+    }
+
     # set the date.
     my $eventtime = $entry->eventtime_mysql;
     $eventtime =~ /^(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d)/;
@@ -572,4 +582,25 @@ sub supports_challenge {
     return 1;
 }
 
+# returns the options for this protocol
+sub protocol_options {
+    my ( $self, $extacct, $POST ) = @_;
+    my $option = {
+        type => 'select',
+        description => BML::ml( '.protocol.ljxmlrpc.minsecurity.desc' ),
+        opts => {
+            id => 'minsecurity',
+            name => 'minsecurity',
+            selected => $POST ? $POST->{minsecurity} : ( $extacct && 
$extacct->options && $extacct->options->{minsecurity} ) ? 
$extacct->options->{minsecurity} : 'public',
+        },
+        options => [
+            'public', BML::ml( '.protocol.ljxmlrpc.minsecurity.public' ),
+            'friends', BML::ml( '.protocol.ljxmlrpc.minsecurity.friends' ),
+            'private', BML::ml( '.protocol.ljxmlrpc.minsecurity.private' ),
+        ],
+    };
+    my @return_value =  ( $option );
+    return @return_value;
+}
+
 1;
diff -r 65a29c20761c -r df531c62cb65 htdocs/js/externalaccount.js
--- a/htdocs/js/externalaccount.js      Mon Sep 20 22:09:58 2010 +0800
+++ b/htdocs/js/externalaccount.js      Tue Sep 21 17:03:48 2010 +0800
@@ -1,4 +1,9 @@
+// the siteProtocol (if edit), or the map of sites to protocols (if new)
+var siteProtocol = null;
+var siteProtocolMap = {};
 
+// callback for updating the site selection.  if selecting 'custom site',
+// shows the customsitetable.  also calls to updateProtocolSelection().
 function updateSiteSelection() {
   var siteSelect = document.getElementById("createacct");
   if (siteSelect != null && siteSelect.site != null) {
@@ -9,5 +14,42 @@ function updateSiteSelection() {
       customsitetable.style.display='none';
     }
   }
+  updateProtocolSelection();
 }
 
+// returns the currently selected protocol.  if we're editing an account,
+// uses the preset siteProtocol.  otherwise checks the siteProtocolMap (if a
+// configured site is selected) or the selected servicetype (if a custom site
+// is selected)
+function getProtocol() {
+  if (siteProtocol != null)
+    return siteProtocool;
+
+  var siteSelect = document.getElementById("createacct");
+  if (siteSelect != null && siteSelect.site != null) {
+    var customsitetable = document.getElementById('customsite');
+    if (siteSelect.site.value == -1) {
+      return $('servicetype').value;
+    } else {
+      return siteProtocolMap[siteSelect.site.value];
+    }
+  }
+}
+
+// updates the protocol selection.  shows/hides the appropriate options rows.
+function updateProtocolSelection() {
+  var protocol = getProtocol();
+  var optionBodies = DOM.getElementsByTagAndClassName(document, "tbody", 
"protocol_options") || [];
+  for (var i = 0; i < optionBodies.length; i++) {
+    var optionBody = optionBodies[i];
+    if ( optionBody.id != protocol + '_options' ) {
+      optionBody.style.display='none';
+    } else {
+      optionBody.style.display='';
+    }
+  }
+
+}
+
+LiveJournal.register_hook("page_load", updateProtocolSelection);
+
diff -r 65a29c20761c -r df531c62cb65 htdocs/manage/externalaccount.bml
--- a/htdocs/manage/externalaccount.bml Mon Sep 20 22:09:58 2010 +0800
+++ b/htdocs/manage/externalaccount.bml Tue Sep 21 17:03:48 2010 +0800
@@ -77,28 +77,37 @@ use strict;
         $body .= LJ::html_hidden('acctid', $editacct->acctid);
     }
 
-    my @sitevalues;
-    my @sites = DW::External::Site->get_xpost_sites;
-
-    foreach my $site (sort { $a->{sitename} cmp $b->{sitename} } @sites) {
-        push @sitevalues, $site->{siteid},  $site->{sitename};
-    }
-    # add custom
-    push @sitevalues, '-1';
-    push @sitevalues, $ML{'.setting.xpost.option.site.custom'};
+    $body .= "<br />";
 
     my %protocols =  DW::External::XPostProtocol->get_all_protocols;
-    my %protocolselectmap;
-    foreach my $protocol (keys %protocols) {
-        $protocolselectmap{$protocol} = $protocol;
-    }
-
-    $body .= "<br />";
 
     $body .= "<tr><td class='setting_label'><label for='site'>" . 
$ML{'.setting.xpost.option.site'} . "</label></td>";
     if ($editpage) {
         $body .= "<td>" . $editacct->servername . "</td>\n";
+        $body .= "<script type='text/javascript'>\n   siteProtocol = '" . 
$editacct->protocol->protocolid . "';\n</script>\n";
     } else {
+        my @sitevalues;
+        my @sites = DW::External::Site->get_xpost_sites;
+        
+        # sort the sites for the site dropdown, but also add in the protocol
+        # map for the options hide/show
+        $body .= "<script type='text/javascript'>\n";
+        foreach my $site (sort { $a->{sitename} cmp $b->{sitename} } @sites) {
+            push @sitevalues, $site->{siteid},  $site->{sitename};
+            $body .= "siteProtocolMap[" . $site->{siteid} . "] = '" . 
$site->servicetype . "';\n";
+        }
+        $body .= "</script>\n";
+        
+        # add the custom site option
+        push @sitevalues, '-1';
+        push @sitevalues, $ML{'.setting.xpost.option.site.custom'};
+        
+        # the values for the protocol selection dropdown for custom sites
+        my %protocolselectmap;
+        foreach my $protocol (keys %protocols) {
+            $protocolselectmap{$protocol} = $protocol;
+        }
+        
         $body .= "<td>" . LJ::html_select({
             name => "site", 
             onchange => "updateSiteSelection()",
@@ -110,7 +119,7 @@ use strict;
         $body .= "<td>" . LJ::html_select({
             name => "servicetype",
             id => "servicetype",
-            onchange => "updateProtocolSelection" }, %protocolselectmap);
+            onchange => "updateProtocolSelection()" }, %protocolselectmap);
         
         my $servicetype_errdiv = errdiv(\%errs, "servicetype");
         $body .= "<br />$servicetype_errdiv" if $servicetype_errdiv;
@@ -233,6 +242,22 @@ use strict;
     $body .= "<br />$savepassword_errdiv" if $savepassword_errdiv;
     $body .= "</td></tr>\n";
     
+    # put in the protocol option section for each protocol
+    foreach my $protocol_id ( keys %protocols ) {
+        my $protocol = $protocols{$protocol_id};
+        my @protocol_options = $protocol->protocol_options( $editacct, 
LJ::did_post() ? \%POST : undef );
+        if ( @protocol_options ) {
+            $body .= "<tbody class='protocol_options' id='" . $protocol_id . 
"_options'><tr><td>" . BML::ml( '.protocol.options', { protocol => 
$protocol->protocolid } ) . "</td>\n";
+            $body .="<td>";
+            foreach my $option ( @protocol_options ) { 
+                if ( $option->{type} eq 'select' ) {
+                    $body .= "<label for=" . $option->{opts}->{propid} . ">" . 
LJ::ehtml( $option->{description} ) . "</label>" . LJ::html_select( 
$option->{opts}, @{$option->{options}} ) . "</td>\n";
+                }
+            }
+        }
+        $body .= "</td></tr></tbody>\n";
+    }
+
     $body .= "<tr><td>";
     $body .= "<br />";
     $body .= LJ::html_submit(undef, $editpage ? $ML{'.btn.update'} : 
$ML{'.btn.create'});
@@ -338,7 +363,19 @@ sub create_external_account {
         }
     }
 
-    if ($ok) {
+    if ( $ok ) {
+        # check the options, if any.
+        my $protocol;
+        if ( $opts{siteid} ) {
+            my $site = DW::External::Site->get_site_by_id( $opts{siteid} );
+            $protocol = DW::External::XPostProtocol->get_protocol( 
$site->servicetype );
+        } else { 
+            $protocol = DW::External::XPostProtocol->get_protocol( 
$opts{servicetype} );
+        }
+        my $options = parse_options( $protocol, $POST );
+
+        $opts{options} = $options;
+
         # if the user requested that we don't save their password, then
         # don't save their password.
         $opts{password} = "" unless $opts{savepassword};
@@ -367,7 +404,7 @@ sub account_isvalid {
         my $siteid = $extacct->{site};
         my $externalsite = DW::External::Site->get_site_by_id( $siteid );
         $proxyurl = "http://"; . $externalsite->{domain} . "/interface/xmlrpc";
-        $protocol_id = $externalsite->{servicetype};
+        $protocol_id = $externalsite->servicetype;
     } else {
         $proxyurl = $extacct->{serviceurl}; 
         $protocol_id = $extacct->{servicetype};
@@ -408,7 +445,23 @@ sub edit_external_account {
     $acct->set_xpostbydefault($POST{xpostbydefault});
     $acct->set_recordlink($POST{recordlink});
 
+    $acct->set_options( parse_options( $acct->protocol, $POST ) );
+
     return "&update=" . $acct->acctid;
+}
+
+# returns the appropriate options from the post.
+sub parse_options {
+    my ( $protocol, $POST ) = @_;
+    my $options = {};
+    foreach my $option ( $protocol->protocol_options ) {
+        my $option_name = $option->{opts}->{name};
+        my $value = $POST{$option_name};
+        if ( $value ) {
+            $options->{$option_name} = $value;
+        }
+    }
+    return $options;
 }
 
 _code?>
diff -r 65a29c20761c -r df531c62cb65 htdocs/manage/externalaccount.bml.text
--- a/htdocs/manage/externalaccount.bml.text    Mon Sep 20 22:09:58 2010 +0800
+++ b/htdocs/manage/externalaccount.bml.text    Tue Sep 21 17:03:48 2010 +0800
@@ -7,6 +7,16 @@
 .error.maxacct.plural=You are already at your limit of [[max_accts]] accounts.
 
 .error.maxacct.singular=You are already at your limit of [[max_accts]] account.
+
+.protocol.ljxmlrpc.minsecurity.desc=Minimum Security
+
+.protocol.ljxmlrpc.minsecurity.friends=Friends
+
+.protocol.ljxmlrpc.minsecurity.private=Private
+
+.protocol.ljxmlrpc.minsecurity.public=Public
+
+.protocol.options=[[protocol]] options
 
 .settings.xpost.error.ipban=Too many log-in attempts. Please try creating the 
account again later.
 
_______________________________________________
dw-changelog mailing list
[email protected]
http://lists.dwscoalition.org/mailman/listinfo/dw-changelog

Reply via email to