[gwibber/f14/master] 2.91.92

Tom Callaway spot at fedoraproject.org
Fri Mar 25 20:14:29 UTC 2011


commit 38fc4d2560cb4008216402157e2854c585492331
Author: Tom "spot" Callaway <tcallawa at redhat.com>
Date:   Fri Mar 25 16:15:57 2011 -0400

    2.91.92

 gwibber-2.91.92-NetworkManager-0.9.patch    |   62 +++
 gwibber-2.91.92-facebook-likes-count.patch  |   12 +
 gwibber-2.91.92-fix-desktop.patch           |   32 ++
 gwibber-2.91.92-gowalla-icons.patch         |  Bin 0 -> 8093 bytes
 gwibber-2.91.92-gowalla-kitchen.patch       |   78 +++
 gwibber-2.91.92-gowalla.patch               |  442 +++++++++++++++
 gwibber-2.91.92-handle-x00-in-content.patch |   14 +
 gwibber-2.91.92-kitchen-unicode.patch       |  771 +++++++++++++++++++++++++++
 gwibber-2.91.92-minimize-chars.patch        |  111 ++++
 gwibber-2.91.92-no-libproxy.patch           |   19 +
 gwibber-2.91.92-undefined-mark.patch        |   12 +
 gwibber.spec                                |   66 ++-
 sources                                     |    2 +-
 13 files changed, 1602 insertions(+), 19 deletions(-)
---
diff --git a/gwibber-2.91.92-NetworkManager-0.9.patch b/gwibber-2.91.92-NetworkManager-0.9.patch
new file mode 100644
index 0000000..3da8014
--- /dev/null
+++ b/gwibber-2.91.92-NetworkManager-0.9.patch
@@ -0,0 +1,62 @@
+diff -up gwibber-2.91.92/gwibber/microblog/dispatcher.py.nm09 gwibber-2.91.92/gwibber/microblog/dispatcher.py
+--- gwibber-2.91.92/gwibber/microblog/dispatcher.py.nm09	2011-03-25 15:01:06.291113010 -0400
++++ gwibber-2.91.92/gwibber/microblog/dispatcher.py	2011-03-25 15:03:10.625112926 -0400
+@@ -766,14 +766,10 @@ class ConnectionMonitor(dbus.service.Obj
+   def on_connection_changed(self, state):
+     log.logger.debug("Network state changed, new state is %d", state)
+     """
+-    NM_STATE_UNKNOWN = 0
+-    NM_STATE_ASLEEP = 1
+-    NM_STATE_CONNECTING = 2
+-    NM_STATE_CONNECTED = 3
+-    NM_STATE_DISCONNECTED = 4
++    See util/const.py for states.
+     """
+ 
+-    if state == NM_STATE_CONNECTED or state == NM_STATE_UNKNOWN:
++    if state in NM_CONNECTED_STATES or state == NM_STATE_UNKNOWN:
+       log.logger.info("Network state changed to Online")
+       self.ConnectionOnline()
+     else:
+@@ -789,7 +785,7 @@ class ConnectionMonitor(dbus.service.Obj
+   @dbus.service.method("com.Gwibber.Connection")
+   def isConnected(self):
+     try:
+-      if self.nm.state() == NM_STATE_CONNECTED:
++      if self.nm.state() in NM_CONNECTED_STATES:
+         return True
+       return False
+     except:
+diff -up gwibber-2.91.92/gwibber/microblog/util/const.py.nm09 gwibber-2.91.92/gwibber/microblog/util/const.py
+--- gwibber-2.91.92/gwibber/microblog/util/const.py.nm09	2011-03-25 15:03:24.729113003 -0400
++++ gwibber-2.91.92/gwibber/microblog/util/const.py	2011-03-25 15:04:08.148112931 -0400
+@@ -75,11 +75,24 @@ NM_DBUS_SERVICE = "org.freedesktop.Netwo
+ NM_DBUS_OBJECT_PATH = "/org/freedesktop/NetworkManager"
+ NM_DBUS_INTERFACE = "org.freedesktop.NetworkManager"
+ NM_STATE_UNKNOWN = 0
+-NM_STATE_ASLEEP = 1
+-NM_STATE_CONNECTING = 2
+-NM_STATE_CONNECTED = 3
+-NM_STATE_DISCONNECTED = 4
+-
++NM_STATE_ASLEEP_OLD = 1
++NM_STATE_CONNECTING_OLD = 2
++NM_STATE_CONNECTED_OLD = 3
++NM_STATE_DISCONNECTED_OLD = 4
++NM_STATE_ASLEEP = 10,
++NM_STATE_DISCONNECTED = 20,
++NM_STATE_DISCONNECTING = 30,
++NM_STATE_CONNECTING = 40,
++NM_STATE_CONNECTED_LOCAL = 50,
++NM_STATE_CONNECTED_SITE = 60,
++NM_STATE_CONNECTED_GLOBAL = 70
++
++NM_CONNECTED_STATES = (
++  NM_STATE_CONNECTED_OLD,
++  NM_STATE_CONNECTED_LOCAL,
++  NM_STATE_CONNECTED_SITE,
++  NM_STATE_CONNECTED_GLOBAL
++)
+ 
+ GWIBBER_OPERATIONS = """
+ {
diff --git a/gwibber-2.91.92-facebook-likes-count.patch b/gwibber-2.91.92-facebook-likes-count.patch
new file mode 100644
index 0000000..2250805
--- /dev/null
+++ b/gwibber-2.91.92-facebook-likes-count.patch
@@ -0,0 +1,12 @@
+diff -up gwibber-2.91.92/gwibber/microblog/plugins/facebook/__init__.py.likes-count gwibber-2.91.92/gwibber/microblog/plugins/facebook/__init__.py
+--- gwibber-2.91.92/gwibber/microblog/plugins/facebook/__init__.py.likes-count	2011-03-25 15:10:10.315113010 -0400
++++ gwibber-2.91.92/gwibber/microblog/plugins/facebook/__init__.py	2011-03-25 15:10:20.369113034 -0400
+@@ -172,7 +172,7 @@ class Client:
+ 
+     if data.has_key("likes"):
+       m["likes"] = {}
+-      m["likes"]["count"] = data["likes"]
++      m["likes"]["count"] = data["likes"]["count"]
+ 
+     if data.get("comments", 0):
+       m["comments"] = []
diff --git a/gwibber-2.91.92-fix-desktop.patch b/gwibber-2.91.92-fix-desktop.patch
new file mode 100644
index 0000000..a804297
--- /dev/null
+++ b/gwibber-2.91.92-fix-desktop.patch
@@ -0,0 +1,32 @@
+diff -up gwibber-2.91.92/gwibber.desktop.in.BAD gwibber-2.91.92/gwibber.desktop.in
+--- gwibber-2.91.92/gwibber.desktop.in.BAD	2011-03-25 13:12:01.133113140 -0400
++++ gwibber-2.91.92/gwibber.desktop.in	2011-03-25 13:12:09.499112646 -0400
+@@ -10,28 +10,3 @@ Categories=GTK;GNOME;Network;
+ X-GNOME-Gettext-Domain=gwibber
+ X-Ayatana-Desktop-Shortcuts=Gwibber;Refresh;Accounts;Preferences;Quit
+ X-Ayatana-Appmenu-Show-Stubs=False
+-
+-[Gwibber Shortcut Group]
+-_Name=Gwibber
+-Exec=gwibber
+-TargetEnvironment=Unity
+-
+-[Refresh Shortcut Group]
+-_Name=Refresh
+-Exec=gwibber-client -r
+-TargetEnvironment=Unity
+-
+-[Accounts Shortcut Group]
+-_Name=Accounts
+-Exec=gwibber-accounts
+-TargetEnvironment=Unity
+-
+-[Preferences Shortcut Group]
+-_Name=Preferences
+-Exec=gwibber-preferences
+-TargetEnvironment=Unity
+-
+-[Quit Shortcut Group]
+-_Name=Quit
+-Exec=gwibber-client -q
+-TargetEnvironment=Unity
diff --git a/gwibber-2.91.92-gowalla-icons.patch b/gwibber-2.91.92-gowalla-icons.patch
new file mode 100644
index 0000000..ea9e0b9
Binary files /dev/null and b/gwibber-2.91.92-gowalla-icons.patch differ
diff --git a/gwibber-2.91.92-gowalla-kitchen.patch b/gwibber-2.91.92-gowalla-kitchen.patch
new file mode 100644
index 0000000..3a4519c
--- /dev/null
+++ b/gwibber-2.91.92-gowalla-kitchen.patch
@@ -0,0 +1,78 @@
+diff -up gwibber-2.91.92/gwibber/microblog/plugins/gowalla/__init__.py.gowalla-kitchen gwibber-2.91.92/gwibber/microblog/plugins/gowalla/__init__.py
+--- gwibber-2.91.92/gwibber/microblog/plugins/gowalla/__init__.py.gowalla-kitchen	2011-03-25 13:43:11.123113004 -0400
++++ gwibber-2.91.92/gwibber/microblog/plugins/gowalla/__init__.py	2011-03-25 13:47:05.879113003 -0400
+@@ -26,6 +26,7 @@ from gwibber.microblog import network, u
+ from gwibber.microblog.util import log, resources
+ import json, htmllib, re
+ from gettext import lgettext as _
++from kitchen.text.converters import to_unicode
+ log.logger.name = "Gowalla"
+ 
+ PROTOCOL_INFO = {
+@@ -60,46 +61,46 @@ class Client:
+   def _message(self, data):
+ 
+     m = {}; 
+-    m["mid"] = str(data["user"]["first_name"]) + str(data["user"]["last_name"])
+-    m["service"] = "gowalla"
++    m["mid"] = to_unicode(str(data["user"]["first_name"]) + str(data["user"]["last_name"]))
++    m["service"] = u"gowalla"
+     m["account"] = self.account["id"]
+     m["time"] = util.parsetime(data["created_at"])
+ 
+-    messagetext = ""
+-    text = ""
++    messagetext = u""
++    text = u""
+     if data.has_key("spot"):
+         if data.has_key("message"):
+             messagetext += data["message"] + "<br/><br/>"
+             text += data["message"] + "\n"
+-        m["url"] = "http://gowalla.com%s" % data["spot"]["url"]
+-        img = "<table><tr><td><img src='%s'/></td><td>" % data["spot"]["image_url"]
+-        messagetext += img + "Checked in at <a href='" + m["url"] + "'>" + data["spot"]["name"] + "</a>"
+-        text += "Checked in at " + data["spot"]["name"]
++        m["url"] = to_unicode("http://gowalla.com%s" % data["spot"]["url"])
++        img = to_unicode("<table><tr><td><img src='%s'/></td><td>" % data["spot"]["image_url"])
++        messagetext += img + "Checked in at <a href='" + m["url"] + "'>" + to_unicode(data["spot"]["name"]) + "</a>"
++        text += u"Checked in at " + to_unicode(data["spot"]["name"])
+     else:
+         if data.has_key("message"):
+-            messagetext += data["message"] + "<br/><br/>"
+-            text += data["message"] + "\n"
++            messagetext += to_unicode(data["message"]) + u"<br/><br/>"
++            text += to_unicode(data["message"]) + u"\n"
+         else:
+-            text= "Checked in off the grid"
+-            messagetext= "<table><tr><td><img src='http://gowalla.com/favicon.ico'/></td><td>Checked in off the grid"
++            text= u"Checked in off the grid"
++            messagetext= u"<table><tr><td><img src='http://gowalla.com/favicon.ico'/></td><td>Checked in off the grid"
+ 
+     m["text"] = text
+-    m["content"] = messagetext + "</td></tr></table>"
+-    m["html"] = messagetext + "</td></tr></table>"
++    m["content"] = messagetext + u"</td></tr></table>"
++    m["html"] = messagetext + u"</td></tr></table>"
+ 
+     m["sender"] = {}
+-    m["sender"]["image"] = data["user"]["image_url"]
+-    m["sender"]["url"] = "http://gowalla.com%s" % data["user"]["url"]
+-    fullname = ""
++    m["sender"]["image"] = to_unicode(data["user"]["image_url"])
++    m["sender"]["url"] = to_unicode("http://gowalla.com%s" % data["user"]["url"])
++    fullname = u""
+     if data["user"].has_key("first_name"):
+-        fullname += data["user"]["first_name"] + " "
++        fullname += to_unicode(data["user"]["first_name"]) + u" "
+     if data["user"].has_key("last_name"):
+-        fullname += data["user"]["last_name"]
++        fullname += to_unicode(data["user"]["last_name"])
+ 
+     m["sender"]["name"] = fullname
+     m["sender"]["nick"] = fullname
+ 
+-    m["source"] = "<a href='http://gowalla.com/'>Gowalla</a>"
++    m["source"] = u"<a href='http://gowalla.com/'>Gowalla</a>"
+ 
+     return m
+ 
diff --git a/gwibber-2.91.92-gowalla.patch b/gwibber-2.91.92-gowalla.patch
new file mode 100644
index 0000000..f2e039e
--- /dev/null
+++ b/gwibber-2.91.92-gowalla.patch
@@ -0,0 +1,442 @@
+diff -up gwibber-2.91.92/gwibber/microblog/plugins/gowalla/gtk/gowalla/__init__.py.gowalla gwibber-2.91.92/gwibber/microblog/plugins/gowalla/gtk/gowalla/__init__.py
+--- gwibber-2.91.92/gwibber/microblog/plugins/gowalla/gtk/gowalla/__init__.py.gowalla	2011-03-25 13:37:54.077113013 -0400
++++ gwibber-2.91.92/gwibber/microblog/plugins/gowalla/gtk/gowalla/__init__.py	2011-03-25 13:18:40.175113003 -0400
+@@ -0,0 +1,43 @@
++#
++# Gowalla support for Gwibber
++#
++# Derived from Foursquare support (foursquare.py)
++# That code is (C) 2010 Ken VanDine <ken.vandine at canonical.com>
++# and is available under GPLv2 only.
++#
++# Copyright 2011, Tom "spot" Callaway <tcallawa at redhat.com>
++#
++# This program is free software: you can redistribute it and/or modify
++# it under the terms of the GNU General Public License version 2 or later 
++# as published by the Free Software Foundation.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++import gtk
++from gtk import Builder
++from gwibber.microblog.util import resources
++
++class AccountWidget(gtk.VBox):
++  """AccountWidget: A widget that provides a user interface for configuring Gowalla accounts in Gwibber
++  """
++  
++  def __init__(self, account=None, dialog=None):
++    """Creates the account pane for configuring Gowalla accounts"""
++    gtk.VBox.__init__( self, False, 20 )
++    self.ui = gtk.Builder()
++    self.ui.set_translation_domain ("gwibber")
++    self.ui.add_from_file (resources.get_ui_asset("gwibber-accounts-gowalla.ui"))
++    self.ui.connect_signals(self)
++    self.vbox_settings = self.ui.get_object("vbox_settings")
++    self.pack_start(self.vbox_settings, False, False)
++    self.show_all()
++    if dialog.ui:
++      dialog.ui.get_object("vbox_create").show()
++
++    
+diff -up gwibber-2.91.92/gwibber/microblog/plugins/gowalla/gtk/__init__.py.gowalla gwibber-2.91.92/gwibber/microblog/plugins/gowalla/gtk/__init__.py
+diff -up gwibber-2.91.92/gwibber/microblog/plugins/gowalla/__init__.py.gowalla gwibber-2.91.92/gwibber/microblog/plugins/gowalla/__init__.py
+--- gwibber-2.91.92/gwibber/microblog/plugins/gowalla/__init__.py.gowalla	2011-03-25 13:37:40.775113004 -0400
++++ gwibber-2.91.92/gwibber/microblog/plugins/gowalla/__init__.py	2011-03-25 13:32:04.759113008 -0400
+@@ -0,0 +1,134 @@
++#
++# Gowalla support for Gwibber
++#
++# Derived from Foursquare support (foursquare/__init__.py)
++#
++# Copyright 2011, Tom "spot" Callaway <tcallawa at redhat.com>
++#
++# Permission to use, copy, modify, and distribute this software and its
++# documentation for any purpose and without fee is hereby granted,
++# provided that the above copyright notice appear in all copies and that
++# both that copyright notice and this permission notice appear in
++# supporting documentation.
++#
++# THE AUTHOR PROVIDES THIS SOFTWARE ''AS IS'' AND ANY EXPRESSED OR
++# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
++# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
++# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
++# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
++# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++
++from gwibber.microblog import network, util
++from gwibber.microblog.util import log, resources
++import json, htmllib, re
++from gettext import lgettext as _
++log.logger.name = "Gowalla"
++
++PROTOCOL_INFO = {
++  "name": "Gowalla",
++  "version": "1.0",
++  
++  "config": [
++    "private:password",
++    "receive_enabled",
++    "username",
++    "color",
++  ],
++
++  "authtype": "none",
++  "color": "#f7911f",
++
++  "features": [
++    "receive",
++  ],
++
++  "default_streams": [
++    "receive",
++  ],
++}
++
++URL_PREFIX = "https://api.gowalla.com/"
++
++class Client:
++  def __init__(self, acct):
++    self.account = acct
++
++  def _message(self, data):
++
++    m = {}; 
++    m["mid"] = str(data["user"]["first_name"]) + str(data["user"]["last_name"])
++    m["service"] = "gowalla"
++    m["account"] = self.account["id"]
++    m["time"] = util.parsetime(data["created_at"])
++
++    messagetext = ""
++    text = ""
++    if data.has_key("spot"):
++        if data.has_key("message"):
++            messagetext += data["message"] + "<br/><br/>"
++            text += data["message"] + "\n"
++        m["url"] = "http://gowalla.com%s" % data["spot"]["url"]
++        img = "<table><tr><td><img src='%s'/></td><td>" % data["spot"]["image_url"]
++        messagetext += img + "Checked in at <a href='" + m["url"] + "'>" + data["spot"]["name"] + "</a>"
++        text += "Checked in at " + data["spot"]["name"]
++    else:
++        if data.has_key("message"):
++            messagetext += data["message"] + "<br/><br/>"
++            text += data["message"] + "\n"
++        else:
++            text= "Checked in off the grid"
++            messagetext= "<table><tr><td><img src='http://gowalla.com/favicon.ico'/></td><td>Checked in off the grid"
++
++    m["text"] = text
++    m["content"] = messagetext + "</td></tr></table>"
++    m["html"] = messagetext + "</td></tr></table>"
++
++    m["sender"] = {}
++    m["sender"]["image"] = data["user"]["image_url"]
++    m["sender"]["url"] = "http://gowalla.com%s" % data["user"]["url"]
++    fullname = ""
++    if data["user"].has_key("first_name"):
++        fullname += data["user"]["first_name"] + " "
++    if data["user"].has_key("last_name"):
++        fullname += data["user"]["last_name"]
++
++    m["sender"]["name"] = fullname
++    m["sender"]["nick"] = fullname
++
++    m["source"] = "<a href='http://gowalla.com/'>Gowalla</a>"
++
++    return m
++
++  def _check_error(self, data):
++    if isinstance(data, dict) and "activity" in data:
++      return True
++    else:
++      log.logger.error("Gowalla error %s", data)
++      return False
++
++  def _get(self, path, parse="message", post=False, single=False, **args):
++    url = "/".join((URL_PREFIX, path))
++
++    data = network.Download(url, util.compact(args) or None, post,
++        self.account["username"], self.account["password"]).get_json()
++
++    resources.dump(self.account["service"], self.account["id"], data)
++
++    if not self._check_error(data):
++      return []
++
++    checkins = data["activity"]
++    if single: return [getattr(self, "_%s" % parse)(checkins)]
++    if parse: return [getattr(self, "_%s" % parse)(m) for m in checkins]
++    else: return []
++
++  def __call__(self, opname, **args):
++    return getattr(self, opname)(**args)
++
++  def receive(self):
++    return self._get("users/%s/activity/friends" % self.account["username"])
++
+diff -up gwibber-2.91.92/gwibber/microblog/plugins/gowalla/ui/gwibber-accounts-gowalla.ui.gowalla gwibber-2.91.92/gwibber/microblog/plugins/gowalla/ui/gwibber-accounts-gowalla.ui
+--- gwibber-2.91.92/gwibber/microblog/plugins/gowalla/ui/gwibber-accounts-gowalla.ui.gowalla	2011-03-25 13:37:59.317113004 -0400
++++ gwibber-2.91.92/gwibber/microblog/plugins/gowalla/ui/gwibber-accounts-gowalla.ui	2011-03-25 13:21:50.015113004 -0400
+@@ -0,0 +1,201 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<interface>
++  <requires lib="gtk+" version="2.16"/>
++  <!-- interface-naming-policy toplevel-contextual -->
++  <object class="GtkVBox" id="vbox_settings">
++    <property name="visible">True</property>
++    <property name="spacing">6</property>
++    <child>
++      <object class="GtkTable" id="table_common_settings">
++        <property name="visible">True</property>
++        <property name="n_rows">3</property>
++        <property name="n_columns">3</property>
++        <property name="column_spacing">12</property>
++        <property name="row_spacing">6</property>
++        <child>
++          <object class="GtkEntry" id="password">
++            <property name="visible">True</property>
++            <property name="can_focus">True</property>
++            <property name="visibility">False</property>
++            <property name="invisible_char">●</property>
++          </object>
++          <packing>
++            <property name="left_attach">1</property>
++            <property name="right_attach">3</property>
++            <property name="top_attach">2</property>
++            <property name="bottom_attach">3</property>
++            <property name="y_options"></property>
++          </packing>
++        </child>
++        <child>
++          <object class="GtkEntry" id="username">
++            <property name="visible">True</property>
++            <property name="can_focus">True</property>
++            <property name="invisible_char">●</property>
++          </object>
++          <packing>
++            <property name="left_attach">1</property>
++            <property name="right_attach">3</property>
++            <property name="y_options"></property>
++          </packing>
++        </child>
++        <child>
++          <object class="GtkLabel" id="label_username">
++            <property name="visible">True</property>
++            <property name="xalign">0</property>
++            <property name="label" translatable="yes">Login I_D:</property>
++            <property name="use_underline">True</property>
++            <property name="mnemonic_widget">username</property>
++          </object>
++          <packing>
++            <property name="x_options">GTK_FILL</property>
++            <property name="y_options"></property>
++          </packing>
++        </child>
++        <child>
++          <object class="GtkLabel" id="label_password">
++            <property name="visible">True</property>
++            <property name="xalign">0</property>
++            <property name="label" translatable="yes">Pass_word:</property>
++            <property name="use_underline">True</property>
++            <property name="justify">right</property>
++            <property name="mnemonic_widget">password</property>
++          </object>
++          <packing>
++            <property name="top_attach">2</property>
++            <property name="bottom_attach">3</property>
++            <property name="x_options">GTK_FILL</property>
++            <property name="y_options"></property>
++          </packing>
++        </child>
++        <child>
++          <object class="GtkVBox" id="vbox1">
++            <property name="visible">True</property>
++            <child>
++              <object class="GtkLabel" id="label_username_example">
++                <property name="visible">True</property>
++                <property name="xalign">0</property>
++                <property name="xpad">3</property>
++                <property name="label" translatable="yes">&lt;span size="small"&gt;&lt;b&gt;Example:&lt;/b&gt; username at email.com&lt;/span&gt;</property>
++                <property name="use_markup">True</property>
++              </object>
++              <packing>
++                <property name="fill">False</property>
++                <property name="position">0</property>
++              </packing>
++            </child>
++          </object>
++          <packing>
++            <property name="left_attach">1</property>
++            <property name="right_attach">2</property>
++            <property name="top_attach">1</property>
++            <property name="bottom_attach">2</property>
++          </packing>
++        </child>
++        <child>
++          <placeholder/>
++        </child>
++        <child>
++          <placeholder/>
++        </child>
++      </object>
++      <packing>
++        <property name="expand">False</property>
++        <property name="fill">False</property>
++        <property name="position">0</property>
++      </packing>
++    </child>
++    <child>
++      <object class="GtkHSeparator" id="hseparator1">
++        <property name="visible">True</property>
++      </object>
++      <packing>
++        <property name="expand">False</property>
++        <property name="position">1</property>
++      </packing>
++    </child>
++    <child>
++      <object class="GtkVBox" id="vbox_advanced">
++        <property name="visible">True</property>
++        <property name="spacing">6</property>
++        <child>
++          <object class="GtkLabel" id="label3">
++            <property name="visible">True</property>
++            <property name="xalign">0</property>
++            <property name="label" translatable="yes">Account Settings:</property>
++            <attributes>
++              <attribute name="weight" value="bold"/>
++            </attributes>
++          </object>
++          <packing>
++            <property name="position">0</property>
++          </packing>
++        </child>
++        <child>
++          <object class="GtkTable" id="table_advanced_settings">
++            <property name="visible">True</property>
++            <property name="n_columns">3</property>
++            <property name="column_spacing">12</property>
++            <property name="row_spacing">6</property>
++            <child>
++              <object class="GtkCheckButton" id="receive_enabled">
++                <property name="label" translatable="yes">_Receive Messages</property>
++                <property name="visible">True</property>
++                <property name="can_focus">True</property>
++                <property name="receives_default">False</property>
++                <property name="tooltip_text" translatable="yes">Include this account when downloading messages</property>
++                <property name="use_underline">True</property>
++                <property name="active">True</property>
++                <property name="draw_indicator">True</property>
++              </object>
++              <packing>
++                <property name="right_attach">3</property>
++                <property name="x_options">GTK_FILL</property>
++                <property name="y_options"></property>
++              </packing>
++            </child>
++          </object>
++          <packing>
++            <property name="position">1</property>
++          </packing>
++        </child>
++        <child>
++          <object class="GtkHBox" id="hbox1">
++            <property name="visible">True</property>
++            <property name="homogeneous">True</property>
++            <child>
++              <object class="GtkLabel" id="label4">
++                <property name="visible">True</property>
++                <property name="tooltip_text" translatable="yes">Color used to help distinguish accounts</property>
++                <property name="xalign">0</property>
++                <property name="label" translatable="yes">Account Color:</property>
++              </object>
++              <packing>
++                <property name="position">0</property>
++              </packing>
++            </child>
++            <child>
++              <object class="GtkColorButton" id="color">
++                <property name="visible">True</property>
++                <property name="can_focus">True</property>
++                <property name="receives_default">True</property>
++                <property name="tooltip_text" translatable="yes">Color used to help distinguish accounts</property>
++                <property name="color">#000000000000</property>
++              </object>
++              <packing>
++                <property name="expand">False</property>
++                <property name="position">1</property>
++              </packing>
++            </child>
++          </object>
++          <packing>
++            <property name="position">2</property>
++          </packing>
++        </child>
++      </object>
++      <packing>
++        <property name="position">2</property>
++      </packing>
++    </child>
++  </object>
++</interface>
+diff -up gwibber-2.91.92/MANIFEST.gowalla gwibber-2.91.92/MANIFEST
+--- gwibber-2.91.92/MANIFEST.gowalla	2011-03-25 13:32:58.698113010 -0400
++++ gwibber-2.91.92/MANIFEST	2011-03-25 13:34:28.606113047 -0400
+@@ -83,6 +83,14 @@ gwibber/microblog/plugins/friendfeed/__i
+ gwibber/microblog/plugins/friendfeed/gtk/__init__.py
+ gwibber/microblog/plugins/friendfeed/gtk/friendfeed/__init__.py
+ gwibber/microblog/plugins/friendfeed/ui/gwibber-accounts-friendfeed.ui
++gwibber/microblog/plugins/gowalla/__init__.py
++gwibber/microblog/plugins/gowalla/gtk/__init__.py
++gwibber/microblog/plugins/gowalla/gtk/gowalla/__init__.py
++gwibber/microblog/plugins/gowalla/ui/gwibber-accounts-gowalla.ui
++gwibber/microblog/plugins/gowalla/ui/icons/16x16/gowalla.png
++gwibber/microblog/plugins/gowalla/ui/icons/22x22/gowalla.png
++gwibber/microblog/plugins/gowalla/ui/icons/32x32/gowalla.png
++gwibber/microblog/plugins/gowalla/ui/icons/scalable/gowalla.png
+ gwibber/microblog/plugins/identica/__init__.py
+ gwibber/microblog/plugins/identica/gtk/__init__.py
+ gwibber/microblog/plugins/identica/gtk/identica/__init__.py
+diff -up gwibber-2.91.92/po/POTFILES.in.gowalla gwibber-2.91.92/po/POTFILES.in
+--- gwibber-2.91.92/po/POTFILES.in.gowalla	2011-03-25 13:34:39.204112988 -0400
++++ gwibber-2.91.92/po/POTFILES.in	2011-03-25 13:35:10.815112928 -0400
+@@ -34,6 +34,7 @@ gwibber/util.py
+ [type: gettext/glade] gwibber/microblog/plugins/twitter/ui/gwibber-accounts-twitter.ui
+ [type: gettext/glade] gwibber/microblog/plugins/qaiku/ui/gwibber-accounts-qaiku.ui
+ [type: gettext/glade] gwibber/microblog/plugins/foursquare/ui/gwibber-accounts-foursquare.ui
++[type: gettext/glade] gwibber/microblog/plugins/gowalla/ui/gwibber-accounts-gowalla.ui
+ ui/templates/base.mako
+ ui/templates/targetbar.mako
+ bin/gwibber-poster
+diff -up gwibber-2.91.92/setup.py.gowalla gwibber-2.91.92/setup.py
+--- gwibber-2.91.92/setup.py.gowalla	2011-03-25 13:35:19.692113025 -0400
++++ gwibber-2.91.92/setup.py	2011-03-25 13:36:38.870113063 -0400
+@@ -61,6 +61,14 @@ setup(name="gwibber",
+     ('share/gwibber/plugins/foursquare/ui/icons/22x22', glob("gwibber/microblog/plugins/foursquare/ui/icons/22x22/*.*")),
+     ('share/gwibber/plugins/foursquare/ui/icons/32x32', glob("gwibber/microblog/plugins/foursquare/ui/icons/32x32/*.*")),
+     ('share/gwibber/plugins/foursquare/ui/icons/scalable', glob("gwibber/microblog/plugins/foursquare/ui/icons/scalable/*.*")),
++    ('share/gwibber/plugins/gowalla', glob("gwibber/microblog/plugins/gowalla/*.*")),
++    ('share/gwibber/plugins/gowalla/gtk', glob("gwibber/microblog/plugins/gowalla/gtk/*.*")),
++    ('share/gwibber/plugins/gowalla/gtk/gowalla', glob("gwibber/microblog/plugins/gowalla/gtk/gowalla/*.*")),
++    ('share/gwibber/plugins/gowalla/ui', glob("gwibber/microblog/plugins/gowalla/ui/*.*")),
++    ('share/gwibber/plugins/gowalla/ui/icons/16x16', glob("gwibber/microblog/plugins/gowalla/ui/icons/16x16/*.*")),
++    ('share/gwibber/plugins/gowalla/ui/icons/22x22', glob("gwibber/microblog/plugins/gowalla/ui/icons/22x22/*.*")),
++    ('share/gwibber/plugins/gowalla/ui/icons/32x32', glob("gwibber/microblog/plugins/gowalla/ui/icons/32x32/*.*")),
++    ('share/gwibber/plugins/gowalla/ui/icons/scalable', glob("gwibber/microblog/plugins/gowalla/ui/icons/scalable/*.*")),
+     ('share/gwibber/plugins/buzz', glob("gwibber/microblog/plugins/buzz/*.*")),
+     ('share/gwibber/plugins/buzz/gtk', glob("gwibber/microblog/plugins/buzz/gtk/*.*")),
+     ('share/gwibber/plugins/buzz/gtk/buzz', glob("gwibber/microblog/plugins/buzz/gtk/buzz/*.*")),
+--- gwibber-2.91.92/gwibber/microblog/plugins/gowalla/gtk/__init__.py.gowalla	2011-03-25 14:53:06.734113004 -0400
++++ gwibber-2.91.92/gwibber/microblog/plugins/gowalla/gtk/__init__.py	2011-03-25 14:53:19.607112967 -0400
+@@ -0,0 +1 @@
++ 
diff --git a/gwibber-2.91.92-handle-x00-in-content.patch b/gwibber-2.91.92-handle-x00-in-content.patch
new file mode 100644
index 0000000..4eb05f1
--- /dev/null
+++ b/gwibber-2.91.92-handle-x00-in-content.patch
@@ -0,0 +1,14 @@
+diff -up gwibber-2.91.92/gwibber/gwui.py.x00 gwibber-2.91.92/gwibber/gwui.py
+--- gwibber-2.91.92/gwibber/gwui.py.x00	2011-03-24 16:13:45.000000000 -0400
++++ gwibber-2.91.92/gwibber/gwui.py	2011-03-24 16:15:10.564112992 -0400
+@@ -255,6 +255,10 @@ class WebUi(webkit.WebView):
+     template = Template(template, lookup=TemplateLookup(directories=lookup_paths))
+     content = template.render(theme=util.get_theme_colors(), util=util, resources=resources, _=_, **kwargs)
+ 
++    # Content occasionally ends up with nulls (\x00) which causes a traceback
++    # This works around it by replacing \x00 with a space whenever it is found.
++    content = content.replace('\x00', ' ')
++
+     # Avoid navigation redraw crashes
+     if isinstance(self, Navigation) and not self.get_property("visible"):
+       return content
diff --git a/gwibber-2.91.92-kitchen-unicode.patch b/gwibber-2.91.92-kitchen-unicode.patch
new file mode 100644
index 0000000..27748da
--- /dev/null
+++ b/gwibber-2.91.92-kitchen-unicode.patch
@@ -0,0 +1,771 @@
+diff -up gwibber-2.91.92/gwibber/microblog/brightkite.py.kitchen gwibber-2.91.92/gwibber/microblog/brightkite.py
+--- gwibber-2.91.92/gwibber/microblog/brightkite.py.kitchen	2011-03-13 11:09:42.000000000 -0400
++++ gwibber-2.91.92/gwibber/microblog/brightkite.py	2011-03-25 15:08:55.099113004 -0400
+@@ -8,6 +8,7 @@ SegPhault (Ryan Paul) - 10/19/2008
+ from . import support
+ import urllib2, urllib, base64, re, simplejson
+ from xml.dom import minidom
++from kitchen.text.converters import to_unicode
+ 
+ PROTOCOL_INFO = {
+   "name": "BrightKite",
+@@ -34,62 +35,62 @@ class Message:
+   def __init__(self, client, data):
+     self.client = client
+     self.account = client.account
+-    self.service = client.account["service"]
+-    self.username = client.account["username"]
++    self.service = to_unicode(client.account["service"])
++    self.username = to_unicode(client.account["username"])
+ 
+-    self.sender = data["creator"]["fullname"]
+-    self.sender_nick = data["creator"]["login"]
+-    self.sender_id = data["creator"]["login"]
+-    self.image = data["creator"]["small_avatar_url"]
++    self.sender = to_unicode(data["creator"]["fullname"])
++    self.sender_nick = to_unicode(data["creator"]["login"])
++    self.sender_id = to_unicode(data["creator"]["login"])
++    self.image = to_unicode(data["creator"]["small_avatar_url"])
+     
+     self.time = support.parse_time(data["created_at"])
+-    self.text = data["body"] or ""
+-    self.bgcolor = "message_color"
+-    self.id = data["id"]
++    self.text = to_unicode(data["body"]) or u""
++    self.bgcolor = u"message_color"
++    self.id = to_unicode(data["id"])
+     
+-    self.url = "http://brightkite.com/objects/%s" % data["id"]
+-    self.profile_url = "http://brightkite.com/people/%s" % self.sender_nick
++    self.url = to_unicode("http://brightkite.com/objects/%s" % data["id"])
++    self.profile_url = to_unicode("http://brightkite.com/people/%s" % self.sender_nick)
+     
+-    self.html_string = '<span class="text">%s</span>' % \
++    self.html_string = to_unicode('<span class="text">%s</span>' % \
+       NICK_PARSE.sub('@<a class="inlinenick" href="http://brightkite.com/people/\\1">\\1</a>',
+-        support.linkify(self.text))
++        support.linkify(self.text)))
+     
+     self.is_reply = ("@%s" % self.username) in self.text
+     self.can_thread = data["comments_count"] > 0
+ 
+     # Geolocation
+-    self.location_lon = data["place"]["longitude"]
+-    self.location_lat = data["place"]["latitude"]
+-    self.location_id = data["place"]["id"]
+-    self.location_name = data["place"]["name"]
+-    self.location_fullname = data["place"]["display_location"]
++    self.location_lon = to_unicode(data["place"]["longitude"])
++    self.location_lat = to_unicode(data["place"]["latitude"])
++    self.location_id = to_unicode(data["place"]["id"])
++    self.location_name = to_unicode(data["place"]["name"])
++    self.location_fullname = to_unicode(data["place"]["display_location"])
+     self.geo_position = (self.location_lat, self.location_lon)
+ 
+     if "photo" in data:
+-      self.thumbnails = [{"src": data["photo"], "href": data["photo"]}]
++      self.thumbnails = [{"src": to_unicode(data["photo"]), "href": to_unicode(data["photo"])}]
+ 
+ class Comment:
+   def __init__(self, client, data):
+     self.client = client
+     self.account = client.account
+-    self.service = client.account["service"]
+-    self.username = client.account["username"]
++    self.service = to_unicode(client.account["service"])
++    self.username = to_unicode(client.account["username"])
+ 
+-    self.sender = data["user"]["fullname"]
+-    self.sender_nick = data["user"]["login"]
+-    self.sender_id = data["user"]["login"]
+-    self.image = data["user"]["small_avatar_url"]
++    self.sender = to_unicode(data["user"]["fullname"])
++    self.sender_nick = to_unicode(data["user"]["login"])
++    self.sender_id = to_unicode(data["user"]["login"])
++    self.image = to_unicode(data["user"]["small_avatar_url"])
+     
+     self.time = support.parse_time(data["created_at"])
+-    self.text = data["comment"]
+-    self.bgcolor = "message_color"
++    self.text = to_unicode(data["comment"])
++    self.bgcolor = u"message_color"
+     
+-    self.url = "http://brightkite.com/objects/%s" % data["place_object"]["id"]
+-    self.profile_url = "http://brightkite.com/people/%s" % self.sender_nick
++    self.url = to_unicode("http://brightkite.com/objects/%s" % data["place_object"]["id"])
++    self.profile_url = to_unicode("http://brightkite.com/people/%s" % self.sender_nick)
+     
+-    self.html_string = '<span class="text">%s</span>' % \
++    self.html_string = to_unicode('<span class="text">%s</span>' % \
+       NICK_PARSE.sub('@<a class="inlinenick" href="http://brightkite.com/people/\\1">\\1</a>',
+-        support.linkify(self.text))
++        support.linkify(self.text)))
+     
+     self.is_reply = ("@%s" % self.username) in self.text
+ 
+@@ -97,26 +98,26 @@ class FriendPosition:
+   def __init__(self, client, data):
+     self.client = client
+     self.account = client.account
+-    self.service = client.account["service"]
+-    self.username = client.account["username"]
+-    self.sender = data["fullname"]
+-    self.sender_nick = data["login"]
++    self.service = to_unicode(client.account["service"])
++    self.username = to_unicode(client.account["username"])
++    self.sender = to_unicode(data["fullname"])
++    self.sender_nick = to_unicode(data["login"])
+     self.sender_id = self.sender_nick
+     self.time = support.parse_time(data["last_checked_in"])
+-    self.text = data["place"]["display_location"]
+-    self.image = data["small_avatar_url"]
+-    self.image_small = data["smaller_avatar_url"]
+-    self.bgcolor = "message_color"
+-    self.url = "http://brightkite.com" # TODO
+-    self.profile_url = "http://brightkite.com" # TODO
++    self.text = to_unicode(data["place"]["display_location"])
++    self.image = to_unicode(data["small_avatar_url"])
++    self.image_small = to_unicode(data["smaller_avatar_url"])
++    self.bgcolor = u"message_color"
++    self.url = u"http://brightkite.com" # TODO
++    self.profile_url = u"http://brightkite.com" # TODO
+     self.is_reply = False
+ 
+     # Geolocation
+-    self.location_lon = data["place"]["longitude"]
+-    self.location_lat = data["place"]["latitude"]
+-    self.location_id = data["place"]["id"]
+-    self.location_name = data["place"]["name"]
+-    self.location_fullname = data["place"]["display_location"]
++    self.location_lon = to_unicode(data["place"]["longitude"])
++    self.location_lat = to_unicode(data["place"]["latitude"])
++    self.location_id = to_unicode(data["place"]["id"])
++    self.location_name = to_unicode(data["place"]["name"])
++    self.location_fullname = to_unicode(data["place"]["display_location"])
+ 
+ class Client:
+   def __init__(self, acct):
+diff -up gwibber-2.91.92/gwibber/microblog/dispatcher.py.kitchen gwibber-2.91.92/gwibber/microblog/dispatcher.py
+--- gwibber-2.91.92/gwibber/microblog/dispatcher.py.kitchen	2011-03-22 17:00:03.000000000 -0400
++++ gwibber-2.91.92/gwibber/microblog/dispatcher.py	2011-03-25 15:08:55.099113004 -0400
+@@ -5,6 +5,7 @@ import multiprocessing, threading, trace
+ import gobject, dbus, dbus.service
+ import sqlite3, mx.DateTime, re, uuid
+ import urlshorter, storage, network, util, config
++from kitchen.text.converters import to_unicode
+ from gettext import lgettext as _
+ import signal
+ 
+@@ -59,9 +60,9 @@ def perform_operation((account, opname, 
+       for m in message_data:
+         try: 
+           if isinstance(m, dict) and m.has_key("mid"):
+-            m["id"] = uuid.uuid1().hex
+-            m["operation"] = opname
+-            m["stream"] = stream
++            m["id"] = to_unicode(uuid.uuid1().hex)
++            m["operation"] = to_unicode(opname)
++            m["stream"] = to_unicode(stream)
+             m["transient"] = transient
+             m["rtl"] = util.isRTL(re.sub(text_cleaner, "", m["text"].decode('utf-8')))
+             if m.has_key("type"):
+diff -up gwibber-2.91.92/gwibber/microblog/plugins/buzz/__init__.py.kitchen gwibber-2.91.92/gwibber/microblog/plugins/buzz/__init__.py
+--- gwibber-2.91.92/gwibber/microblog/plugins/buzz/__init__.py.kitchen	2011-03-13 11:09:42.000000000 -0400
++++ gwibber-2.91.92/gwibber/microblog/plugins/buzz/__init__.py	2011-03-25 15:08:55.099113004 -0400
+@@ -2,6 +2,7 @@ from gwibber.microblog import network, u
+ from gwibber.microblog.util import resources
+ import json
+ from oauth import oauth
++from kitchen.text.converters import to_unicode
+ 
+ PROTOCOL_INFO = {
+   "name": "Buzz",
+@@ -43,32 +44,32 @@ class Client:
+ 
+   def _actor(self, user):
+     return {
+-        "name": user["name"],
+-        "nick": user["id"],
+-        "id": user["id"],
+-        "image": user.get("thumbnailUrl", "https://mail.google.com/mail/images/blue_ghost.jpg?sz=45"),
+-        "url": user.get("profileUrl", None),
++        "name": to_unicode(user["name"]),
++        "nick": to_unicode(user["id"]),
++        "id": to_unicode(user["id"]),
++        "image": to_unicode(user.get("thumbnailUrl", "https://mail.google.com/mail/images/blue_ghost.jpg?sz=45")),
++        "url": to_unicode(user.get("profileUrl", None)),
+         "is_me": user["id"] == self.account["user_id"],
+     }
+ 
+   def _message(self, data):
+     m = {
+         "mid": data["id"],
+-        "service": "buzz",
+-        "account": self.account["id"],
++        "service": u"buzz",
++        "account": to_unicode(self.account["id"]),
+         "time": util.parsetime(data["published"]),
+-        "url": data.get("links", {})["alternate"][0].get("href", ""),
+-        "source": data.get("source", {}).get("title", None),
++        "url": to_unicode(data.get("links", {})["alternate"][0].get("href", "")),
++        "source": to_unicode(data.get("source", {}).get("title", None)),
+         "sender": self._actor(data["actor"]),
+     }
+ 
+-    m["text"] = data["object"]["content"]
++    m["text"] = to_unicode(data["object"]["content"])
+ 
+     if data.get("source", {}).get("title", 0) == "Twitter":
+       m["text"] = m["text"].split(">:", 1)[1].strip()
+     
+-    m["html"] = m["text"]
+-    m["content"] = m["text"]
++    m["html"] = to_unicode(m["text"])
++    m["content"] = to_unicode(m["text"])
+ 
+     if data.get("geocode", 0):
+       m["location"] = {
+@@ -77,24 +78,24 @@ class Client:
+       }
+ 
+       if data.get("address", 0):
+-        m["location"]["address"] = data["address"]
++        m["location"]["address"] = to_unicode(data["address"])
+ 
+     m["images"] = []
+     for a in data["object"].get("attachments", []):
+       if a["type"] == "photo":
+         m["images"].append({
+-          "src": a["links"]["preview"][0]["href"],
+-          "url": a["links"]["enclosure"][0]["href"]
++          "src": to_unicode(a["links"]["preview"][0]["href"]),
++          "url": to_unicode(a["links"]["enclosure"][0]["href"])
+         })
+ 
+       if a["type"] == "video":
+         m["images"].append({
+-          "src": a["links"]["preview"][0]["href"],
+-          "url": a["links"]["alternate"][0]["href"],
++          "src": to_unicode(a["links"]["preview"][0]["href"]),
++          "url": to_unicode(a["links"]["alternate"][0]["href"]),
+         })
+ 
+       if a["type"] == "article":
+-        m["content"] += "<p><b><a href=\"%s\">%s</a></b></p>" % (a["links"]["alternate"][0]["href"], a["title"])
++        m["content"] += to_unicode("<p><b><a href=\"%s\">%s</a></b></p>" % (a["links"]["alternate"][0]["href"], a["title"]))
+ 
+     return m
+ 
+diff -up gwibber-2.91.92/gwibber/microblog/plugins/digg/__init__.py.kitchen gwibber-2.91.92/gwibber/microblog/plugins/digg/__init__.py
+--- gwibber-2.91.92/gwibber/microblog/plugins/digg/__init__.py.kitchen	2011-03-13 11:09:42.000000000 -0400
++++ gwibber-2.91.92/gwibber/microblog/plugins/digg/__init__.py	2011-03-25 15:08:55.099113004 -0400
+@@ -1,6 +1,7 @@
+ from gwibber.microblog import network, util
+ from gwibber.microblog.util import resources
+ from gettext import lgettext as _
++from kitchen.text.converters import to_unicode
+ 
+ PROTOCOL_INFO = {
+   "name": "Digg",
+@@ -33,33 +34,33 @@ class Client:
+   def _story(self, data):
+     m = {}; 
+     m["mid"] = str(data["id"])
+-    m["service"] = "digg"
+-    m["account"] = self.account["id"]
++    m["service"] = u"digg"
++    m["account"] = to_unicode(self.account["id"])
+     m["time"] = data["submit_date"]
+ 
+-    m["text"] = data["title"] + "\n" + data["description"]
+-    m["content"] = "<b>%(title)s</b><br />%(description)s" % data
+-    m["html"] = "<b>%(title)s</b><br />%(description)s" % data
++    m["text"] = to_unicode(data["title"]) + u"\n" + to_unicode(data["description"])
++    m["content"] = to_unicode("<b>%(title)s</b><br />%(description)s" % data)
++    m["html"] = to_unicode("<b>%(title)s</b><br />%(description)s" % data)
+     user = data["friends"]["users"][0]
+ 
+     m["sender"] = {}
+-    m["sender"]["nick"] = user["name"]
+-    m["sender"]["id"] = user["name"]
+-    m["sender"]["image"] = user["icon"]
+-    m["sender"]["url"] = "http://digg.com/users/%s" % user["name"]
++    m["sender"]["nick"] = to_unicode(user["name"])
++    m["sender"]["id"] = to_unicode(user["name"])
++    m["sender"]["image"] = to_unicode(user["icon"])
++    m["sender"]["url"] = to_unicode("http://digg.com/users/%s" % user["name"])
+     m["sender"]["is_me"] = user["name"] == self.account["username"]
+-    if user.get("fullname", 0): m["sender"]["name"] = user["fullname"]
++    if user.get("fullname", 0): m["sender"]["name"] = to_unicode(user["fullname"])
+     
+-    m["url"] = data["link"]
++    m["url"] = to_unicode(data["link"])
+     m["likes"] = {"count": data["diggs"]}
+ 
+-    m["html"] = util.linkify(m["text"],
++    m["html"] = to_unicode(util.linkify(m["text"],
+       ((util.PARSE_HASH, '#<a class="hash" href="%s#search?q=\\1">\\1</a>' % URL_PREFIX),
+-      (util.PARSE_NICK, '@<a class="nick" href="%s/\\1">\\1</a>' % URL_PREFIX)))
++      (util.PARSE_NICK, '@<a class="nick" href="%s/\\1">\\1</a>' % URL_PREFIX))))
+ 
+-    m["content"] = util.linkify(m["text"],
++    m["content"] = to_unicode(util.linkify(m["text"],
+       ((util.PARSE_HASH, '#<a class="hash" href="gwibber:/tag?acct=%s&query=\\1">\\1</a>' % m["account"]),
+-      (util.PARSE_NICK, '@<a class="nick" href="gwibber:/user?acct=%s&name=\\1">\\1</a>' % m["account"])))
++      (util.PARSE_NICK, '@<a class="nick" href="gwibber:/user?acct=%s&name=\\1">\\1</a>' % m["account"]))))
+ 
+     return m
+ 
+diff -up gwibber-2.91.92/gwibber/microblog/plugins/facebook/__init__.py.kitchen gwibber-2.91.92/gwibber/microblog/plugins/facebook/__init__.py
+--- gwibber-2.91.92/gwibber/microblog/plugins/facebook/__init__.py.kitchen	2011-03-13 11:09:42.000000000 -0400
++++ gwibber-2.91.92/gwibber/microblog/plugins/facebook/__init__.py	2011-03-25 15:09:03.036113003 -0400
+@@ -6,6 +6,7 @@ import hashlib, mx.DateTime, time
+ from os.path import join, getmtime, exists
+ from gettext import lgettext as _
+ from gwibber.microblog.util.const import *
++from kitchen.text.converters import to_unicode
+ # Try to import * from custom, install custom.py to include packaging 
+ # customizations like distro API keys, etc
+ try:
+@@ -101,37 +102,37 @@ class Client:
+ 
+   def _sender(self, data):
+     sender = {
+-      "name": data["name"],
++      "name": to_unicode(data["name"]),
+       "id": str(data.get("id", '')),
+       "is_me": str(data.get("id", '')) == self.user_id,
+-      "image": URL_PREFIX + data["id"] + "/picture",
+-      "url": "https://www.facebook.com/profile.php?id=" + str(data.get("id", ''))
++      "image": to_unicode(URL_PREFIX) + to_unicode(data["id"]) + u"/picture",
++      "url": u"https://www.facebook.com/profile.php?id=" + to_unicode(str(data.get("id", '')))
+     }
+     return sender
+   
+   def _message(self, data):
+     m = {}
+-    m["mid"] = str(data["id"])
+-    m["service"] = "facebook"
++    m["mid"] = to_unicode(str(data["id"]))
++    m["service"] = u"facebook"
+     m["account"] = self.account["id"]
+ 
+     m["time"] = int(mx.DateTime.DateTimeFrom(str(data.get("updated_time", data["created_time"]))))
+-    m["url"] = "https://facebook.com/" + data["id"].split("_")[0] + "/posts/" + data["id"].split("_")[1]
++    m["url"] = u"https://facebook.com/" + to_unicode(data["id"].split("_")[0]) + u"/posts/" + to_unicode(data["id"].split("_")[1])
+     
+ 
+     if data.get("attribution", 0):
+-      m["source"] = util.strip_urls(data["attribution"]).replace("via ", "")
++      m["source"] = to_unicode(util.strip_urls(data["attribution"]).replace("via ", ""))
+     
+     if data.has_key("message"):
+       m["to_me"] = ("@%s" % self.account["username"]) in data["message"]
+     if data.get("message", "").strip():
+-      m["text"] = data["message"]
+-      m["html"] = util.linkify(data["message"])
+-      m["content"] = m["html"]
++      m["text"] = to_unicode(data["message"])
++      m["html"] = to_unicode(util.linkify(data["message"]))
++      m["content"] = to_unicode(m["html"])
+     else:
+-      m["text"] = ""
+-      m["html"] = ""
+-      m["content"] = ""
++      m["text"] = u""
++      m["html"] = u""
++      m["content"] = u""
+ 
+     m["sender"] = self._sender(data["from"])
+ 
+@@ -178,17 +179,17 @@ class Client:
+       if data["comments"].has_key("data"):
+         for item in data["comments"]["data"]:
+           m["comments"].append({
+-              "text": item["message"],
++              "text": to_unicode(item["message"]),
+               "time": int(mx.DateTime.DateTimeFrom(str(data.get("updated_time", data["created_time"])))),
+               "sender": self._sender(item["from"]),
+             })
+ 
+     if data.get("attachment", 0):
+       if data["attachment"].get("name", 0):
+-        m["content"] += "<p><b>%s</b></p>" % data["attachment"]["name"]
++        m["content"] += to_unicode("<p><b>%s</b></p>" % data["attachment"]["name"])
+ 
+       if data["attachment"].get("description", 0):
+-        m["content"] += "<p>%s</p>" % data["attachment"]["description"]
++        m["content"] += to_unicode("<p>%s</p>" % data["attachment"]["description"])
+ 
+     return m
+ 
+diff -up gwibber-2.91.92/gwibber/microblog/plugins/identica/__init__.py.kitchen gwibber-2.91.92/gwibber/microblog/plugins/identica/__init__.py
+--- gwibber-2.91.92/gwibber/microblog/plugins/identica/__init__.py.kitchen	2011-03-13 11:09:42.000000000 -0400
++++ gwibber-2.91.92/gwibber/microblog/plugins/identica/__init__.py	2011-03-25 15:08:55.100113004 -0400
+@@ -4,6 +4,7 @@ import gnomekeyring
+ from oauth import oauth
+ from gwibber.microblog.util import log, resources
+ from gettext import lgettext as _
++from kitchen.text.converters import to_unicode
+ log.logger.name = "Identi.ca"
+ 
+ PROTOCOL_INFO = {
+@@ -58,27 +59,27 @@ class Client:
+     m = {}
+     try:
+       m["mid"] = str(data["id"])
+-      m["service"] = "identica"
++      m["service"] = u"identica"
+       m["account"] = self.account["id"]
+       m["time"] = util.parsetime(data["created_at"])
+-      m["source"] = data.get("source", False)
+-      m["text"] = data["text"]
++      m["source"] = to_unicode(data.get("source", False))
++      m["text"] = to_unicode(data["text"])
+       m["to_me"] = ("@%s" % self.account["username"]) in data["text"]
+ 
+-      m["html"] = util.linkify(m["text"],
++      m["html"] = to_unicode(util.linkify(m["text"],
+         ((util.PARSE_HASH, '#<a class="hash" href="%s#search?q=\\1">\\1</a>' % self.url_prefix),
+-        (util.PARSE_NICK, '@<a class="nick" href="%s/\\1">\\1</a>' % self.url_prefix)))
++        (util.PARSE_NICK, '@<a class="nick" href="%s/\\1">\\1</a>' % self.url_prefix))))
+ 
+-      m["content"] = util.linkify(m["text"],
++      m["content"] = to_unicode(util.linkify(m["text"],
+         ((util.PARSE_HASH, '#<a class="hash" href="gwibber:/tag?acct=%s&query=\\1">\\1</a>' % m["account"]),
+-        (util.PARSE_NICK, '@<a class="nick" href="gwibber:/user?acct=%s&name=\\1">\\1</a>' % m["account"])))
++        (util.PARSE_NICK, '@<a class="nick" href="gwibber:/user?acct=%s&name=\\1">\\1</a>' % m["account"]))))
+ 
+       images = []
+       if data.get("attachments", 0):
+         for a in data["attachments"]:
+           mime = a.get("mimetype", "")
+           if mime and mime.startswith("image") and a.get("url", 0):
+-            images.append({"src": a["url"], "url": a["url"]})
++            images.append({"src": to_unicode(a["url"]), "url": to_unicode(a["url"])})
+ 
+       images.extend(util.imgpreview(m["text"]))
+   
+@@ -96,33 +97,33 @@ class Client:
+       if data["in_reply_to_status_id"]:
+         m["reply"] = {}
+         m["reply"]["id"] = data["in_reply_to_status_id"]
+-        m["reply"]["nick"] = data["in_reply_to_screen_name"]
+-        m["reply"]["url"] = "/".join((self.url_prefix, "notice", str(m["reply"]["id"])))
++        m["reply"]["nick"] = to_unicode(data["in_reply_to_screen_name"])
++        m["reply"]["url"] = to_unicode("/".join((self.url_prefix, "notice", str(m["reply"]["id"]))))
+ 
+     user = data.get("user", data.get("sender", 0))
+     
+     m["sender"] = {}
+-    m["sender"]["name"] = user["name"]
+-    m["sender"]["nick"] = user["screen_name"]
++    m["sender"]["name"] = to_unicode(user["name"])
++    m["sender"]["nick"] = to_unicode(user["screen_name"])
+     m["sender"]["id"] = user["id"]
+-    m["sender"]["location"] = user["location"]
++    m["sender"]["location"] = to_unicode(user["location"])
+     m["sender"]["followers"] = user["followers_count"]
+-    m["sender"]["image"] = user["profile_image_url"]
+-    m["sender"]["url"] = "/".join((self.url_prefix, m["sender"]["nick"]))
++    m["sender"]["image"] = to_unicode(user["profile_image_url"])
++    m["sender"]["url"] = to_unicode("/".join((self.url_prefix, m["sender"]["nick"])))
+     m["sender"]["is_me"] = m["sender"]["nick"] == self.account["username"]
+-    m["url"] = "/".join((self.url_prefix, "notice", m["mid"]))
++    m["url"] = to_unicode("/".join((self.url_prefix, "notice", m["mid"])))
+     return m
+ 
+   def _private(self, data):
+     m = self._message(data)
+     m["private"] = True
+     m["recipient"] = {}
+-    m["recipient"]["name"] = data["recipient"]["name"]
+-    m["recipient"]["nick"] = data["recipient"]["screen_name"]
++    m["recipient"]["name"] = to_unicode(data["recipient"]["name"])
++    m["recipient"]["nick"] = to_unicode(data["recipient"]["screen_name"])
+     m["recipient"]["id"] = data["recipient"]["id"]
+-    m["recipient"]["image"] = data["recipient"]["profile_image_url"]
+-    m["recipient"]["location"] = data["recipient"]["location"]
+-    m["recipient"]["url"] = "/".join((self.url_prefix, m["recipient"]["nick"]))
++    m["recipient"]["image"] = to_unicode(data["recipient"]["profile_image_url"])
++    m["recipient"]["location"] = to_unicode(data["recipient"]["location"])
++    m["recipient"]["url"] = to_unicode("/".join((self.url_prefix, m["recipient"]["nick"])))
+     m["recipient"]["is_me"] = m["recipient"]["nick"].lower() == self.account["username"].lower()
+     m["to_me"] = m["recipient"]["is_me"]
+     return m
+@@ -133,14 +134,14 @@ class Client:
+     if data["to_user_id"]:
+       m["reply"] = {}
+       m["reply"]["id"] = data["to_user_id"]
+-      m["reply"]["nick"] = data["to_user"]
++      m["reply"]["nick"] = to_unicode(data["to_user"])
+ 
+     m["sender"] = {}
+-    m["sender"]["nick"] = data["from_user"]
++    m["sender"]["nick"] = to_unicode(data["from_user"])
+     m["sender"]["id"] = data["from_user_id"]
+-    m["sender"]["image"] = data["profile_image_url"]
+-    m["sender"]["url"] = "/".join((self.url_prefix, m["sender"]["nick"]))
+-    m["url"] = "/".join((self.url_prefix, "notice", str(m["mid"])))
++    m["sender"]["image"] = to_unicode(data["profile_image_url"])
++    m["sender"]["url"] = to_unicode("/".join((self.url_prefix, m["sender"]["nick"])))
++    m["url"] = to_unicode("/".join((self.url_prefix, "notice", str(m["mid"]))))
+     return m
+ 
+   def _get(self, path, parse="message", post=False, single=False, **args):
+diff -up gwibber-2.91.92/gwibber/microblog/plugins/statusnet/__init__.py.kitchen gwibber-2.91.92/gwibber/microblog/plugins/statusnet/__init__.py
+--- gwibber-2.91.92/gwibber/microblog/plugins/statusnet/__init__.py.kitchen	2011-03-13 11:09:42.000000000 -0400
++++ gwibber-2.91.92/gwibber/microblog/plugins/statusnet/__init__.py	2011-03-25 15:08:55.100113004 -0400
+@@ -4,6 +4,7 @@ import gnomekeyring
+ from oauth import oauth
+ from gwibber.microblog.util import log, resources
+ from gettext import lgettext as _
++from kitchen.text.converters import to_unicode
+ log.logger.name = "StatusNet"
+ 
+ PROTOCOL_INFO = {
+@@ -64,27 +65,27 @@ class Client:
+     m = {}
+     try:
+       m["mid"] = str(data["id"])
+-      m["service"] = "statusnet"
++      m["service"] = u"statusnet"
+       m["account"] = self.account["id"]
+       m["time"] = util.parsetime(data["created_at"])
+-      m["source"] = data.get("source", False)
+-      m["text"] = data["text"]
++      m["source"] = to_unicode(data.get("source", False))
++      m["text"] = to_unicode(data["text"])
+       m["to_me"] = ("@%s" % self.account["username"]) in data["text"]
+ 
+-      m["html"] = util.linkify(m["text"],
++      m["html"] = to_unicode(util.linkify(m["text"],
+         ((util.PARSE_HASH, '#<a class="hash" href="%s#search?q=\\1">\\1</a>' % self.account["url_prefix"]),
+-        (util.PARSE_NICK, '@<a class="nick" href="%s/\\1">\\1</a>' % self.account["url_prefix"])))
++        (util.PARSE_NICK, '@<a class="nick" href="%s/\\1">\\1</a>' % self.account["url_prefix"]))))
+ 
+-      m["content"] = util.linkify(m["text"],
++      m["content"] = to_unicode(util.linkify(m["text"],
+         ((util.PARSE_HASH, '#<a class="hash" href="gwibber:/tag?acct=%s&query=\\1">\\1</a>' % m["account"]),
+-        (util.PARSE_NICK, '@<a class="nick" href="gwibber:/user?acct=%s&name=\\1">\\1</a>' % m["account"])))
++        (util.PARSE_NICK, '@<a class="nick" href="gwibber:/user?acct=%s&name=\\1">\\1</a>' % m["account"]))))
+ 
+       images = []
+       if data.get("attachments", 0):
+         for a in data["attachments"]:
+           mime = a.get("mimetype", "")
+           if mime and mime.startswith("image") and a.get("url", 0):
+-            images.append({"src": a["url"], "url": a["url"]})
++            images.append({"src": to_unicode(a["url"]), "url": to_unicode(a["url"])})
+ 
+       images.extend(util.imgpreview(m["text"]))
+   
+@@ -102,33 +103,33 @@ class Client:
+       if data["in_reply_to_status_id"]:
+         m["reply"] = {}
+         m["reply"]["id"] = data["in_reply_to_status_id"]
+-        m["reply"]["nick"] = data["in_reply_to_screen_name"]
+-        m["reply"]["url"] = "/".join((self.account["url_prefix"], "notice", str(m["reply"]["id"])))
++        m["reply"]["nick"] = to_unicode(data["in_reply_to_screen_name"])
++        m["reply"]["url"] = to_unicode("/".join((self.account["url_prefix"], "notice", str(m["reply"]["id"]))))
+ 
+     user = data.get("user", data.get("sender", 0))
+     
+     m["sender"] = {}
+-    m["sender"]["name"] = user["name"]
+-    m["sender"]["nick"] = user["screen_name"]
++    m["sender"]["name"] = to_unicode(user["name"])
++    m["sender"]["nick"] = to_unicode(user["screen_name"])
+     m["sender"]["id"] = user["id"]
+-    m["sender"]["location"] = user["location"]
++    m["sender"]["location"] = to_unicode(user["location"])
+     m["sender"]["followers"] = user["followers_count"]
+-    m["sender"]["image"] = user["profile_image_url"]
+-    m["sender"]["url"] = "/".join((self.account["url_prefix"], m["sender"]["nick"]))
++    m["sender"]["image"] = to_unicode(user["profile_image_url"])
++    m["sender"]["url"] = to_unicode("/".join((self.account["url_prefix"], m["sender"]["nick"])))
+     m["sender"]["is_me"] = m["sender"]["nick"] == self.account["username"]
+-    m["url"] = "/".join((self.account["url_prefix"], "notice", m["mid"]))
++    m["url"] = to_unicode("/".join((self.account["url_prefix"], "notice", m["mid"])))
+     return m
+ 
+   def _private(self, data):
+     m = self._message(data)
+     m["private"] = True
+     m["recipient"] = {}
+-    m["recipient"]["name"] = data["recipient"]["name"]
+-    m["recipient"]["nick"] = data["recipient"]["screen_name"]
++    m["recipient"]["name"] = to_unicode(data["recipient"]["name"])
++    m["recipient"]["nick"] = to_unicode(data["recipient"]["screen_name"])
+     m["recipient"]["id"] = data["recipient"]["id"]
+-    m["recipient"]["image"] = data["recipient"]["profile_image_url"]
+-    m["recipient"]["location"] = data["recipient"]["location"]
+-    m["recipient"]["url"] = "/".join((self.account["url_prefix"], m["recipient"]["nick"]))
++    m["recipient"]["image"] = to_unicode(data["recipient"]["profile_image_url"])
++    m["recipient"]["location"] = to_unicode(data["recipient"]["location"])
++    m["recipient"]["url"] = to_unicode("/".join((self.account["url_prefix"], m["recipient"]["nick"])))
+     m["recipient"]["is_me"] = m["recipient"]["nick"].lower() == self.account["username"].lower()
+     m["to_me"] = m["recipient"]["is_me"]
+     return m
+@@ -142,11 +143,11 @@ class Client:
+       m["reply"]["nick"] = data["to_user"]
+ 
+     m["sender"] = {}
+-    m["sender"]["nick"] = data["from_user"]
++    m["sender"]["nick"] = to_unicode(data["from_user"])
+     m["sender"]["id"] = data["from_user_id"]
+-    m["sender"]["image"] = data["profile_image_url"]
+-    m["sender"]["url"] = "/".join((self.account["url_prefix"], m["sender"]["nick"]))
+-    m["url"] = "/".join((self.account["url_prefix"], "notice", str(m["mid"])))
++    m["sender"]["image"] = to_unicode(data["profile_image_url"])
++    m["sender"]["url"] = to_unicode("/".join((self.account["url_prefix"], m["sender"]["nick"])))
++    m["url"] = to_unicode("/".join((self.account["url_prefix"], "notice", str(m["mid"]))))
+     return m
+ 
+   def _get(self, path, parse="message", post=False, single=False, **args):
+diff -up gwibber-2.91.92/gwibber/microblog/plugins/twitter/__init__.py.kitchen gwibber-2.91.92/gwibber/microblog/plugins/twitter/__init__.py
+--- gwibber-2.91.92/gwibber/microblog/plugins/twitter/__init__.py.kitchen	2011-03-22 12:15:23.000000000 -0400
++++ gwibber-2.91.92/gwibber/microblog/plugins/twitter/__init__.py	2011-03-25 15:08:55.101113004 -0400
+@@ -5,6 +5,7 @@ import gnomekeyring
+ from oauth import oauth
+ from gwibber.microblog.util import log, resources
+ from gettext import lgettext as _
++from kitchen.text.converters import to_unicode
+ log.logger.name = "Twitter"
+ 
+ PROTOCOL_INFO = {
+@@ -75,19 +76,19 @@ class Client:
+     m = {};
+     try:
+       m["mid"] = str(data["id"])
+-      m["service"] = "twitter"
++      m["service"] = u"twitter"
+       m["account"] = self.account["id"]
+       m["time"] = util.parsetime(data["created_at"])
+-      m["text"] = unescape(data["text"])
++      m["text"] = to_unicode(unescape(data["text"]))
+       m["to_me"] = ("@%s" % self.account["username"]) in data["text"]
+ 
+-      m["html"] = util.linkify(data["text"],
++      m["html"] = to_unicode(util.linkify(data["text"],
+         ((util.PARSE_HASH, '#<a class="hash" href="%s#search?q=\\1">\\1</a>' % URL_PREFIX),
+-        (util.PARSE_NICK, '@<a class="nick" href="%s/\\1">\\1</a>' % URL_PREFIX)), escape=False)
++        (util.PARSE_NICK, '@<a class="nick" href="%s/\\1">\\1</a>' % URL_PREFIX)), escape=False))
+ 
+-      m["content"] = util.linkify(data["text"],
++      m["content"] = to_unicode(util.linkify(data["text"],
+         ((util.PARSE_HASH, '#<a class="hash" href="gwibber:/tag?acct=%s&query=\\1">\\1</a>' % m["account"]),
+-        (util.PARSE_NICK, '@<a class="nick" href="gwibber:/user?acct=%s&name=\\1">\\1</a>' % m["account"])), escape=False)
++        (util.PARSE_NICK, '@<a class="nick" href="gwibber:/user?acct=%s&name=\\1">\\1</a>' % m["account"])), escape=False))
+ 
+       images = util.imgpreview(m["text"])
+       if images:
+@@ -100,13 +101,13 @@ class Client:
+ 
+   def _user(self, user):
+     return {
+-        "name": user["name"],
+-        "nick": user["screen_name"],
++        "name": to_unicode(user["name"]),
++        "nick": to_unicode(user["screen_name"]),
+         "id": user["id"],
+-        "location": user["location"],
++        "location": to_unicode(user["location"]),
+         "followers": user.get("followers", None),
+-        "image": user["profile_image_url"],
+-        "url": "/".join((URL_PREFIX, user["screen_name"])),
++        "image": to_unicode(user["profile_image_url"]),
++        "url": to_unicode("/".join((URL_PREFIX, user["screen_name"]))),
+         "is_me": user["screen_name"] == self.account["username"],
+     }
+     
+@@ -121,14 +122,14 @@ class Client:
+       if data["in_reply_to_status_id"]:
+         m["reply"] = {}
+         m["reply"]["id"] = data["in_reply_to_status_id"]
+-        m["reply"]["nick"] = data["in_reply_to_screen_name"]
++        m["reply"]["nick"] = to_unicode(data["in_reply_to_screen_name"])
+         if m["reply"]["id"] and m["reply"]["nick"]:
+-          m["reply"]["url"] = "/".join((URL_PREFIX, m["reply"]["nick"], "statuses", str(m["reply"]["id"])))
++          m["reply"]["url"] = to_unicode("/".join((URL_PREFIX, m["reply"]["nick"], "statuses", str(m["reply"]["id"]))))
+         else:
+           m["reply"]["url"] = None
+ 
+     m["sender"] = self._user(data["user"] if "user" in data else data["sender"])
+-    m["url"] = "/".join((m["sender"]["url"], "statuses", str(m["mid"])))
++    m["url"] = to_unicode("/".join((m["sender"]["url"], "statuses", str(m["mid"]))))
+ 
+     return m
+ 
+@@ -137,12 +138,12 @@ class Client:
+     m["private"] = True
+ 
+     m["recipient"] = {}
+-    m["recipient"]["name"] = data["recipient"]["name"]
+-    m["recipient"]["nick"] = data["recipient"]["screen_name"]
++    m["recipient"]["name"] = to_unicode(data["recipient"]["name"])
++    m["recipient"]["nick"] = to_unicode(data["recipient"]["screen_name"])
+     m["recipient"]["id"] = data["recipient"]["id"]
+-    m["recipient"]["image"] = data["recipient"]["profile_image_url"]
+-    m["recipient"]["location"] = data["recipient"]["location"]
+-    m["recipient"]["url"] = "/".join((URL_PREFIX, m["recipient"]["nick"]))
++    m["recipient"]["image"] = to_unicode(data["recipient"]["profile_image_url"])
++    m["recipient"]["location"] = to_unicode(data["recipient"]["location"])
++    m["recipient"]["url"] = to_unicode("/".join((URL_PREFIX, m["recipient"]["nick"])))
+     m["recipient"]["is_me"] = m["recipient"]["nick"] == self.account["username"]
+     m["to_me"] = m["recipient"]["is_me"]
+ 
+@@ -154,37 +155,37 @@ class Client:
+     if data["to_user_id"]:
+       m["reply"] = {}
+       m["reply"]["id"] = data["to_user_id"]
+-      m["reply"]["nick"] = data["to_user"]
++      m["reply"]["nick"] = to_unicode(data["to_user"])
+ 
+     m["sender"] = {}
+-    m["sender"]["nick"] = data["from_user"]
++    m["sender"]["nick"] = to_unicode(data["from_user"])
+     m["sender"]["id"] = data["from_user_id"]
+-    m["sender"]["image"] = data["profile_image_url"]
+-    m["sender"]["url"] = "/".join((URL_PREFIX, m["sender"]["nick"]))
++    m["sender"]["image"] = to_unicode(data["profile_image_url"])
++    m["sender"]["url"] = to_unicode("/".join((URL_PREFIX, m["sender"]["nick"])))
+     m["sender"]["is_me"] = m["sender"]["nick"] == self.account["username"]
+-    m["url"] = "/".join((m["sender"]["url"], "statuses", str(m["mid"])))
++    m["url"] = to_unicode("/".join((m["sender"]["url"], "statuses", str(m["mid"]))))
+     return m
+ 
+   def _list(self, data):
+     return {
+         "mid": data["id"],
+-        "service": "twitter",
++        "service": u"twitter",
+         "account": self.account["id"],
+         "time": 0,
+-        "text": data["description"],
+-        "html": data["description"],
+-        "content": data["description"],
+-        "url": "/".join((URL_PREFIX, data["uri"])),
+-        "sender": self._user(data["user"]),
+-        "name": data["name"],
+-        "nick": data["slug"],
++        "text": to_unicode(data["description"]),
++        "html": to_unicode(data["description"]),
++        "content": to_unicode(data["description"]),
++        "url": to_unicode("/".join((URL_PREFIX, data["uri"]))),
++        "sender": to_unicode(self._user(data["user"])),
++        "name": to_unicode(data["name"]),
++        "nick": to_unicode(data["slug"]),
+         "key": data["slug"],
+-        "full": data["full_name"],
+-        "uri": data["uri"],
++        "full": to_unicode(data["full_name"]),
++        "uri": to_unicode(data["uri"]),
+         "mode": data["mode"],
+         "members": data["member_count"],
+         "followers": data["subscriber_count"],
+-        "kind": "list",
++        "kind": u"list",
+     }
+ 
+   def _get(self, path, parse="message", post=False, single=False, **args):
diff --git a/gwibber-2.91.92-minimize-chars.patch b/gwibber-2.91.92-minimize-chars.patch
new file mode 100644
index 0000000..8247371
--- /dev/null
+++ b/gwibber-2.91.92-minimize-chars.patch
@@ -0,0 +1,111 @@
+diff -up gwibber-2.91.92/gwibber/gwui.py.minimize gwibber-2.91.92/gwibber/gwui.py
+--- gwibber-2.91.92/gwibber/gwui.py.minimize	2011-03-24 16:17:30.569113002 -0400
++++ gwibber-2.91.92/gwibber/gwui.py	2011-03-24 16:18:32.829112921 -0400
+@@ -1,4 +1,5 @@
+-
++# -*- coding: utf-8 -*-
++#
+ import os, json, urlparse, util
+ import subprocess
+ import gtk, gobject, pango, webkit, time, gconf
+@@ -1053,6 +1054,14 @@ class InputTextView(gtk.TextView):
+       except:
+         pass
+ 
++    # Replace these characters with shorter ones
++    # First field: search for string if this character was entered
++    # Second field: string to search for
++    # Third field: replace with this string
++    self.replacements = [(".", "...", "…"), ("-", "--", "—")]
++    # Keep replacements from triggering themselves
++    self.__replace_lock = False
++
+   def get_text(self):
+     buf = self.get_buffer()
+     return buf.get_text(*buf.get_bounds()).strip()
+@@ -1061,8 +1070,11 @@ class InputTextView(gtk.TextView):
+     return len(unicode(self.get_text(), "utf-8"))
+ 
+   def on_add_text(self, buf, iter, text, tlen):
++    if not text:
++      return
++
+     if self.model.settings["shorten_urls"]:
+-      if text and text.startswith("http") and not " " in text \
++      if text.startswith("http") and not " " in text \
+           and len(text) > 30:
+ 
+         buf = self.get_buffer()
+@@ -1090,6 +1102,26 @@ class InputTextView(gtk.TextView):
+         self.shortener.Shorten(text,
+             reply_handler=add_shortened,
+             error_handler=error_shortened)
++    if self.model.settings["minimize_chars"] and not self.__replace_lock:
++      for entry in self.replacements:
++        if entry[0] in text:
++          buf = self.get_buffer()
++          buf.stop_emission("insert-text")
++          try:
++            self.__replace_lock = True
++            buf.insert(iter, text)
++          finally:
++            self.__replace_lock = False
++
++          # Search the whole buffer in case someone pastes something with the
++          # replacement string as a subset
++          search_iter = buf.get_start_iter()
++          match = search_iter.forward_search(entry[1], 0)
++          while match:
++            buf.delete(match[0], match[1])
++            buf.insert(match[0], entry[2])
++            search_iter = buf.get_start_iter()
++            match = search_iter.forward_search(entry[1], 0)
+ 
+   def set_overlay_text(self, text):
+     if not hasattr(self, 'pango_overlay'):
+diff -up gwibber-2.91.92/gwibber/microblog/util/const.py.minimize gwibber-2.91.92/gwibber/microblog/util/const.py
+--- gwibber-2.91.92/gwibber/microblog/util/const.py.minimize	2011-03-22 12:15:23.000000000 -0400
++++ gwibber-2.91.92/gwibber/microblog/util/const.py	2011-03-24 16:17:30.586113002 -0400
+@@ -38,6 +38,7 @@ DEFAULT_SETTINGS = {
+   "presence_check": True,
+   "show_fullname": True,
+   "shorten_urls": True,
++  "minimize_chars": False,
+   "urlshorter": "is.gd",
+   "reply_append_colon": True,
+   "retweet_style": "recycle",
+diff -up gwibber-2.91.92/gwibber/preferences.py.minimize gwibber-2.91.92/gwibber/preferences.py
+--- gwibber-2.91.92/gwibber/preferences.py.minimize	2011-03-13 11:09:42.000000000 -0400
++++ gwibber-2.91.92/gwibber/preferences.py	2011-03-24 16:17:30.587113002 -0400
+@@ -69,6 +69,7 @@ class GwibberPreferences(object):
+       "no_notifications",
+       "show_fullname",
+       "shorten_urls",
++      "minimize_chars",
+       "reply_append_colon",
+       "global_retweet",
+       "interval",
+diff -up gwibber-2.91.92/ui/gwibber-preferences-dialog.ui.minimize gwibber-2.91.92/ui/gwibber-preferences-dialog.ui
+--- gwibber-2.91.92/ui/gwibber-preferences-dialog.ui.minimize	2011-03-13 11:09:42.000000000 -0400
++++ gwibber-2.91.92/ui/gwibber-preferences-dialog.ui	2011-03-24 16:17:30.587113002 -0400
+@@ -396,6 +396,20 @@
+                             <property name="n_rows">3</property>
+                             <property name="homogeneous">True</property>
+                             <child>
++                              <object class="GtkCheckButton" id="minimize_chars">
++                                <property name="label" translatable="yes">Automatically replace common strings with unicode equivalents to minimize characters (e.g. ... replaced with …)</property>
++                                <property name="visible">True</property>
++                                <property name="can_focus">True</property>
++                                <property name="receives_default">False</property>
++                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
++                                <property name="draw_indicator">True</property>
++                              </object>
++                              <packing>
++                                <property name="top_attach">3</property>
++                                <property name="bottom_attach">4</property>
++                              </packing>
++       	       	       	    </child>
++                            <child>
+                               <object class="GtkCheckButton" id="reply_append_colon">
+                                 <property name="label" translatable="yes">Append colon to username when replying</property>
+                                 <property name="visible">True</property>
diff --git a/gwibber-2.91.92-no-libproxy.patch b/gwibber-2.91.92-no-libproxy.patch
new file mode 100644
index 0000000..d26c8d8
--- /dev/null
+++ b/gwibber-2.91.92-no-libproxy.patch
@@ -0,0 +1,19 @@
+diff -up gwibber-2.91.92/gwibber/microblog/network.py.no-libproxy gwibber-2.91.92/gwibber/microblog/network.py
+--- gwibber-2.91.92/gwibber/microblog/network.py.no-libproxy	2011-03-13 11:09:42.000000000 -0400
++++ gwibber-2.91.92/gwibber/microblog/network.py	2011-03-24 16:12:09.278112938 -0400
+@@ -3,10 +3,11 @@
+ import urllib, pycurl, json, StringIO
+ from util import log
+ 
+-try:
+-  import libproxy
+-except:
+-  libproxy = None
++# try:
++#   import libproxy
++# except:
++#   libproxy = None
++libproxy = None
+ 
+ # Completely disable libproxy support for now, it causes crashes on amd64
+ libproxy = None
diff --git a/gwibber-2.91.92-undefined-mark.patch b/gwibber-2.91.92-undefined-mark.patch
new file mode 100644
index 0000000..8ebdf5a
--- /dev/null
+++ b/gwibber-2.91.92-undefined-mark.patch
@@ -0,0 +1,12 @@
+diff -up gwibber-2.91.92/gwibber/gwui.py.BAD gwibber-2.91.92/gwibber/gwui.py
+--- gwibber-2.91.92/gwibber/gwui.py.BAD	2011-03-25 15:27:09.077112944 -0400
++++ gwibber-2.91.92/gwibber/gwui.py	2011-03-25 15:27:19.810113006 -0400
+@@ -1088,7 +1088,7 @@ class InputTextView(gtk.TextView):
+             buf.insert(iter_start, shortened_url)
+         def error_shortened(dbus_exc):
+             "Internal shortening-url-died function: a closure"
+-            iter = buf.get_iter_at_mark(mark)
++            iter = buf.get_iter_at_mark(mark_start)
+             buf.insert(iter, text) # shortening failed
+ 
+         # set a mark at iter, so that the callback knows where to insert
diff --git a/gwibber.spec b/gwibber.spec
index cb7adcc..3a343fb 100644
--- a/gwibber.spec
+++ b/gwibber.spec
@@ -1,11 +1,10 @@
  %{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
 
-%global basever 2.33.0
 %global bzr_rev 894
 
 Name:           gwibber
-Version:        %{basever}
-Release:        12.%{bzr_rev}bzr%{?dist}
+Version:        2.91.92
+Release:        1%{?dist}
 Epoch:          1
 Summary:        An open source microblogging client for GNOME developed with Python and GTK
 Group:          Applications/Internet
@@ -15,8 +14,8 @@ URL:            https://launchpad.net/gwibber
 # The source for this package can be pulled from upstream's vcs.  Use the
 # following command to generate the tarball:
 #   bzr export -r %{bzr_rev} gwibber-%{bzr_rev}bzr.tar.gz lp:gwibber
-# Source0:        http://launchpad.net/gwibber/trunk/%{basever}/+download/gwibber-%{version}.tar.gz
-Source0:	gwibber-%{bzr_rev}bzr.tar.gz
+# Source0:        %{name}-%{bzr_rev}bzr.tar.gz
+Source0:        http://launchpad.net/gwibber/trunk/%{version}/+download/%{name}-%{version}.tar.gz
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
 # Fix situation where pango_overlay can be undefined
@@ -25,29 +24,25 @@ Patch1:		gwibber-865bzr-undefined.patch
 
 # Disable libproxy support
 # It doesn't work for some unknown reason.
-Patch2:		gwibber-894bzr-no-libproxy.patch
+Patch2:		gwibber-2.91.92-no-libproxy.patch
 
 # Handle \x00 if it shows up in our content string
 # bz 630944 & 620170
 # https://bugs.launchpad.net/gwibber/+bug/647049
-Patch3:        gwibber-867bzr-handle-x00-in-content.patch
+Patch3:		gwibber-2.91.92-handle-x00-in-content.patch
 
 # Oauth bits
 Patch6:		gwibber-832bzr-twitter-oauth.patch
 
-# Gowalla
-Patch7:		gwibber-867bzr-gowalla.patch
-Patch8:		gwibber-867bzr-gowalla-icons.patch
-
 # Minimize characters with unicode equivs
-Patch10:	gwibber-867bzr-minimize-chars.patch
+Patch10:	gwibber-2.91.92-minimize-chars.patch
 
 # Fix iter call to non-existent "mark", use "mark_start"
 # bz635345 bz623754
-Patch11:	gwibber-867bzr-missing-mark.patch
+Patch11:	gwibber-2.91.92-undefined-mark.patch
 
 # Use kitchen to force all strings generated by microblog inputs to unicode
-Patch13:	gwibber-894bzr-kitchen-utf8.patch
+Patch13:	gwibber-2.91.92-kitchen-unicode.patch
 
 # Right click on a stream in the navigation bar to close it.
 Patch14:	gwibber-875bzr-right-click-to-close-stream.patch
@@ -55,6 +50,20 @@ Patch14:	gwibber-875bzr-right-click-to-close-stream.patch
 # Facebook Fedora key
 Patch15:	gwibber-886bzr-facebook-fedora.patch
 
+# Take non-standard sections out of .desktop file
+Patch16:	gwibber-2.91.92-fix-desktop.patch
+
+# Support NetworkManager 0.9 states (and older NM states too)
+Patch17:	gwibber-2.91.92-NetworkManager-0.9.patch
+
+# Properly grab the "likes count" for facebook items
+Patch18:	gwibber-2.91.92-facebook-likes-count.patch
+
+# Gowalla support
+Patch40:	gwibber-2.91.92-gowalla.patch
+Patch41:	gwibber-2.91.92-gowalla-icons.patch
+Patch42:	gwibber-2.91.92-gowalla-kitchen.patch
+
 Requires:	libsoup, python-pycurl
 Requires:	python 
 Requires:	dbus-python >= 0.80.2
@@ -83,22 +92,32 @@ and GTK. It supports Twitter, Jaiku, Identi.ca, Facebook, and Digg.
 
 
 %prep
-%setup -q -n gwibber-%{bzr_rev}bzr
+%setup -q
 
 %patch1 -p1 -b .undefined
 %patch2 -p1 -b .no-libproxy
 %patch3 -p1 -b .x00
 
 %patch6 -p1 -b .oauth
-%patch7 -p1 -b .gowalla
-%patch8 -p1 -b .gowalla-icons
 
 %patch10 -p1 -b .minimize
+%patch11 -p1 -b .missing-mark
 
 %patch13 -p1 -b .kitchen
+
 %patch14 -p1 -b .right-click
 
 %patch15 -p1 -b .fedora
+%patch16 -p1 -b .fix
+
+%patch17 -p1 -b .nm09
+
+%patch18 -p1 -b .likes-count
+
+# Gowalla
+%patch40 -p1 -b .gowalla
+%patch41 -p1 -b .gowalla-icons
+%patch42 -p1 -b .gowalla-kitchen
 
 # sed -i -e '/^#! \?\//, 1d' $(find %{name} | grep "\.py$")
 
@@ -110,6 +129,11 @@ and GTK. It supports Twitter, Jaiku, Identi.ca, Facebook, and Digg.
 rm -rf %{buildroot}
 %{__python} setup.py install --prefix %{_prefix} -O1 --skip-build --root %{buildroot}
 
+# Clean up patchfiles
+for i in `find %{buildroot} |grep "\.gowalla"`; do
+	rm -f $i
+done
+
 ## Reinstall .desktop file
 rm -rf %{buildroot}%{_datadir}/applications
 desktop-file-install --vendor="fedora" --dir=%{buildroot}%{_datadir}/applications build/share/applications/%{name}.desktop
@@ -130,7 +154,7 @@ rm -rf %{buildroot}
 %{python_sitelib}/%{name}-*.egg-info
 %{_bindir}/%{name}
 %{_bindir}/%{name}-accounts
-%{_bindir}/%{name}-error
+%{_bindir}/%{name}-client
 %{_bindir}/%{name}-poster
 %{_bindir}/%{name}-preferences
 %{_bindir}/%{name}-service
@@ -147,6 +171,12 @@ rm -rf %{buildroot}
 %{_datadir}/indicators/messages/applications/gwibber
 
 %changelog
+* Thu Mar 24 2011 Tom Callaway <spot at fedoraproject.org> - 1:2.91.92-1
+- update to 2.91.92
+
+* Wed Feb 09 2011 Fedora Release Engineering <rel-eng at lists.fedoraproject.org> - 1:2.33.0-13.894bzr
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
+
 * Wed Oct 13 2010 Tom "spot" Callaway <tcallawa at redhat.com> - 1:2.33.0-12.894bzr
 - update to 894, improve result parsing, more digg fixes, fedora facebook key
 
diff --git a/sources b/sources
index 5fd2f02..d5cc6e5 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-77f770393c613bb2e7b4ada32222b690  gwibber-894bzr.tar.gz
+bc6725081aa79b654b7c2120e4012eb1  gwibber-2.91.92.tar.gz


More information about the scm-commits mailing list