mark: A photo of Mark kneeling on top of the Taal Volcano in the Philippines. It was a long hike. (Default)
Mark Smith ([staff profile] mark) wrote in [site community profile] changelog2009-04-29 06:41 am

[dw-free] crossposter stripping LJ code

[commit: http://hg.dwscoalition.org/dw-free/rev/f6dbed2712c3]

http://bugs.dwscoalition.org/show_bug.cgi?id=938

Xposter: properly our tags to remote site tags. This should fix <cut>, etc.

Patch by [personal profile] allen.

Files modified:
  • bin/upgrading/en.dat
  • cgi-bin/DW/External/XPostProtocol/LJXMLRPC.pm
  • htdocs/editjournal.bml
  • htdocs/update.bml
--------------------------------------------------------------------------------
diff -r efe0c2bfca94 -r f6dbed2712c3 bin/upgrading/en.dat
--- a/bin/upgrading/en.dat	Wed Apr 29 06:23:44 2009 +0000
+++ b/bin/upgrading/en.dat	Wed Apr 29 06:41:40 2009 +0000
@@ -4543,7 +4543,7 @@ xpost.redirect.comment=<span style="font
 
 xpost.request.success=Crosspost requested to [[account]].  You will be notified when this attempt has completed.
 
-xpost.request.failed=Failed to crosspost to [[account]].  You may go to [[editurl]] to attempt to crosspost this entry again.
+xpost.request.failed=Failed to crosspost to [[account]].  You may go <a href = "[[editurl]]">here</a> to attempt to crosspost this entry again.
 
 xpost.success=Crosspost to [[username]]@[[server]] successful.  You can view this entry <a href = "[[xpostlink]]">here</a>.
 
diff -r efe0c2bfca94 -r f6dbed2712c3 cgi-bin/DW/External/XPostProtocol/LJXMLRPC.pm
--- a/cgi-bin/DW/External/XPostProtocol/LJXMLRPC.pm	Wed Apr 29 06:23:44 2009 +0000
+++ b/cgi-bin/DW/External/XPostProtocol/LJXMLRPC.pm	Wed Apr 29 06:41:40 2009 +0000
@@ -94,7 +94,7 @@ sub crosspost {
         $req = { event => '' };
     } else {
         # if it's a post or edit, fully populate the request.
-        $req = $self->entry_to_req($entry);
+        $req = $self->entry_to_req($entry, $extacct);
         # handle disable comments
         if ($extacct->owner->prop('opt_xpost_disable_comments')) {
             if ($req->{props}->{opt_nocomments}) {
@@ -171,12 +171,12 @@ sub validate_server {
 
 # translates at Entry object into a request for crossposting
 sub entry_to_req {
-    my ($self, $entry) = @_;
+    my ($self, $entry, $extacct) = @_;
 
     # basic parts of the request
     my $req = {
         'subject' => $entry->subject_text,
-        'event' => $self->clean_entry_text($entry),
+        'event' => $self->clean_entry_text($entry, $extacct),
         'security' => $entry->security,
     };
 
@@ -218,6 +218,127 @@ sub entry_to_req {
 
     return $req;
 }
+
+# cleans the entry text for crossposting
+# overrides default implementation for use with LJ-based sites
+sub clean_entry_text {
+    my ($self, $entry, $extacct) = @_;
+
+    my $event_text = $entry->event_raw;
+
+    # clean up lj-tags
+    $self->clean_lj_tags(\$event_text, $extacct);
+    
+    # clean up any embedded objects
+    LJ::EmbedModule->expand_entry($entry->journal, \$event_text, expand_full => 1);
+    
+    # remove polls, then return the text
+    return $self->scrub_polls($event_text);
+}
+
+# cleans up lj-tags for crossposting
+sub clean_lj_tags {
+    my ($self, $entry_text_ref, $extacct) = @_;
+    my $p = HTML::TokeParser->new($entry_text_ref);
+    my $newdata = "";
+
+    # this is mostly gakked from cgi-bin/cleanhtml.pl
+
+    # go throught each token.
+  TOKEN:
+    while (my $token = $p->get_token) {
+        my $type = $token->[0];
+        # See if this tag should be treated as an alias
+        
+        if ($type eq "S") {
+            my $tag = $token->[1];
+            my $hash  = $token->[2]; # attribute hashref
+            my $attrs = $token->[3]; # attribute names, in original order
+
+            # we need to rewrite cut tags as lj-cut
+            if ($tag eq "cut") {
+                $tag = "lj-cut";
+                
+                # for tags like <name/>, pretend it's <name> and reinsert the slash later
+                my $slashclose = 0;   # If set to 1, use XML-style empty tag marker
+                $slashclose = 1 if delete $hash->{'/'};
+                
+                # spit it back out
+                $newdata .= "<$tag";
+                # output attributes in original order
+                foreach (@$attrs) {
+                    $newdata .= " $_=\"" . LJ::ehtml($hash->{$_}) . "\""
+                        if exists $hash->{$_};
+                }
+                $newdata .= " /" if $slashclose;
+                $newdata .= ">";
+            } elsif ($tag eq 'lj' || $tag eq 'user') {
+                my $user = $hash->{user} = exists $hash->{name} ? $hash->{name} :
+                    exists $hash->{user} ? $hash->{user} :
+                    exists $hash->{comm} ? $hash->{comm} : undef;
+                
+                # allow external sites
+                if (my $site = $hash->{site}) {
+                    # try to load this user@site combination
+                    if (my $ext_u = DW::External::User->new( user => $user, site => $site )) {
+                        # if the sites match, make this into a standard 
+                        # lj user tag
+                        if ($ext_u->site == $extacct->externalsite) {
+                            $newdata .= "<lj user=\"$user\">";
+                        } else {
+                            $newdata .= $ext_u->ljuser_display(no_ljuser_class => 1);
+                        }
+                    } else {
+                        # if we hit the else, then we know that this user doesn't appear
+                        # to be valid at the requested site
+                        $newdata .= "<b>[Bad username or site: " .
+                            LJ::ehtml( LJ::no_utf8_flag( $user ) ) . " @ " .
+                            LJ::ehtml( LJ::no_utf8_flag( $site ) ) . "]</b>";
+                    }
+                    # failing that, no site, use the local behavior
+                } elsif (length $user) {
+                    my $orig_user = $user;
+                    $user = LJ::canonical_username($user);
+                    if (length $user) {
+                        $newdata .= LJ::ljuser( $user, { no_ljuser_class => 1 });
+                    } else {
+                        $orig_user = LJ::no_utf8_flag($orig_user);
+                        $newdata .= "<b>[Bad username: " . LJ::ehtml($orig_user) . "]</b>";
+                    }
+                } else {
+                    $newdata .= "<b>[Unknown LJ tag]</b>";
+                }
+            } else {
+                # if no change was necessary
+                $newdata .= $token->[4];
+                next TOKEN;
+            }
+        }
+        elsif ($type eq "E") {
+            if ($token->[1] eq "cut") {
+                $newdata .= "</lj-cut>";
+            } else {
+                $newdata .= $token->[2];
+            }
+        }
+        elsif ($type eq "D") {
+            $newdata .= $token->[1];
+        }
+        elsif ($type eq "T") {
+            $newdata .= $token->[1];
+        }
+        elsif ($type eq "C") {
+            $newdata .= $token->[1];
+        }
+        elsif ($type eq "PI") {
+            $newdata .= $token->[2];
+        }
+    } # end while
+    
+    $$entry_text_ref = $newdata;
+    return undef;
+}
+
 
 sub protocolid {
     my $self = shift;
diff -r efe0c2bfca94 -r f6dbed2712c3 htdocs/editjournal.bml
--- a/htdocs/editjournal.bml	Wed Apr 29 06:23:44 2009 +0000
+++ b/htdocs/editjournal.bml	Wed Apr 29 06:41:40 2009 +0000
@@ -276,8 +276,7 @@ body<=
                                 push @xpost_success, "<li>" . BML::ml('xpost.request.success', {'account' => $acct->displayname}) . "</li>";
                             } else {
                                 # one of them didn't work.
-                                push @xpost_success, "<li>" . BML::ml('xpost.request.success', {'account' => $acct->displayname}) . "</li>";
-                                push @xpost_errors, "<li><div style='color: red;'><strong>" . BML::ml('xpost.request.failed', {'account' => $acct->displayname}, 'editurl' => $edititemlink)  . " </strong></div></li>";
+                                push @xpost_errors, "<li><div style='color: red;'><strong>" . BML::ml('xpost.request.failed', { 'account' => $acct->displayname, 'editurl' => $edititemlink })  . " </strong></div></li>";
                             }
                         }
                     }
diff -r efe0c2bfca94 -r f6dbed2712c3 htdocs/update.bml
--- a/htdocs/update.bml	Wed Apr 29 06:23:44 2009 +0000
+++ b/htdocs/update.bml	Wed Apr 29 06:41:40 2009 +0000
@@ -468,8 +468,7 @@
                                     push @xpost_success, "<li>" . BML::ml('xpost.request.success', {'account' => $acct->displayname}) . "</li>";
                                 } else {
                                     # one of them didn't work.
-                                    push @xpost_success, "<li>" . BML::ml('xpost.request.success', {'account' => $acct->displayname}) . "</li>";
-                                    push @xpost_errors, "<li><div style='color: red;'><strong>" . BML::ml('xpost.request.failed', {'account' => $acct->displayname}, 'editurl' => $edititemlink)  . " </strong></div></li>";
+                                    push @xpost_errors, "<li><div style='color: red;'><strong>" . BML::ml('xpost.request.failed', { 'account' => $acct->displayname, 'editurl' => $edititemlink })  . " </strong></div></li>";
                                 }
                             }
                         }
--------------------------------------------------------------------------------

Post a comment in response:

This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

If you are unable to use this captcha for any reason, please contact us by email at support@dreamwidth.org