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>";
                                 }
                             }
                         }
--------------------------------------------------------------------------------