[smuxi/stable] Frontend-GNOME: fix crash when rendering broken image files in MessageTextView



commit 4f217cf84f76e6ac127cdf3ba88e4fa846215422
Author: Mirco Bauer <meebey meebey net>
Date:   Sat Jun 24 13:33:27 2017 +0800

    Frontend-GNOME: fix crash when rendering broken image files in MessageTextView
    
    Usually this should never happen, but if the downloaded emoji from the [emoji
    provider][emojione] is corrupted then the frontend crashes like this:
    
        Exception Type:
        GLib.GException
    
        Exception Message:
        Fatal error reading PNG image file: Not a PNG file
    
        Exception StackTrace:
          at Gdk.Pixbuf..ctor (System.String filename, System.Int32 width, System.Int32 height) [0x00069] in 
<f4cb27d9fe5c4db497df3d8a2c1f9dcb>:0
          at Smuxi.Frontend.Gnome.MessageTextView.AddEmoji (Gtk.TextBuffer buffer, Gtk.TextIter& iter, 
Smuxi.Engine.ImageMessagePartModel imgPart, System.String shortName) [0x00112] in 
/tmp/buildd/smuxi-1.0.6/src/Frontend-GNOME/Views/MessageTextView.cs:328
          at Smuxi.Frontend.Gnome.MessageTextView.AddMessage (Smuxi.Engine.MessageModel msg, System.Boolean 
addLinebreak, System.Boolean showTimestamps) [0x0051c] in 
/tmp/buildd/smuxi-1.0.6/src/Frontend-GNOME/Views/MessageTextView.cs:545
          at Smuxi.Frontend.Gnome.MessageTextView.AddMessage (Smuxi.Engine.MessageModel msg, System.Boolean 
addLinebreak) [0x0000a] in /tmp/buildd/smuxi-1.0.6/src/Frontend-GNOME/Views/MessageTextView.cs:374
          at Smuxi.Frontend.Gnome.MessageTextView.AddMessage (Smuxi.Engine.MessageModel msg) [0x00001] in 
/tmp/buildd/smuxi-1.0.6/src/Frontend-GNOME/Views/MessageTextView.cs:369
          at Smuxi.Frontend.Gnome.ChatView.AddMessage (Smuxi.Engine.MessageModel msg) [0x0002b] in 
/tmp/buildd/smuxi-1.0.6/src/Frontend-GNOME/Views/Chats/ChatView.cs:634
          at Smuxi.Frontend.Gnome.GroupChatView.AddMessage (Smuxi.Engine.MessageModel msg) [0x00003] in 
/tmp/buildd/smuxi-1.0.6/src/Frontend-GNOME/Views/Chats/GroupChatView.cs:361
          at Smuxi.Frontend.Gnome.GnomeUI._AddMessageToChat (Smuxi.Engine.ChatModel chatModel, 
Smuxi.Engine.MessageModel msg) [0x00036] in /tmp/buildd/smuxi-1.0.6/src/Frontend-GNOME/GnomeUI.cs:87
          at Smuxi.Frontend.Gnome.GnomeUI+<AddMessageToChat>c__AnonStorey0.<>m__0 (System.Object , 
System.EventArgs ) [0x00014] in /tmp/buildd/smuxi-1.0.6/src/Frontend-GNOME/GnomeUI.cs:108
    
    This did happen because my [ISP][netvigator] is doing MiTM and instead of
    returning the image it returns a HTML page saying the bill was not paid. This
    MiTM attack only works because HTTP is used and is a good reminder why the
    Internet needs to move to HTTPS by default for everything to prevent breaking
    web APIs and also doing more evil things than this.
    
     [emojione]: https://www.emojione.com/
     [netvigator]: https://www.netvigator.com/

 src/Frontend-GNOME/Views/MessageTextView.cs |   72 ++++++++++++++++++---------
 1 files changed, 49 insertions(+), 23 deletions(-)
---
diff --git a/src/Frontend-GNOME/Views/MessageTextView.cs b/src/Frontend-GNOME/Views/MessageTextView.cs
index 96db4d8..d765acb 100644
--- a/src/Frontend-GNOME/Views/MessageTextView.cs
+++ b/src/Frontend-GNOME/Views/MessageTextView.cs
@@ -305,15 +305,6 @@ namespace Smuxi.Frontend.Gnome
                 return;
             }
 
-            int width, height;
-            int widthPango, heightPango;
-            int descent;
-            using (var layout = CreatePangoLayout(null)) {
-                layout.GetPixelSize(out width, out height);
-                layout.GetSize(out widthPango, out heightPango);
-                descent = layout.Context.GetMetrics(layout.FontDescription, null).Descent;
-            }
-
             // A mark here serves two pusposes. One is to allow us to apply the
             // tag across the pixbuf. It also lets us know later where to put
             // the pixbuf if we need to load it from the network
@@ -325,13 +316,7 @@ namespace Smuxi.Frontend.Gnome
             if (EmojiCache.TryGetIcon("emojione", emojiName, out emojiPath)) {
                 var emojiFile = new FileInfo(emojiPath);
                 if (emojiFile.Exists && emojiFile.Length > 0) {
-                    var pix = new Gdk.Pixbuf(emojiPath, -1, height);
-                    buffer.InsertPixbuf(ref iter, pix);
-                    var beforeIter = buffer.GetIterAtMark(mark);
-                    var imgTag = new EmojiTag(mark, emojiFile.FullName);
-                    imgTag.Rise = - descent;
-                    _MessageTextTagTable.Add(imgTag);
-                    buffer.ApplyTag(imgTag, beforeIter, iter);
+                    AddEmoji(buffer, ref iter, imgPart, shortName, mark, emojiPath);
                 } else {
                     AddAlternativeText(buffer, ref iter, imgPart);
                 }
@@ -343,13 +328,8 @@ namespace Smuxi.Frontend.Gnome
             EmojiCache.BeginDownloadFile("emojione", emojiName, emojiUrl,
                 (path) => {
                     GLib.Idle.Add(delegate {
-                        var afterIter = buffer.GetIterAtMark(mark);
-                        buffer.InsertPixbuf(ref afterIter, new Gdk.Pixbuf(path, -1, height));
-                        var beforeIter = buffer.GetIterAtMark(mark);
-                        var emojiTag = new EmojiTag(mark, path);
-                        _MessageTextTagTable.Add(emojiTag);
-                        emojiTag.Rise = - descent;
-                        buffer.ApplyTag(emojiTag, beforeIter, afterIter);
+                        var markIter = buffer.GetIterAtMark(mark);
+                        AddEmoji(buffer, ref markIter, imgPart, shortName, mark, path);
                         return false;
                     });
                 },
@@ -364,6 +344,52 @@ namespace Smuxi.Frontend.Gnome
             );
         }
 
+        void AddEmoji(Gtk.TextBuffer buffer, ref Gtk.TextIter iter,
+                      ImageMessagePartModel imgPart, string shortName,
+                      Gtk.TextMark emojiMark , string imagePath)
+        {
+            int width, height;
+            int widthPango, heightPango;
+            int descent;
+            using (var layout = CreatePangoLayout(null)) {
+                layout.GetPixelSize(out width, out height);
+                layout.GetSize(out widthPango, out heightPango);
+                descent = layout.Context.GetMetrics(layout.FontDescription, null).Descent;
+            }
+
+            Gdk.Pixbuf emojiPixBuf;
+            try {
+                emojiPixBuf = new Gdk.Pixbuf(imagePath, -1, height);
+            } catch (Exception ex) {
+#if LOG4NET
+                _Logger.ErrorFormat(
+                    "AddEmoji(): error loading " +
+                    "image file: '{0}' " +
+                    "emoji: '{1}' into Gdk.Pixbuf(), " +
+                    "Exception: {2}",
+                    imagePath, shortName, ex
+                );
+#endif
+
+                // delete the broken image file, maybe after the
+                // next download this will be a valid image
+                File.Delete(imagePath);
+
+                // show alternative text as fallback instead
+                buffer.DeleteMark(emojiMark);
+                AddAlternativeText(buffer, ref iter, imgPart);
+                return;
+            }
+
+            buffer.InsertPixbuf(ref iter, emojiPixBuf);
+            var beforeIter = buffer.GetIterAtMark(emojiMark);
+            var emojiTag = new EmojiTag(emojiMark, imagePath) {
+                Rise =  - descent
+            };
+            _MessageTextTagTable.Add(emojiTag);
+            buffer.ApplyTag(emojiTag, beforeIter, iter);
+        }
+
         public void AddMessage(MessageModel msg)
         {
             AddMessage(msg, true);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]