diff --git a/include/class.format.php b/include/class.format.php
index b8cfe03be6f60302ce9f5fabd972b012c1694248..70b06a8a37c09f05f0e27017f9d520c08f99cd29 100644
--- a/include/class.format.php
+++ b/include/class.format.php
@@ -352,7 +352,7 @@ class Format {
     }
 
     //Format text for display..
-    function display($text, $inline_images=true) {
+    function display($text, $inline_images=true, $balance=true) {
         // Make showing offsite images optional
         $text = preg_replace_callback('/<img ([^>]*)(src="http[^"]+")([^>]*)\/>/',
             function($match) {
@@ -363,8 +363,10 @@ class Format {
             },
             $text);
 
-        //make urls clickable.
-        $text = self::html_balance($text, false);
+        if ($balance)
+            $text = self::html_balance($text, false);
+
+        // make urls clickable.
         $text = Format::clickableurls($text);
 
         if ($inline_images)
diff --git a/include/class.thread.php b/include/class.thread.php
index c3d58f3b9f56783ef491e18ed35c91bf013a61ba..5b412f2357ca7f25d211bb77a3f4bfc669e9542d 100644
--- a/include/class.thread.php
+++ b/include/class.thread.php
@@ -378,6 +378,7 @@ class Thread extends VerySimpleModel {
         ) {
             $vars['userId'] = $mailinfo['userId'] ?: $C->getUserId();
             $vars['message'] = $body;
+            $vars['flags'] = ThreadEntry::FLAG_COLLABORATOR;
 
             if ($object instanceof Threadable)
                 return $object->postThreadEntry('M', $vars);
@@ -611,6 +612,9 @@ implements TemplateVariable {
     const FLAG_GUARDED                  = 0x0008;   // No replace on edit
     const FLAG_RESENT                   = 0x0010;
 
+    const FLAG_COLLABORATOR             = 0x0020;   // Message from collaborator
+    const FLAG_BALANCED                 = 0x0040;   // HTML does not need to be balanced on ::display()
+
     const PERM_EDIT     = 'thread.edit';
 
     var $_headers;
@@ -665,7 +669,9 @@ implements TemplateVariable {
     }
 
     function getBody() {
-        return ThreadEntryBody::fromFormattedText($this->body, $this->format);
+        return ThreadEntryBody::fromFormattedText($this->body, $this->format,
+            array('balanced' => $this->hasFlag(self::FLAG_BALANCED))
+        );
     }
 
     function setBody($body) {
@@ -1354,8 +1360,13 @@ implements TemplateVariable {
             'user_id' => $vars['userId'],
             'poster' => $poster,
             'source' => $vars['source'],
+            'flags' => $vars['flags'] ?: 0,
         ));
 
+        if ($entry->format == 'html')
+            // The current codebase properly balances html
+            $entry->flags |= self::FLAG_BALANCED;
+
         if (!isset($vars['attachments']) || !$vars['attachments'])
             // Otherwise, body will be configured in a block below (after
             // inline attachments are saved and updated in the database)
@@ -2113,12 +2124,12 @@ class ThreadEntryBody /* extends SplString */ {
         return Format::searchable($this->body);
     }
 
-    static function fromFormattedText($text, $format=false) {
+    static function fromFormattedText($text, $format=false, $options=array()) {
         switch ($format) {
         case 'text':
             return new TextThreadEntryBody($text);
         case 'html':
-            return new HtmlThreadEntryBody($text, array('strip-embedded'=>false));
+            return new HtmlThreadEntryBody($text, array('strip-embedded'=>false) + $options);
         default:
             return new ThreadEntryBody($text);
         }
@@ -2207,7 +2218,7 @@ class HtmlThreadEntryBody extends ThreadEntryBody {
         case 'pdf':
             return Format::clickableurls($this->body);
         default:
-            return Format::display($this->body);
+            return Format::display($this->body, true, !$this->options['balanced']);
         }
     }
 }
diff --git a/include/staff/templates/thread-entry.tmpl.php b/include/staff/templates/thread-entry.tmpl.php
index 5b9c3b132a04de1efbbe530a8059d6dee1d6e6b3..3f3bfee7c97316a62a87ac00716eafdc7e513a32 100644
--- a/include/staff/templates/thread-entry.tmpl.php
+++ b/include/staff/templates/thread-entry.tmpl.php
@@ -41,9 +41,12 @@ if ($user)
             echo sprintf(__('Edited on %s by %s'), Format::datetime($entry->updated),
                 ($editor = $entry->getEditor()) ? $editor->getName() : '');
                 ?>"><?php echo __('Edited'); ?></span>
-<?php   } ?>
-<?php   if ($entry->flags & ThreadEntry::FLAG_RESENT) { ?>
+<?php   }
+        if ($entry->flags & ThreadEntry::FLAG_RESENT) { ?>
             <span class="label label-bare"><?php echo __('Resent'); ?></span>
+<?php   }
+        if ($entry->flags & ThreadEntry::FLAG_COLLABORATOR) { ?>
+            <span class="label label-bare"><?php echo __('Collaborator'); ?></span>
 <?php   } ?>
         </span>
         </div>
diff --git a/scp/css/scp.css b/scp/css/scp.css
index 9014081c9fd20d07e6ecafd6d292209da26b9303..12389fb2660b96b1adcc3e97199fd26bae6e3f7c 100644
--- a/scp/css/scp.css
+++ b/scp/css/scp.css
@@ -971,6 +971,9 @@ img.avatar {
     display: inline-block;
     margin-left: 15px;
 }
+.thread-entry .header .button {
+    margin-top: -4px;
+}
 
 .thread-entry .thread-body {
     border: 1px solid #ddd;
diff --git a/scp/js/thread.js b/scp/js/thread.js
index 434c8d05d9ac57360ce742abaa11e5c6e1cd8cc5..c590323161e6a3be7ac8d31ffa732802344fceda 100644
--- a/scp/js/thread.js
+++ b/scp/js/thread.js
@@ -65,7 +65,7 @@ var thread = {
               .text(' ' + __('Show Images'))
               .click(function(ev) {
                 imgs.each(function(i, img) {
-                  this.showExternalImage(img);
+                  thread.showExternalImage(img);
                   $(img).removeClass('non-local-image')
                     // Remove placeholder sizing
                     .css({'display':'inline-block'})