[meego-commits] 6028: Changes to Trunk:Testing/telepathy-butterfly

Huaxu Wan huaxu.wan at intel.com
Wed Jul 28 03:08:14 UTC 2010


Hi,
I have made the following changes to telepathy-butterfly in project Trunk:Testing. Please review and accept ASAP.

Thank You,
Huaxu Wan

[This message was auto-generated]

---

Request #6028:

  submit:   home:huaxu:branches:Trunk:Testing/telepathy-butterfly(r2)(cleanup) -> Trunk:Testing/telepathy-butterfly


Message:
    Update to 0.5.12

State:   new          2010-07-27T15:01:25 huaxu
Comment: None



changes files:
--------------
--- telepathy-butterfly.changes
+++ telepathy-butterfly.changes
@@ -0,0 +1,3 @@
+* Tue Jul 27 2010 Huaxu Wan <huaxu.wan at linux.intel.com> - 0.5.12
+- Update to 0.5.12
+

old:
----
  telepathy-butterfly-0.5.8.tar.gz

new:
----
  telepathy-butterfly-0.5.12.tar.gz
  telepathy-butterfly.yaml

spec files:
-----------
--- telepathy-butterfly.spec
+++ telepathy-butterfly.spec
@@ -1,26 +1,27 @@
-%{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
+# 
+# Do not Edit! Generated by:
+# spectacle version 0.18
+# 
+# >> macros
+# << macros
 
 Name:           telepathy-butterfly
-Version:        0.5.8
-Release:        1
 Summary:        MSN connection manager for Telepathy
-
+Version:    0.5.12
+Release:    1
 Group:          Applications/Communications
 License:        GPLv2+
+BuildArch:  noarch
 URL:            http://telepathy.freedesktop.org/wiki/
 Source0:        http://telepathy.freedesktop.org/releases/%{name}/%{name}-%{version}.tar.gz
-BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-
-BuildArch:      noarch
-
-BuildRequires:	dbus-devel
-BuildRequires:	python-devel
-BuildRequires:	pkgconfig
-
+Source100:  telepathy-butterfly.yaml
 Requires:	python-telepathy >= 0.15.17
 Requires:	papyon >= 0.4.2
 Requires:	dbus
 Requires:	telepathy-filesystem
+BuildRequires:  pkgconfig(dbus-1)
+BuildRequires:  python-devel
+BuildRequires:  pkgconfig
 
 
 %description
@@ -28,30 +29,48 @@
 and conversations
 
 
+
+
 %prep
-%setup -q
+%setup -q -n %{name}-%{version}
 
+# >> setup
+# << setup
 
 %build
+# >> build pre
 ./configure --prefix=%{_prefix}
-make
+# << build pre
+
 
+make %{?jobs:-j%jobs}
 
+# >> build post
+# << build post
 %install
-rm -rf $RPM_BUILD_ROOT
-make install DESTDIR=$RPM_BUILD_ROOT
+rm -rf %{buildroot}
+# >> install pre
+# << install pre
+%make_install 
+
+# >> install post
+
+
+# << install post
+
+
 
 
-%clean
-rm -rf $RPM_BUILD_ROOT
 
 
 %files
 %defattr(-,root,root,-)
+# >> files
 %doc COPYING AUTHORS NEWS
 %{_libexecdir}/%{name}
 %{_datadir}/dbus-1/services/*.service
 %{_datadir}/telepathy/managers/*.manager
 %{python_sitelib}/*
+# << files
 
 

other changes:
--------------

++++++ telepathy-butterfly-0.5.8.tar.gz -> telepathy-butterfly-0.5.12.tar.gz
--- ChangeLog
+++ ChangeLog
@@ -1,3 +1,634 @@
+commit b571ea726eb5d01180312d871cf71e62e9333796
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-07-09 21:33:50 +0100
+
+    Version 0.5.12.
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 5f9dc818bbee41015f8ea3db744a2145e699d1bb
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-07-09 21:29:46 +0100
+
+    NEWS: updated
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 0f5b5a3d7e7bd773ae7f58f409ccb96e29c491af
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-07-06 13:41:33 +0100
+
+    debug: only print to stderr when BUTTERFLY_DEBUG is set
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit c80212d3bf17463525bc5ea5b895a7ffb5a737c1
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-07-09 18:12:35 +0100
+
+    NEWS: updated
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 1db384e1d6a809721c046fe8aa782fa0bbf502cc
+Merge: bd71b7b d29b988
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-07-09 18:04:24 +0100
+
+    Merge remote branch 'lfrb/file-transfer'
+
+commit bd71b7b0208e39b1d882d404e0da719239148388
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-07-09 18:04:04 +0100
+
+    telepathy-butterfly: depend on papyon 0.4.9
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit a374cf0630d9d33b5174d8495e6b81859430ba4a
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-07-06 18:29:54 +0100
+
+    connection: don't try and get details of an oim if we aren't given the sender
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 36e992a776f7e9b424b244fe4f97209ad64b5ef8
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-07-06 17:14:10 +0100
+
+    connection_manager: ensure the list of connections isn't altered during iteration
+    
+    Otherwise we can get this:
+    
+    File "/usr/lib/python2.6/site-packages/butterfly/util/decorator.py", line 87, in async_function
+      func(*args, **kwargs)
+    File "/usr/libexec/telepathy-butterfly", line 67, in quit
+      manager.quit()
+    File "/usr/lib/python2.6/site-packages/butterfly/connection_manager.py", line 87, in quit
+      for connection in self._connections:
+    RuntimeError: Set changed size during iteration
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 5647aab0a726c2e5600e40ab4d15560bc67e8b42
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-07-06 17:03:06 +0100
+
+    connection: only try and logout if the client isn't already closed
+    
+    Fixes fd.o#28431
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit eef4f9ffcb6fff6cecff03660e2e414e54035d30
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-06-08 15:56:35 +0100
+
+    Start 0.5.12 development.
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 3a496cb5594927a85f0774965b0442a071110973
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-06-08 15:33:04 +0100
+
+    Version 0.5.11.
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 67d700f310a869fc16d7b793ae75727cd24e68ce
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-06-08 15:45:36 +0100
+
+    im/text channels: replace \r\n with \n with incoming messages
+    
+    Thanks to Rodrigo Virote Kassick for the original patch.
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit b1e429d079acc30e0c21d662ab35c29a7a94e14f
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-06-08 13:34:03 +0100
+
+    text channel: make sure the correct type gets returned when getting PendingMessages
+    
+    First of all, PendingMessages is an array, not a dict, so return what
+    is expected. Secondly, simply make sure dbus knows exactly what type a
+    variable is.
+    
+    Fixes: fd.o#28354
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 637318774aff25dbd66227fa4dafdf23b1b65eba
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-06-08 13:27:19 +0100
+
+    text channel: don't always remove pending messages when ListPendingMessages is called
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit d29b9888d93212d82f8d1b8732eff838f32f48ac
+Author: Louis-Francis Ratté-Boulianne <louis-francis.ratte-boulianne at collabora.co.uk>
+Date:   2010-06-03 18:45:58 -0400
+
+    file transfer: add file transfer capabilities to all contacts by default
+
+commit 50d5068fcf4864b0f05b6e19593a85bac5cfc8de
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-28 22:39:18 +0100
+
+    file transfer: steal salut's logic for when to emit TransferredBytesChanged
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 061893c2b5a8ff5e6c15f232f454ed6b86c337cc
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-28 22:13:34 +0100
+
+    file transfer: cleanup after changing status when done so we don't cancel the session
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 3b584de255a938e3f6dcc84e10011eabb23ad05e
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-28 21:41:28 +0100
+
+    file transfer: use a valid and appropriate mime-type as the content type
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 7f9f90e76ad13abe5d8bc830ec610c922103b6f0
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-28 21:37:30 +0100
+
+    file transfer: misc style changes
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit f8349dad2ef6f26a9bc5e827d544de182885757d
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-28 21:34:05 +0100
+
+    file transfer: call ChannelTypeFileTransfer.__init__ first
+    
+    Good practices and all that.
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 01a387df54ad37e511b3be4f01e0a9527d847342
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-28 21:32:22 +0100
+
+    file transfer: move to file_transfer.py to be more consistent
+    
+    We have connection_manager, channel_manager, contact_list, etc.
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 1b47140303096ca6d35e94347e23ae12ca7b19e1
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-28 21:20:47 +0100
+
+    file transfer channel: make the object path prettier
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 985e40ec30e96193e27b06e600e4c622e6c6b9fb
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-03-18 15:50:59 +0000
+
+    file transfer: use mkdtemp to get the temporary directory and clean up afterwards
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit fa2214d7baa9665d54e961a6a0b4e95881d8a64e
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-03-16 01:12:28 +0000
+
+    file transfer: move mandatory property checking to FT channel
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit fbe356d90b46e00cc9b4706c0f058b50d39523e7
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-03-16 01:02:04 +0000
+
+    file transfer: add more debug messages
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit d8eecd3b44c81b8e84a34ef52415c2807af7829b
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-03-16 00:58:56 +0000
+
+    file transfer: set self._receiving in __init__
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit d627ae232b799073ccef909eff16c8a8dcc2cca7
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-03-15 22:22:08 +0000
+
+    file transfer: remove duplicate completed callback
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 153256ae81ecac8dde84aaf0fbc223c1f50ab0da
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-03-15 22:10:16 +0000
+
+    file transfer: remove on_conversation_user_left method
+    
+    We don't even subclass ConversationEventInterface.
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 671f160be02c78ea41e55c931025e2856ec868f8
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-03-15 21:41:29 +0000
+
+    file transfer: raise NotImplemented if called with unknown socket type
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 98eb001f2ebf5ddaa17a7beefb0b851b5ce05d4c
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-03-15 19:16:04 +0000
+
+    channel manager: raise InvalidArgument if Filename or Size is missing
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit af60af50bd837b50a24fb54c4b4ef70a593b958b
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-03-15 19:10:43 +0000
+
+    channel manager: update RCC for file transfer
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 4e00d9b24a5959b9034299e5c88c908927243668
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-03-15 18:58:57 +0000
+
+    file transfer: fix copyright
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 1ec3909612ac5e7d8820b674f7ab2ace53b6e6d8
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-03-14 14:42:57 +0000
+
+    filetransfer: stop implementing the group interface
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit b52d71de881d83efc0ec937fb00b936cb3102c96
+Author: Louis-Francis Ratté-Boulianne <louis-francis.ratte-boulianne at collabora.co.uk>
+Date:   2010-02-05 17:57:53 -0500
+
+    Fixed file-transfer support (NOT async)
+
+commit 95022400567cfed7bdb448a41fea71ed0569753e
+Author: Olivier Le Thanh Duong <olivier at lethanh.be>
+Date:   2010-01-18 21:32:57 +0100
+
+    Add Filename and Size as immutable property of FTChannel
+
+commit b79cc33a55652af655a533167fb86e45c862720a
+Author: Olivier Le Thanh Duong <olivier at lethanh.be>
+Date:   2010-01-13 11:38:03 +0100
+
+    Change FT socket name
+
+commit a30815eedb3aab3165aa128c63b70627da2e7ce9
+Author: Olivier Le Thanh Duong <staz at ks2014638.kimsufi.com>
+Date:   2010-01-02 17:07:06 +0100
+
+    Small fix on ft reception
+
+commit 695e1ad599457206ace19b900f30b13129eb75bc
+Author: Olivier Le Thanh Duong <staz at ks2014638.kimsufi.com>
+Date:   2010-01-02 17:05:43 +0100
+
+    Always create a new channel (rely on tp-python git) for incoming FT
+
+commit 487207db61f7ed8411a0d5691a4fabc04b876dfb
+Author: Louis-Francis Ratté-Boulianne <louis-francis.ratte-boulianne at collabora.co.uk>
+Date:   2009-08-19 18:44:05 -0400
+
+    Added cancelling support
+
+commit 6db9df485e7b5285ed2067cf42d149fa53b8b0b1
+Author: Louis-Francis Ratté-Boulianne <louis-francis.ratte-boulianne at collabora.co.uk>
+Date:   2009-08-19 18:40:41 -0400
+
+    Added close loggin'
+
+commit 307bea8955d2c5b9a88d47109e4a18474eb68085
+Author: Louis-Francis Ratté-Boulianne <louis-francis.ratte-boulianne at collabora.co.uk>
+Date:   2009-08-19 18:16:30 -0400
+
+    Removed on_chunk_received
+
+commit dd6bfe3c021b4f41402eae914ecfa3f6129fc19d
+Author: Louis-Francis Ratte-Boulianne <lfrb at lfrb-desktop.no-domain-set.bellcanada>
+Date:   2009-07-02 10:34:46 -0400
+
+    Initialize threads so GUPnP IGD can be used in papyon
+
+commit 766abfac9de31a5e3daf88f55e17274e2f87f2e8
+Author: Louis-Francis Ratte-Boulianne <lfrb at lfrb-desktop.no-domain-set.bellcanada>
+Date:   2009-06-29 19:06:14 -0400
+
+    Receive data directly from the socket (no buffering)
+
+commit d89e864f915455b4ddfbd94bd409ecabfb3a91ca
+Author: Louis-Francis Ratté-Boulianne <lfrb at lfrb-laptop.(none)>
+Date:   2009-06-28 22:21:34 -0400
+
+    Added a class to hide the streaming behind a file-like interface
+
+commit 21a86252526fde572062b0ac5cc2511528cfd15f
+Author: Louis-Francis Ratte-Boulianne <lfrb at lfrb-desktop.no-domain-set.bellcanada>
+Date:   2009-06-26 18:29:51 -0400
+
+    Added FileTransfer channel
+
+commit acd7e513f549fa4471f0e2e2b3a10c5b5fe51b4a
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-06-02 01:31:59 +0100
+
+    text channel: don't assume message-type is set
+    
+    From the spec:
+    
+       "The type of message; if omitted, Channel_Text_Message_Type_Normal
+       MUST be assumed. MAY be omitted for normal chat messages."
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 9931e2acefb9291cf2e0747283468d984b035f9f
+Author: Olivier Le Thanh Duong <olivier at lethanh.be>
+Date:   2010-05-20 23:15:35 +0200
+
+    Version 0.5.10
+
+commit ff542760f41f05c1e77867646d9892c13d75cfa9
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-13 16:49:45 +0100
+
+    channel: fix typo
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 5cd642d1d96642b009cbb037a9df8acece0210b2
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-04 00:51:46 +0100
+
+    channel: set Initiator props in all channel types, not just media
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit eb4ec881377241f49d757af88e5af1f3e1ee4bca
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-04 00:51:25 +0100
+
+    channel: add ButterflyChannel class to deal with Initiator props
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 7aeed14c60c04589523abebe62a3b152df26e0b7
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-16 23:42:37 +0100
+
+    text channel: append a 'sender-nickname' header on messages with a sender nickname
+    
+    Fixes fd.o#25272
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 23a918dc8f6fa64300a42cbc85223a256ee065e7
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-27 08:21:35 +0100
+
+    handle: stop passing args to object.__new__ if __init__ is overridden
+    
+    Fixes fd.o#27843
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 930549e850a086481ccf2f433778f2d45e359d91
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-27 23:26:30 +0100
+
+    contact list channel: keep the handle being added around for long enough
+    
+    Fixes fd.o#27553
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit d3fe72773f3033ddd407d10dc6c4cab48b87cf93
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-16 12:48:25 +0100
+
+    connection: only switch to HTTP mode if we failed during connection
+    
+    If we're connected fine directly, and then the cable is pulled, we
+    don't want to try and connect immediately back using an HTTP
+    connection, otherwise calling logout will trigger an
+    AssertionError[0].
+    
+    Additionally, we just don't want that to happen anyway because it's
+    annoying. If the cable is pulled we need a NetworkError to appear
+    instead.
+    
+    0. http://launchpadlibrarian.net/44282269/butterfly.txt
+    
+    Fixes fd.o#26147
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 2b5d47702f6c4f694d420aacd09c8925f7530f79
+Merge: b38a35b 0050bfb
+Author: Olivier Le Thanh Duong <olivier at lethanh.be>
+Date:   2010-05-14 00:32:50 +0200
+
+    Merge remote branch 'jonny/27736' into fix27736
+    
+    Merge both Maiku and Jonny patch which each resulted in a different error,
+    taken toegether they work fine
+    
+    Conflicts:
+    	butterfly/capabilities.py
+
+commit b38a35b08eaed2afb15fa878463e36405348d1c1
+Author: Mike Ruprecht <mike.ruprecht at collabora.co.uk>
+Date:   2010-05-13 06:35:30 -0500
+
+    Add a signature for the dbus.Array's in GetContactCapabilities.
+    
+    This prevents me from getting:
+      process 4592: Array or variant type requires that type uint32 be
+      written, but end_dict_entry was written. The overall signature
+      expected here was '' and we are on byte 386 of that signature.
+    And:
+      ERROR:dbus.service:Unable to append <The entire dbus message> to
+      message with signature a{ua{sv}}: <type 'exceptions.ValueError'>:
+      invalid literal for long() with base 10:
+      'org.freedesktop.Telepathy.Channel.Type.Text'
+
+commit 0050bfb806995542306b7db68405d6a418cc0c11
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-05-03 13:52:28 +0100
+
+    capabilities: stop raising KeyError for handles with no contact caps yet
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit cbcbf34abee9d2a2b5ced1d5de5d8fd27884b01d
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-24 12:39:39 +0100
+
+    Start 0.5.10 development.
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit edff4cebf8dba3e55a99f0f9d34231a4c6f05f8a
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-24 12:34:06 +0100
+
+    Version 0.5.9.
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 2108ba96231e0084ccd6398c98642f5fa9aaa828
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-22 19:41:19 +0100
+
+    NEWS: updated
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit a7a69dc16a13d775698093b50baf7fe535b80b35
+Merge: 24f2873 1dccdf7
+Author: Simon McVittie <smcv at debian.org>
+Date:   2010-04-22 13:18:34 +0100
+
+    Merge branch 'avatar-reqs'
+    
+    Reviewed-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 1dccdf7d3576175f922467ffd4bf17f56f0cf9b2
+Author: Simon McVittie <smcv at debian.org>
+Date:   2010-04-21 18:11:06 +0100
+
+    fd.o #27776: Avatars: implement the properties from spec 0.17.22
+    
+    The recommended height/width are set to the minimum (96) based on a quick
+    web search for the canonical sizes. Anyone who uses the official MSN
+    client and knows how big its avatars are is welcome to change them.
+
+commit 24f28734e7587674356559663736636d10b362c3
+Author: Simon McVittie <smcv at debian.org>
+Date:   2010-04-20 17:53:18 +0100
+
+    Be explicit about data types in methods that produce contact attributes
+    
+    Previously, the wrong type was returned for SimplePresence/presence.
+    Until telepathy-glib 0.11.3, this was masked by the fact that TpContact
+    would respond to missing or wrongly-typed information in the result of
+    GetContactAttributes by falling back to a slower path. This is no longer
+    done, meaning that all Butterfly contacts appear to have UNKNOWN presence.
+    
+    Reviewed-by: Olivier Le Thanh Duong <olivier at lethanh.be>
+
+commit 825fc60d2476b7e0abfad7f86c8823c2a292e7e3
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-19 14:32:05 +0100
+
+    Revert "connection: register the new connection with the CM so it fires NewConnection"
+    
+    This reverts commit 485e9596386bbb16d5d0d9354d6b950686c008c3. Turns
+    out telepathy.server.ConnectionManager already calls connected in
+    RequestConnection, and NewConnection is now being fired twice. Oops!
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 2f27c8aa1fcf6d68c9f29348a978bcf890bb2fbb
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-16 12:20:41 +0100
+
+    channel manager: stop adding StreamedMedia to RequestableChannelClasses
+    
+    Fixes fd.o#27689
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 57f4f6f82aeaba15e5fafea1b854d16f4de0b1ea
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-12 15:04:36 +0100
+
+    capabilities: fix typo
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 568bbfd74d44c28648b5522d9880cdb5792294e0
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-09 19:21:46 +0100
+
+    NEWS: update
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 9c1bac1a8c34e3a277d80c316e72eef9bf67f742
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-09 16:15:56 +0100
+
+    capabilities: fix typo
+    
+    ButterflyCapabilities is a class which ButterflyConnection inherits
+    from, so self *is* the connection.
+    
+    Fixes fd.o#27559
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit d173a535bbf07e0c97325fd01fa4ab1ad2299281
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-09 16:06:48 +0100
+
+    capabilities: handle the case when handle capabilities are not yet present for text channels
+    
+    Fixes fd.o#27555
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 3abc79447d1ebd3a2ea805c13af18b2b3b3c64bd
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-08 21:31:37 +0100
+
+    NEWS: update
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
+commit 78561f164a323836a0b01808d1e6baad2ab180f6
+Merge: 2cb906e 736fb20
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-08 21:24:46 +0100
+
+    Merge branch 'proxies'
+
+commit 2cb906efe9e03a860455ab9c5f1b9132d644f68a
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-08 14:25:22 +0100
+
+    Start 0.5.9 development.
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
 commit a9187b5e59f9bc14d8a9425f5610626bd9a2558c
 Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
 Date:   2010-04-08 14:07:48 +0100
@@ -23,6 +654,14 @@
     
     Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
 
+commit 736fb204bff174c21616ebb899fb8eaa144d1455
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-07 18:07:28 +0100
+
+    connection: only remove the HTTP proxy from the dict if one exists
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
 commit 7e62e6de36f316e43d67355d2dacd71c1691597a
 Author: Olivier Le Thanh Duong <olivier at lethanh.be>
 Date:   2010-04-05 13:30:44 +0200
@@ -47,6 +686,14 @@
 
     Implement the Messages interface (fd.o #27201)
 
+commit 0a2243f54a2bab1b13c54c5527970fd49118288f
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-04-06 19:24:27 +0100
+
+    proxies: only consider direct:// and http:// proxies
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
 commit e5beb9eeffe4da9b3f6c546595e633f98c0624b4
 Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
 Date:   2010-04-02 17:50:02 +0100
@@ -62,6 +709,14 @@
 
     Merge remote branch 'wjt/fd.o-27325-GetContactAttributes-tolerance'
 
+commit baa590f80ecdcb54f9db9490be8fa7c5132201f4
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-03-17 02:16:14 +0000
+
+    connection: use libproxy if available to autofill proxy list
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
 commit d5134bc148c46c0a78721c656af40121780ead83
 Merge: fbbb71a 84821ee
 Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
@@ -187,6 +842,17 @@
     
     Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
 
+commit 410290139bae4db97bf4aa42dec5a9255405d923
+Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
+Date:   2010-03-17 01:12:39 +0000
+
+    connection: fix build_proxy_infos' args
+    
+    This bug prevented proxy support from ever having worked, and due to
+    proxy_type having a default value, it was hidden!
+    
+    Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
+
 commit 6559379d29603d1384bce75ea3d35df6698ace51
 Author: Jonny Lamb <jonny.lamb at collabora.co.uk>
 Date:   2010-03-15 17:00:31 +0000
--- NEWS
+++ NEWS
@@ -1,3 +1,82 @@
+telepathy-butterfly-0.5.12 (2010-07-09)
+=======================================
+
+Enhancements:
+
+ * File transfer support has been merged. papyon 0.4.9 only has
+   switchboard transfers so they will be very slow, but it's a
+   start. (fd.o#22507)
+
+ * Only print messages (and tracebacks) to stderr if
+   BUTTERFLY_DEBUG=all. (fd.o#28930)
+
+Fixes:
+
+ * fd.o#28431: only try and logout if the client isn't already closed.
+
+ * Ensure the list of connections in the connection manager isn't
+   altered during iteration.
+
+ * Don't try and get details of an oim if we aren't given the sender.
+
+Dependencies:
+
+ * papyon 0.4.9 is now required.
+
+telepathy-butterfly-0.5.11 (2010-06-08)
+=======================================
+
+Fixes:
+
+ * fd.o#28354: make sure the correct type gets returned when getting
+   PendingMessages.
+
+ * Don't always remove pending messages when ListPendingMessages is
+   called.
+
+ * Don't assume "message-type" is set on calls to SendMessage.
+
+ * Replace \r\n with \n in incoming messages.
+
+telepathy-butterfly-0.5.10 (2010-05-20)
+=======================================
+
+Enhancements:
+ * Implement friendly names for groups chats (fd.o #25272)
+
+Fixes:
+ * Fix error when getting caps for certain contacts and offline contacts (fd.o #27736)
+ * Remove deprecation warning at start (fd.o #27843)
+ * Set Initator{ID,Handle} for all channels types (fd.o #27445)
+ * Don't connect via HTTP if we lost connection (fd.o #26147)
+ * Fix crash in check_handle when adding a contact (fd.o #27553)
+
+telepathy-butterfly-0.5.9 (2010-04-24)
+======================================
+
+Enhancements:
+
+ * libproxy can now be used to automatically retrieve proxy settings
+   and give these settings to papyon. NOTE: the version of
+   python-libproxy in Ubuntu (0.2.3) has a bug which makes butterfly
+   segfault -- version 0.3.1 is known to work. (fd.o#27121)
+
+Fixes:
+
+ * fd.o#27555: butterfly crashed with KeyError in
+   add_text_capabilities().
+
+ * fd.o#27559: butterfly crashed with AttributeError in
+   on_addressbook_contact_added().
+
+ * fd.o #27776: Avatars: implement the properties from spec 0.17.22.
+
+Dependencies:
+
+ * Not a hard dependency, but python-libproxy is required if you want
+   automatic proxy configuration to work. See the above note about
+   python-libproxy versions.
+
 telepathy-butterfly-0.5.8 (2010-04-08)
 ======================================
 
--- butterfly/aliasing.py
+++ butterfly/aliasing.py
@@ -18,6 +18,7 @@
 
 import logging
 
+import dbus
 import telepathy
 import telepathy.constants
 import papyon
@@ -49,7 +50,7 @@
     def GetAliases(self, contacts):
         logger.debug("Called GetAliases")
 
-        result = {}
+        result = dbus.Dictionary(signature='us')
         for contact in contacts:
             result[contact] = self._get_alias(contact)
         return result
--- butterfly/avatars.py
+++ butterfly/avatars.py
@@ -33,6 +33,12 @@
 
 logger = logging.getLogger('Butterfly.Avatars')
 
+SUPPORTED_AVATAR_MIME_TYPES = dbus.Array(["image/png", "image/jpeg",
+    "image/gif"], signature='s')
+MINIMUM_AVATAR_PIXELS = dbus.UInt32(96)
+RECOMMENDED_AVATAR_PIXELS = dbus.UInt32(96)
+MAXIMUM_AVATAR_PIXELS = dbus.UInt32(192)
+MAXIMUM_AVATAR_BYTES = dbus.UInt32(500 * 1024)
 
 class ButterflyAvatars(\
         telepathy.server.ConnectionInterfaceAvatars,
@@ -45,9 +51,24 @@
         papyon.event.ContactEventInterface.__init__(self, self.msn_client)
         papyon.event.ProfileEventInterface.__init__(self, self.msn_client)
 
+        dbus_interface = telepathy.CONNECTION_INTERFACE_AVATARS
+        self._implement_property_get(dbus_interface, {
+            'SupportedAvatarMIMETypes':
+                lambda: SUPPORTED_AVATAR_MIME_TYPES,
+            'MinimumAvatarHeight': lambda: MINIMUM_AVATAR_PIXELS,
+            'MinimumAvatarWidth': lambda: MINIMUM_AVATAR_PIXELS,
+            'RecommendedAvatarHeight': lambda: RECOMMENDED_AVATAR_PIXELS,
+            'RecommendedAvatarWidth': lambda: RECOMMENDED_AVATAR_PIXELS,
+            'MaximumAvatarHeight': lambda: MAXIMUM_AVATAR_PIXELS,
+            'MaximumAvatarWidth': lambda: MAXIMUM_AVATAR_PIXELS,
+            'MaximumAvatarBytes': lambda: MAXIMUM_AVATAR_BYTES,
+            })
+
     def GetAvatarRequirements(self):
-        mime_types = ("image/png","image/jpeg","image/gif")
-        return (mime_types, 96, 96, 192, 192, 500 * 1024)
+        return (SUPPORTED_AVATAR_MIME_TYPES,
+                MINIMUM_AVATAR_PIXELS, MINIMUM_AVATAR_PIXELS,
+                MAXIMUM_AVATAR_PIXELS, MAXIMUM_AVATAR_PIXELS,
+                MAXIMUM_AVATAR_BYTES)
 
     def GetKnownAvatarTokens(self, contacts):
         result = {}
--- butterfly/capabilities.py
+++ butterfly/capabilities.py
@@ -65,6 +65,18 @@
           telepathy.CHANNEL_TYPE_STREAMED_MEDIA + '.InitialAudio',
           telepathy.CHANNEL_TYPE_STREAMED_MEDIA + '.InitialVideo'])
 
+    file_transfer_class = \
+        ({telepathy.CHANNEL_INTERFACE + '.ChannelType':
+              telepathy.CHANNEL_TYPE_FILE_TRANSFER,
+          telepathy.CHANNEL_INTERFACE + '.TargetHandleType':
+              dbus.UInt32(telepathy.HANDLE_TYPE_CONTACT)},
+         [telepathy.CHANNEL_INTERFACE + '.TargetHandle',
+          telepathy.CHANNEL_INTERFACE + '.TargetID',
+          telepathy.CHANNEL_TYPE_FILE_TRANSFER + '.Requested',
+          telepathy.CHANNEL_TYPE_FILE_TRANSFER + '.Filename',
+          telepathy.CHANNEL_TYPE_FILE_TRANSFER + '.Size',
+          telepathy.CHANNEL_TYPE_FILE_TRANSFER + '.ContentType'])
+
 
     def __init__(self):
         telepathy.server.ConnectionInterfaceCapabilities.__init__(self)
@@ -96,12 +108,18 @@
         ret = dbus.Dictionary({}, signature='ua(a{sv}as)')
         for i in handles:
             handle = self.handle(telepathy.HANDLE_TYPE_CONTACT, i)
-            ret[handle] = self._contact_caps[handle]
+            # If the handle has no contact capabilities yet then it
+            # won't be in the dict. It's fair to return an empty list
+            # here for its contact caps.
+            if handle in self._contact_caps:
+		ret[handle] = dbus.Array(self._contact_caps[handle], signature='(a{sv}as)')
+            else:
+                ret[handle] = dbus.Array([], signature='(a{sv}as)')
 
         return ret
 
     def UpdateCapabilities(self, caps):
-        if self._state != telepathy.CONNECTION_STATUS_CONNECTED:
+        if self._status != telepathy.CONNECTION_STATUS_CONNECTED:
             self._update_capabilities_calls.append(caps)
             return
 
@@ -148,31 +166,55 @@
     # papyon.event.AddressBookEventInterface
     def on_addressbook_contact_added(self, contact):
         """When we add a contact in our contact list, add the
-        capabilities to create text channel to the contact"""
+        default capabilities to the contact"""
         if contact.is_member(papyon.Membership.FORWARD):
-            handle = ButterflyHandleFactory(self._conn_ref(), 'contact',
+            handle = ButterflyHandleFactory(self, 'contact',
                     contact.account, contact.network_id)
-            self.add_text_capabilities([handle])
+            self.add_default_capabilities([handle])
+
+    def _diff_capabilities(self, handle, ctype, new_gen=None,
+            new_spec=None, added_gen=None, added_spec=None):
+
+        if handle in self._caps and ctype in self._caps[handle]:
+            old_gen, old_spec = self._caps[handle][ctype]
+        else:
+            old_gen = 0
+            old_spec = 0
+
+        if new_gen is None:
+            new_gen = old_gen
+        if new_spec is None:
+            new_spec = old_spec
+        if added_gen:
+            new_gen |= added_gen
+        if added_spec:
+            new_spec |= new_spec
+
+        if old_gen != new_gen or old_spec != new_spec:
+            diff = (int(handle), ctype, old_gen, new_gen, old_spec, new_spec)
+            return diff
 
-    def add_text_capabilities(self, contacts_handles):
-        """Add the create capability for text channel to these contacts."""
+        return None
+
+    def add_default_capabilities(self, contacts_handles):
+        """Add the default capabilities to these contacts."""
         ret = []
         cc_ret = dbus.Dictionary({}, signature='ua(a{sv}as)')
         for handle in contacts_handles:
+            new_flag = telepathy.CONNECTION_CAPABILITY_FLAG_CREATE
+
             ctype = telepathy.CHANNEL_TYPE_TEXT
-            if handle in self._caps:
-                old_gen, old_spec = self._caps[handle][ctype]
-            else:
-                old_gen = 0
-                old_spec = 0
-            new_gen = old_gen
-            new_gen |= telepathy.CONNECTION_CAPABILITY_FLAG_CREATE
+            diff = self._diff_capabilities(handle, ctype, added_gen=new_flag)
+            ret.append(diff)
 
-            diff = (int(handle), ctype, old_gen, new_gen, old_spec, old_spec)
+            ctype = telepathy.CHANNEL_TYPE_FILE_TRANSFER
+            diff = self._diff_capabilities(handle, ctype, added_gen=new_flag)
             ret.append(diff)
 
             # ContactCapabilities
-            self._contact_caps.setdefault(handle, []).append(self.text_chat_class)
+            caps = self._contact_caps.setdefault(handle, [])
+            caps.append(self.text_chat_class)
+            caps.append(self.file_transfer_class)
             cc_ret[handle] = self._contact_caps[handle]
 
         self.CapabilitiesChanged(ret)
@@ -184,14 +226,8 @@
         ctype = telepathy.CHANNEL_TYPE_STREAMED_MEDIA
 
         new_gen, new_spec, rcc = self._get_capabilities(contact)
-        if handle in self._caps:
-            old_gen, old_spec = self._caps[handle][ctype]
-        else:
-            old_gen = 0
-            old_spec = 0
-
-        if old_gen != new_gen or old_spec != new_spec:
-            diff = (int(handle), ctype, old_gen, new_gen, old_spec, new_spec)
+        diff = self._diff_capabilities(handle, ctype, new_gen, new_spec)
+        if diff is not None:
             self.CapabilitiesChanged([diff])
 
         if rcc is None:
@@ -237,7 +273,7 @@
 
     @async
     def _populate_capabilities(self):
-        """ Add the capability to create text channels to all contacts in our
+        """ Add the default capabilities to all contacts in our
         contacts list."""
         handles = set([self._self_handle])
         for contact in self.msn_client.address_book.contacts:
@@ -245,7 +281,7 @@
                 handle = ButterflyHandleFactory(self, 'contact',
                         contact.account, contact.network_id)
                 handles.add(handle)
-        self.add_text_capabilities(handles)
+        self.add_default_capabilities(handles)
 
         # These caps were updated before we were online.
         for caps in self._update_capabilities_calls:
--- butterfly/channel/Makefile.am
+++ butterfly/channel/Makefile.am
@@ -2,6 +2,7 @@
 channel_PYTHON = \
 	conference.py \
 	contact_list.py \
+	file_transfer.py \
 	group.py \
 	im.py \
 	__init__.py \
--- butterfly/channel/Makefile.in
+++ butterfly/channel/Makefile.in
@@ -159,6 +159,7 @@
 channel_PYTHON = \
 	conference.py \
 	contact_list.py \
+	file_transfer.py \
 	group.py \
 	im.py \
 	__init__.py \
--- butterfly/channel/__init__.py
+++ butterfly/channel/__init__.py
@@ -14,4 +14,48 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
\ No newline at end of file
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import logging
+import dbus
+
+import telepathy
+
+from butterfly.handle import ButterflyHandleFactory
+
+__all__ = ['ButterflyChannel']
+
+logger = logging.getLogger('Butterfly.Channel')
+
+class ButterflyChannel(object):
+    def __init__(self, conn, props):
+        # If we have InitiatorHandle set in our new channel, use that,
+        if telepathy.CHANNEL_INTERFACE + '.InitiatorHandle' in props:
+            self._initiator = conn.handle(telepathy.HANDLE_TYPE_CONTACT,
+                props[telepathy.CHANNEL_INTERFACE + '.InitiatorHandle'])
+
+        # otherwise use InitiatorID.
+        elif telepathy.CHANNEL_INTERFACE + '.InitiatorID' in props:
+            self._initiator = ButterflyHandleFactory(conn, 'contact',
+                id=props[telepathy.CHANNEL_INTERFACE + '.InitiatorID'])
+
+        # If we don't have either of the above but we requested the channel,
+        # then we're the initiator.
+        elif props[telepathy.CHANNEL_INTERFACE + '.Requested']:
+            self._initiator = conn.GetSelfHandle()
+
+        else:
+            logger.warning('InitiatorID or InitiatorHandle not set on new channel')
+            self._initiator = None
+
+        # Don't implement the initiator properties if we don't have one.
+        if self._initiator:
+            self._implement_property_get(telepathy.CHANNEL_INTERFACE, {
+                    'InitiatorHandle': lambda: dbus.UInt32(self._initiator.id),
+                    'InitiatorID': lambda: self._initiator.name
+                    })
+
+            self._add_immutables({
+                    'InitiatorHandle': telepathy.CHANNEL_INTERFACE,
+                    'InitiatorID': telepathy.CHANNEL_INTERFACE,
+                    })
--- butterfly/channel/contact_list.py
+++ butterfly/channel/contact_list.py
@@ -25,9 +25,11 @@
 
 from butterfly.util.decorator import async
 from butterfly.handle import ButterflyHandleFactory
+from butterfly.channel import ButterflyChannel
 
 __all__ = ['ButterflyContactListChannelFactory']
 
+logger = logging.getLogger('Butterfly.ContactListChannel')
 
 class HandleMutex(object):
     def __init__(self):
@@ -111,6 +113,7 @@
 
 
 class ButterflyListChannel(
+        ButterflyChannel,
         telepathy.server.ChannelTypeContactList,
         telepathy.server.ChannelInterfaceGroup,
         papyon.event.AddressBookEventInterface):
@@ -120,6 +123,7 @@
         self._conn_ref = weakref.ref(connection)
         telepathy.server.ChannelTypeContactList.__init__(self, connection, manager, props,
             object_path=object_path)
+        ButterflyChannel.__init__(self, connection, props)
         telepathy.server.ChannelInterfaceGroup.__init__(self)
         papyon.event.AddressBookEventInterface.__init__(self, connection.msn_client)
         self._populate(connection)
@@ -226,13 +230,59 @@
         groups = list(handle.pending_groups)
         handle.pending_groups = set()
         ab = self._conn.msn_client.address_book
+
+        # We redefine these two callbacks for two reasons:
+        #
+        #  1. For failed, we can give a nice warning.
+        #
+        #  2. For both callbacks, it is more than likely that calling
+        #     finished_cb() will unlock the mutex and the publish
+        #     channel underneath's _add function will be called. If we
+        #     keep handle in scope, it won't be disposed and the
+        #     publish channel will have the same handle. This fixes a
+        #     few bugs:
+        #
+        #      I. When the contact doesn't actually exist, calling
+        #         finished_cb after the handle gets disposed means it
+        #         will no longer be in the connection's handle
+        #         dictionary and the publish channel's _add() will
+        #         raise InvalidHandle (see fd.o#27553). This isn't
+        #         actually a problem as the function should return
+        #         anyway but it doesn't get a chance to unlock the
+        #         mutex and it throws an unhandled exception which
+        #         apport users think is crazy.
+        #
+        #     II. Similar to above, but when the contact does
+        #         actually exist then the publish list wants to act
+        #         appropriately. If the handle has already been
+        #         disposed then it'll raise the same exception and
+        #         won't call the appropriate AB method.
+        #
+        #    III. When a contact is actually added, instead of the
+        #         handle already having been disposed of, it stays
+        #         around for a bit so you don't add handle n and then
+        #         MembersChanged gets fired for handle n+1.
+        #
+        # If these cases aren't in fact in play when this is called,
+        # then not only am I surprised, but no damage is done.
+
+        def failed_cb(error_code, *cb_args):
+            logger.warning('Failed to add messenger contact; '
+                           'error code: %s' % error_code)
+            finished_cb()
+            handle
+
+        def done_cb(*cb_args):
+            finished_cb()
+            handle
+
         ab.add_messenger_contact(account,
                 network_id=network,
                 auto_allow=False,
                 invite_message=message.encode('utf-8'),
                 groups=groups,
-                done_cb=(finished_cb,),
-                failed_cb=(finished_cb,))
+                done_cb=(done_cb,),
+                failed_cb=(failed_cb,))
 
     @Lockable(mutex, 'rem_subscribe', 'finished_cb')
     def _remove(self, handle_id, finished_cb):
@@ -299,6 +349,12 @@
         if contact is not None and contact.is_member(papyon.Membership.ALLOW):
             return True
 
+        # This will occur if the contact doesn't actually exist
+        # (e.g. nobody at example.com).
+        if contact is None:
+            logger.debug('Cannot allow/accept None contact %s' % handle.get_name())
+            return True
+
         account = handle.account
         network = handle.network
         ab = self._conn.msn_client.address_book
--- butterfly/channel/file_transfer.py
+++ butterfly/channel/file_transfer.py
+# telepathy-butterfly - an MSN connection manager for Telepathy
+#
+# Copyright (C) 2010 Collabora Ltd.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+import logging
+import weakref
+import time
+import tempfile
+import os
+import shutil
+
+import dbus
+import gobject
+import telepathy
+import papyon
+import papyon.event
+import socket
+
+from butterfly.util.decorator import async
+from butterfly.handle import ButterflyHandleFactory
+
+from telepathy.interfaces import CHANNEL_TYPE_FILE_TRANSFER
+
+__all__ = ['ButterflyFileTransferChannel']
+
+logger = logging.getLogger('Butterfly.FileTransferChannel')
+
+
+class ButterflyFileTransferChannel(telepathy.server.ChannelTypeFileTransfer):
+
+    def __init__(self, conn, manager, session, handle, props, object_path=None):
+        telepathy.server.ChannelTypeFileTransfer.__init__(self, conn, manager, props,
+            object_path=object_path)
+
+        self._handle = handle
+        self._conn_ref = weakref.ref(conn)
+        self._state = 0
+        self._transferred = 0
+
+        self._receiving = not props[telepathy.CHANNEL + '.Requested']
+        self.socket = None
+        self._tmpdir = None
+
+        self._last_ltb_emitted = 0
+        self._progress_timer = 0
+
+        # Incoming.
+        if session is None:
+            type = telepathy.CHANNEL_TYPE_FILE_TRANSFER
+            filename = props.get(type + ".Filename", None)
+            size = props.get(type + ".Size", None)
+
+            if filename is None or size is None:
+                raise telepathy.InvalidArgument(
+                    "New file transfer channel requires Filename and Size properties")
+
+            client = conn.msn_client
+            session = client.ft_manager.send(handle.contact, filename, size)
+
+        self._session = session
+        self._filename = session.filename
+        self._size = session.size
+
+        session.connect("accepted", self._transfer_accepted)
+        session.connect("progressed", self._transfer_progressed)
+        session.connect("completed", self._transfer_completed)
+
+        dbus_interface = telepathy.CHANNEL_TYPE_FILE_TRANSFER
+        self._implement_property_get(dbus_interface, {
+                'State' : lambda: dbus.UInt32(self.state),
+                'ContentType': lambda: self.content_type,
+                'Filename': lambda: self.filename,
+                'Size': lambda: dbus.UInt64(self.size),
+                'Description': lambda: self.description,
+                'AvailableSocketTypes': lambda: self.socket_types,
+                'TransferredBytes': lambda: self.transferred,
+                'InitialOffset': lambda: self.offset
+                })
+
+        self._add_immutables({
+                'Filename': CHANNEL_TYPE_FILE_TRANSFER,
+                'Size': CHANNEL_TYPE_FILE_TRANSFER,
+                })
+
+        self.set_state(telepathy.FILE_TRANSFER_STATE_PENDING,
+            telepathy.FILE_TRANSFER_STATE_CHANGE_REASON_REQUESTED)
+
+    @property
+    def state(self):
+        return self._state
+
+    @property
+    def content_type(self):
+        return "application/octet-stream"
+
+    @property
+    def filename(self):
+        return self._filename
+
+    @property
+    def size(self):
+        return self._size
+
+    @property
+    def description(self):
+        return ""
+
+    @property
+    def socket_types(self):
+        return {telepathy.SOCKET_ADDRESS_TYPE_UNIX:
+                [telepathy.SOCKET_ACCESS_CONTROL_LOCALHOST,
+                 telepathy.SOCKET_ACCESS_CONTROL_CREDENTIALS]}
+
+    @property
+    def transferred(self):
+        return self._transferred
+
+    @property
+    def offset(self):
+        return 0
+
+    def set_state(self, state, reason):
+        if self._state == state:
+            return
+        logger.debug("State change: %u -> %u (reason: %u)" % (self._state, state, reason))
+        self._state = state
+        self.FileTransferStateChanged(state, reason)
+
+    def AcceptFile(self, address_type, access_control, param, offset):
+        logger.debug("Accept file")
+
+        if address_type not in self.socket_types.keys():
+            raise telepathy.NotImplemented("Socket type %u is unsupported" % address_type)
+
+        self.socket = self.add_listener()
+        self.channel = self.add_io_channel(self.socket)
+        self.set_state(telepathy.FILE_TRANSFER_STATE_PENDING,
+            telepathy.FILE_TRANSFER_STATE_CHANGE_REASON_REQUESTED)
+        self.InitialOffsetDefined(0)
+        self.set_state(telepathy.FILE_TRANSFER_STATE_OPEN,
+            telepathy.FILE_TRANSFER_STATE_CHANGE_REASON_NONE)
+        return self.socket.getsockname()
+
+    def ProvideFile(self, address_type, access_control, param):
+        logger.debug("Provide file")
+
+        if address_type not in self.socket_types.keys():
+            raise telepathy.NotImplemented("Socket type %u is unsupported" % address_type)
+
+        self.socket = self.add_listener()
+        self.channel = self.add_io_channel(self.socket)
+        return self.socket.getsockname()
+
+    def Close(self):
+        logger.debug("Close")
+        self.cleanup()
+        if self.state not in (telepathy.FILE_TRANSFER_STATE_CANCELLED,
+                              telepathy.FILE_TRANSFER_STATE_COMPLETED):
+            self.set_state(telepathy.FILE_TRANSFER_STATE_CANCELLED,
+                telepathy.FILE_TRANSFER_STATE_CHANGE_REASON_LOCAL_CANCELLED)
+        telepathy.server.ChannelTypeFileTransfer.Close(self)
+        self.remove_from_connection()
+
+    def cleanup(self):
+        if self._receiving and self.state == telepathy.FILE_TRANSFER_STATE_PENDING:
+            self._session.reject()
+
+        if self.state not in (telepathy.FILE_TRANSFER_STATE_CANCELLED,
+                              telepathy.FILE_TRANSFER_STATE_COMPLETED):
+            self._session.cancel()
+
+        if self.socket:
+            self.socket.close()
+            self.socket = None
+
+        if self._tmpdir:
+            shutil.rmtree(self._tmpdir)
+            self._tmpdir = None
+
+    def GetSelfHandle(self):
+        return self._conn.GetSelfHandle()
+
+    def add_listener(self):
+        """Create a listener socket"""
+        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0)
+        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
+        self._tmpdir = tempfile.mkdtemp(prefix="butterfly")
+        sock.bind(os.path.join(self._tmpdir, "ft-socket"))
+        sock.listen(1)
+        return sock
+
+    def add_io_channel(self, sock):
+        """Set up notification on the socket via a giochannel"""
+        sock.setblocking(False)
+        channel = gobject.IOChannel(sock.fileno())
+        channel.set_flags(channel.get_flags() | gobject.IO_FLAG_NONBLOCK)
+        channel.add_watch(gobject.IO_IN, self._socket_connected)
+        channel.add_watch(gobject.IO_HUP | gobject.IO_ERR,
+            self._socket_disconnected)
+        return channel
+
+    def _socket_connected(self, channel, condition):
+        logger.debug("Client socket connected")
+        sock = self.socket.accept()[0]
+        if self._receiving:
+            buffer = DataBuffer(sock)
+            self._session.set_receive_data_buffer(buffer, self.size)
+            # Notify the other end we accepted the FT
+            self._session.accept()
+        else:
+            buffer = DataBuffer(sock, self.size)
+            self._session.send(buffer)
+        self.socket = sock
+
+    def _socket_disconnected(self, channel, condition):
+        logger.debug("Client socket disconnected")
+        #self.cleanup()
+        #TODO only cancel if the socket is disconnected while listening
+        #self._session.cancel()
+        #self.set_state(telepathy.FILE_TRANSFER_STATE_CANCELLED,
+        #               telepathy.FILE_TRANSFER_STATE_CHANGE_REASON_LOCAL_ERROR)
+
+    def _transfer_accepted(self, session):
+        logger.debug("Transfer has been accepted")
+        self.set_state(telepathy.FILE_TRANSFER_STATE_ACCEPTED,
+            telepathy.FILE_TRANSFER_STATE_CHANGE_REASON_REQUESTED)
+        self.set_state(telepathy.FILE_TRANSFER_STATE_OPEN,
+            telepathy.FILE_TRANSFER_STATE_CHANGE_REASON_NONE)
+
+    def _transfer_progressed(self, session, size):
+        self._transferred += size
+
+        def emit_signal():
+            self.TransferredBytesChanged(self.transferred)
+            self._last_ltb_emitted = time.time()
+            self._progress_timer = 0
+            return False
+
+        # If the transfer has finished send an update right away.
+        if self.transferred >= self.size:
+            emit_signal()
+            return
+
+        # A progress update signal is already scheduled.
+        if self._progress_timer != 0:
+            return
+
+        # Only emit the TransferredBytes signal if it has been one
+        # second since its last emission.
+        interval = time.time() - self._last_ltb_emitted
+        if interval >= 1:
+            emit_signal()
+            return
+
+        # Get it in microseconds.
+        interval /= 1000
+
+        # Protect against clock skew, if the interval is negative the
+        # worst thing that can happen is that we wait an extra second
+        # before emitting the signal.
+        interval = abs(interval)
+
+        if interval > 1000:
+            emit_signal()
+        else:
+            self._progress_timer = gobject.timeout_add(1000 - interval,
+                emit_signal)
+
+    def _transfer_completed(self, session, data):
+        logger.debug("Transfer completed")
+        self.set_state(telepathy.FILE_TRANSFER_STATE_COMPLETED,
+            telepathy.FILE_TRANSFER_STATE_CHANGE_REASON_NONE)
+        self.cleanup()
+
+class DataBuffer(object):
+
+    def __init__(self, socket, size=0):
+        self._socket = socket
+        self._size = size
+        self._offset = 0
+        self._buffer = ""
+        #self.add_channel()
+
+    def seek(self, offset, position):
+        if position == 0:
+            self._offset = offset
+        elif position == 2:
+            self._offset = self._size
+
+    def tell(self):
+        return self._offset
+
+    def read(self, max_size=None):
+        if max_size is None:
+            # we can't read all the data;
+            # let's just return the last chunk
+            return self._buffer
+        max_size = min(max_size, self._size - self._offset)
+        data = self._socket.recv(max_size)
+        self._buffer = data
+        self._offset += len(data)
+        return data
+
+    def write(self, data):
+        self._buffer = data
+        self._size += len(data)
+        self._offset += len(data)
+        self._socket.send(data)
+
+    def add_channel(self):
+        sock = self._socket
+        sock.setblocking(False)
+        channel = gobject.IOChannel(sock.fileno())
+        channel.set_encoding(None)
+        channel.set_buffered(False)
+        channel.set_flags(channel.get_flags() | gobject.IO_FLAG_NONBLOCK)
+        channel.add_watch(gobject.IO_HUP | gobject.IO_ERR, self.on_error)
+        channel.add_watch(gobject.IO_IN | gobject.IO_PRI, self.on_stream_received)
+        self.channel = channel
+
+    def on_error(self, channel, condition):
+        logger.error("DataBuffer %s" % condition)
+
+    def on_stream_disconnected(self, channel, condition):
+        pass
+
+    def on_stream_received(self, channel, condition):
+        logger.info("Received data to send")
+        data = channel.read(1024)
+        print data
+        #self._session.send_chunk(data)
--- butterfly/channel/im.py
+++ butterfly/channel/im.py
@@ -21,6 +21,7 @@
 import logging
 import weakref
 import time
+import re
 
 import dbus
 import telepathy
@@ -178,7 +179,8 @@
         id = self._recv_id
         sender = message.sender
         timestamp = time.mktime(message.date.timetuple())
-        text = message.text
+        text = re.sub('\r\n', '\n', message.text)
+        text = re.sub('\r', '\n', text)
 
         # Map the id to the offline message so we can remove it
         # when acked by the client
@@ -188,7 +190,7 @@
                 sender.account, sender.network_id)
         type = telepathy.CHANNEL_TEXT_MESSAGE_TYPE_NORMAL
         logger.info("User %r sent a offline message" % handle)
-        self._signal_text_received(id, timestamp, handle, type, 0, text)
+        self._signal_text_received(id, timestamp, handle, type, 0, message.display_name, text)
 
         self._recv_id += 1
 
--- butterfly/channel/media.py
+++ butterfly/channel/media.py
@@ -27,6 +27,7 @@
 from butterfly.util.decorator import async
 from butterfly.handle import ButterflyHandleFactory
 from butterfly.media import ButterflySessionHandler
+from butterfly.channel import ButterflyChannel
 
 from telepathy.interfaces import CHANNEL_INTERFACE, CHANNEL_INTERFACE_GROUP,\
     CHANNEL_TYPE_STREAMED_MEDIA
@@ -38,6 +39,7 @@
 
 
 class ButterflyMediaChannel(
+        ButterflyChannel,
         telepathy.server.ChannelTypeStreamedMedia,
         telepathy.server.ChannelInterfaceCallState,
         telepathy.server.ChannelInterfaceGroup,
@@ -55,33 +57,14 @@
         papyon.event.CallEventInterface.__init__(self, call)
         papyon.event.ContactEventInterface.__init__(self, conn.msn_client)
         papyon.event.MediaSessionEventInterface.__init__(self, call.media_session)
+        ButterflyChannel.__init__(self, conn, props)
 
         self._call = call
         self._handle = handle
 
-        self._implement_property_get(CHANNEL_INTERFACE, {
-                'InitiatorHandle': lambda: dbus.UInt32(self._initiator.id),
-                'InitiatorID': lambda: self._initiator.name
-                })
-
         self._implement_property_get(CHANNEL_INTERFACE_GROUP,
             {'LocalPendingMembers': lambda: self.GetLocalPendingMembersWithInfo() })
 
-        self._add_immutables({
-                'InitiatorHandle': CHANNEL_INTERFACE,
-                'InitiatorID': CHANNEL_INTERFACE,
-                })
-
-        if CHANNEL_INTERFACE + '.InitiatorHandle' in props:
-            self._initiator = conn.handle(telepathy.HANDLE_TYPE_CONTACT,
-                props[CHANNEL_INTERFACE + '.InitiatorHandle'])
-        elif CHANNEL_INTERFACE + '.InitiatorID' in props:
-            self._initiator = ButterflyHandleFactory(conn, 'contact',
-                id=props[CHANNEL_INTERFACE + '.InitiatorHandle'])
-        else:
-            logger.warning('InitiatorID or InitiatorHandle not set on new channel')
-            self._initiator = None
-
         self._session_handler = ButterflySessionHandler(self._conn, self, call.media_session)
 
         flags = (telepathy.CHANNEL_GROUP_FLAG_CAN_REMOVE |
--- butterfly/channel/text.py
+++ butterfly/channel/text.py
@@ -22,6 +22,7 @@
 import logging
 import weakref
 import time
+import re
 
 import dbus
 import telepathy
@@ -31,12 +32,14 @@
 from telepathy.interfaces import CHANNEL_INTERFACE_MESSAGES
 
 from butterfly.handle import ButterflyHandleFactory
+from butterfly.channel import ButterflyChannel
 
 __all__ = ['ButterflyTextChannel']
 
 logger = logging.getLogger('Butterfly.TextChannel')
 
 class ButterflyTextChannel(
+        ButterflyChannel,
         telepathy.server.ChannelTypeText,
         telepathy.server.ChannelInterfaceChatState,
         ChannelInterfaceMessages,
@@ -54,6 +57,7 @@
 
         telepathy.server.ChannelTypeText.__init__(self, conn, manager, props,
             object_path=object_path)
+        ButterflyChannel.__init__(self, conn, props)
         telepathy.server.ChannelInterfaceChatState.__init__(self)
         ChannelInterfaceMessages.__init__(self)
         papyon.event.ConversationEventInterface.__init__(self, conn.msn_client)
@@ -62,7 +66,7 @@
             'SupportedContentTypes': lambda: ["text/plain"] ,
             'MessagePartSupportFlags': lambda: 0,
             'DeliveryReportingSupport': lambda: telepathy.DELIVERY_REPORTING_SUPPORT_FLAG_RECEIVE_FAILURES,
-            'PendingMessages': lambda: self._pending_messages2
+            'PendingMessages': lambda: dbus.Array(self._pending_messages2.values(), signature='aa{sv}')
             })
 
         self._add_immutables({
@@ -151,18 +155,21 @@
         self.Sent(timestamp, message_type, text)
         self.MessageSent(message, 0, '')
 
-    def _signal_text_received(self, id, timestamp, sender, type, flags, text):
+    def _signal_text_received(self, id, timestamp, sender, type, flags, sender_nick, text):
         self.Received(id, timestamp, sender, type, flags, text)
-        headers = {'message-received' : timestamp,
-                   'pending-message-id' : int(id),
-                   'message-sender' : int(sender),
-                   'message-type' : type
-                  }
-
-        body = {'content-type': 'text/plain',
-                'content': text
-               }
-        message = [headers, body]
+        headers = dbus.Dictionary({dbus.String('message-received') : dbus.UInt64(timestamp),
+                   dbus.String('pending-message-id') : dbus.UInt32(id),
+                   dbus.String('message-sender') : dbus.UInt32(sender),
+                   dbus.String('message-type') : dbus.UInt32(type)
+                  }, signature='sv')
+
+        if sender_nick not in (None, ''):
+            headers[dbus.String('sender-nickname')] = dbus.String(sender_nick)
+
+        body = dbus.Dictionary({dbus.String('content-type'): dbus.String('text/plain'),
+                dbus.String('content'): dbus.String(text)
+               }, signature='sv')
+        message = dbus.Array([headers, body], signature='a{sv}')
         self.MessageReceived(message)
 
     def SetChatState(self, state):
@@ -211,7 +218,7 @@
                          out_signature='s', async_callbacks=('_success', '_error'))
     def SendMessage(self, message, flags, _success, _error):
         headers = message.pop(0)
-        message_type = int(headers['message-type'])
+        message_type = int(headers.get('message-type', telepathy.CHANNEL_TEXT_MESSAGE_TYPE_NORMAL))
         if message_type != telepathy.CHANNEL_TEXT_MESSAGE_TYPE_NORMAL:
                 raise telepathy.NotImplemented("Unhandled message type")
         text = None
@@ -237,9 +244,11 @@
         self.PendingMessagesRemoved(ids)
 
     def ListPendingMessages(self, clear):
-        ids = self._pending_messages2.keys()
-        self._pending_messages2 = {}
-        self.PendingMessagesRemoved(ids)
+        if clear:
+            ids = self._pending_messages2.keys()
+            self._pending_messages2 = {}
+            self.PendingMessagesRemoved(ids)
+
         return telepathy.server.ChannelTypeText.ListPendingMessages(self, clear)
 
     # Redefine GetSelfHandle since we use our own handle
@@ -280,9 +289,10 @@
         handle = ButterflyHandleFactory(self._conn_ref(), 'contact',
                 sender.account, sender.network_id)
         type = telepathy.CHANNEL_TEXT_MESSAGE_TYPE_NORMAL
-        message = message.content
         logger.info("User %s sent a message" % unicode(handle))
-        self._signal_text_received(id, timestamp, handle, type, 0, message)
+        content = re.sub('\r\n', '\n', message.content)
+        content = re.sub('\r', '\n', content)
+        self._signal_text_received(id, timestamp, handle, type, 0, message.display_name, content)
         self._recv_id += 1
 
     # papyon.event.ConversationEventInterface
@@ -297,5 +307,5 @@
     @dbus.service.signal(telepathy.CHANNEL_INTERFACE_MESSAGES, signature='aa{sv}')
     def MessageReceived(self, message):
         id = message[0]['pending-message-id']
-        self._pending_messages2[id] = message
+        self._pending_messages2[id] = dbus.Array(message, signature='a{sv}')
 
--- butterfly/channel_manager.py
+++ butterfly/channel_manager.py
@@ -29,6 +29,7 @@
 from butterfly.channel.im import ButterflyImChannel
 from butterfly.channel.muc import ButterflyMucChannel
 from butterfly.channel.conference import ButterflyConferenceChannel
+from butterfly.channel.file_transfer import ButterflyFileTransferChannel
 from butterfly.channel.media import ButterflyMediaChannel
 from butterfly.handle import ButterflyHandleFactory
 
@@ -81,6 +82,7 @@
 class ButterflyChannelManager(telepathy.server.ChannelManager):
     __text_channel_id = 1
     __media_channel_id = 1
+    __ft_channel_id = 1
 
     def __init__(self, connection):
         telepathy.server.ChannelManager.__init__(self, connection)
@@ -114,15 +116,29 @@
             ]
         self.implement_channel_classes(telepathy.CHANNEL_TYPE_CONTACT_LIST, self._get_list_channel, classes)
 
+#        classes = [
+#            ({telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_STREAMED_MEDIA,
+#              telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_CONTACT)},
+#             [telepathy.CHANNEL_INTERFACE + '.TargetHandle',
+#              telepathy.CHANNEL_INTERFACE + '.TargetID',
+#              telepathy.CHANNEL_TYPE_STREAMED_MEDIA + '.InitialAudio',
+#              telepathy.CHANNEL_TYPE_STREAMED_MEDIA + '.InitialVideo'])
+#            ]
+#        self.implement_channel_classes(telepathy.CHANNEL_TYPE_STREAMED_MEDIA, self._get_media_channel, classes)
+
         classes = [
-            ({telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_STREAMED_MEDIA,
+            ({telepathy.CHANNEL_INTERFACE + '.ChannelType': telepathy.CHANNEL_TYPE_FILE_TRANSFER,
               telepathy.CHANNEL_INTERFACE + '.TargetHandleType': dbus.UInt32(telepathy.HANDLE_TYPE_CONTACT)},
              [telepathy.CHANNEL_INTERFACE + '.TargetHandle',
               telepathy.CHANNEL_INTERFACE + '.TargetID',
-              telepathy.CHANNEL_TYPE_STREAMED_MEDIA + '.InitialAudio',
-              telepathy.CHANNEL_TYPE_STREAMED_MEDIA + '.InitialVideo'])
+              telepathy.CHANNEL_TYPE_FILE_TRANSFER + '.ContentType',
+              telepathy.CHANNEL_TYPE_FILE_TRANSFER + '.Filename',
+              telepathy.CHANNEL_TYPE_FILE_TRANSFER + '.Size',
+              telepathy.CHANNEL_TYPE_FILE_TRANSFER + '.ContentHash',
+              telepathy.CHANNEL_TYPE_FILE_TRANSFER + '.Description',
+              telepathy.CHANNEL_TYPE_FILE_TRANSFER + '.Date'])
             ]
-        self.implement_channel_classes(telepathy.CHANNEL_TYPE_STREAMED_MEDIA, self._get_media_channel, classes)
+        self.implement_channel_classes(telepathy.CHANNEL_TYPE_FILE_TRANSFER, self._get_ft_channel, classes)
 
     def _get_list_channel(self, props):
         _, surpress_handler, handle = self._get_type_requested_handle(props)
@@ -183,9 +199,27 @@
             client = self._conn.msn_client
             call = client.call_manager.create_call(contact)
 
-
         path = "MediaChannel/%d" % self.__media_channel_id
         self.__media_channel_id += 1
 
         return ButterflyMediaChannel(self._conn, self, call, handle, props,
             object_path=path)
+
+    def _get_ft_channel(self, props, session=None):
+        _, surpress_handler, handle = self._get_type_requested_handle(props)
+
+        if handle.get_type() != telepathy.HANDLE_TYPE_CONTACT:
+            raise telepathy.NotImplemented('Only contacts are allowed')
+
+        contact = handle.contact
+
+        if contact.presence == papyon.Presence.OFFLINE:
+            raise telepathy.NotAvailable('Contact not available')
+
+        logger.debug('New file transfer channel')
+
+        path = "FileTransferChannel%d" % self.__ft_channel_id
+        self.__ft_channel_id += 1
+
+        return ButterflyFileTransferChannel(self._conn, self, session, handle,
+            props, object_path=path)
--- butterfly/connection.py
+++ butterfly/connection.py
@@ -95,6 +95,14 @@
             if proxy is not None:
                 self._proxies['https'] = proxy
 
+            self._suggested_proxies = []
+
+            # If the HTTP proxy parameters have been set, don't try any
+            # others proxies automatically.
+            if 'http' not in self._proxies:
+                self._fill_suggested_proxies()
+                self._use_next_proxy()
+
             self._manager = weakref.proxy(manager)
             self._new_client(use_http=parameters['http-method'])
             self._account = (parameters['account'].encode('utf-8'),
@@ -117,8 +125,6 @@
             self._initial_presence = papyon.Presence.INVISIBLE
             self._initial_personal_message = None
 
-            self._manager.connected(self)
-
             logger.info("Connection to the account %s created" % account)
         except Exception, e:
             import traceback
@@ -127,7 +133,8 @@
 
     def _new_client(self, use_http=False):
         if hasattr(self, '_msn_client') and self._msn_client:
-            self._msn_client.logout()
+            if self._msn_client.state != papyon.event.ClientState.CLOSED:
+                self._msn_client.logout()
             self._msn_client._events_handlers.remove(self)
 
         if use_http:
@@ -142,6 +149,67 @@
         papyon.event.InviteEventInterface.__init__(self, self._msn_client)
         papyon.event.OfflineMessagesEventInterface.__init__(self, self._msn_client)
 
+    def _fill_suggested_proxies(self):
+        try:
+            import libproxy
+        except ImportError:
+            return
+
+        factory = libproxy.ProxyFactory()
+        proxies = factory.getProxies('http://gateway.messenger.msn.com/')
+
+        # Remove socks proxies that papyon doesn't support.
+        proxies = [p for p in proxies if p.startswith('http://') or p == 'direct://']
+
+        if proxies:
+            self._suggested_proxies = proxies
+
+    def _use_next_proxy(self):
+        if not self._suggested_proxies:
+            return False
+
+        # Use the first one.
+        proxy = self._suggested_proxies.pop(0)
+
+        if proxy == 'direct://':
+            if 'http' in self._proxies:
+                del self._proxies['http']
+            return True
+
+        # libproxy documentation states:
+        #
+        #  * The format of the returned proxy strings are as follows:
+        #  *   - http://[username:password@]proxy:port
+        #  *   - socks://[username:password@]proxy:port
+        #  *   - direct://
+        #  etc.
+        #
+        # We've already removed every proxy other than http and
+        # direct, and have dealt with direct, so any other element
+        # will be an HTTP proxy:
+
+        proxy = proxy[len('http://'):]
+
+        # Get username and password out.
+        if '@' in proxy:
+            auth, proxy = proxy.split('@')
+            user, password = auth.split(':')
+        else:
+            user = password = None
+
+        server, port = proxy.split(':')
+
+        self._proxies['http'] = \
+            papyon.ProxyInfos(host=server, port=int(port), type='http',
+                user=user, password=password)
+
+        if user:
+            logger.info('Using proxy: http://%s:***@%s:%u' % (user, server, int(port)))
+        else:
+            logger.info('Using proxy: http://%s:%u' % (server, int(port)))
+
+        return True
+
     @property
     def manager(self):
         return self._manager
@@ -163,7 +231,8 @@
     def Disconnect(self):
         logger.info("Disconnecting")
         self.__disconnect_reason = telepathy.CONNECTION_STATUS_REASON_REQUESTED
-        self._msn_client.logout()
+        if self._msn_client.state != papyon.event.ClientState.CLOSED:
+            self._msn_client.logout()
 
     def GetInterfaces(self):
         # The self._interfaces set is only ever touched in ButterflyConnection.__init__,
@@ -307,8 +376,15 @@
     # papyon.event.ClientEventInterface
     def on_client_error(self, type, error):
         if type == papyon.event.ClientErrorType.NETWORK:
-            if self._tried_http is False:
-                logger.info("Failed to connect directly, trying HTTP")
+            # Only move onto the next proxy if we've not already tried
+            # HTTP and we're in the connecting state. We don't want to
+            # connect to HTTP if we're already connected and we lose
+            # connectivity (see fd.o#26147).
+            if self._status == telepathy.CONNECTION_STATUS_CONNECTING and \
+                    (self._tried_http is False or \
+                   (self._tried_http is True and self._use_next_proxy())):
+                logger.info("Failed to connect, trying HTTP "
+                            "(possibly again with another proxy)")
                 self._new_client(use_http=True)
                 self._msn_client.login(*self._account)
             else:
@@ -377,6 +453,8 @@
     # papyon.event.OfflineMessagesEventInterface
     def on_oim_messages_fetched(self, messages):
         for message in messages:
+            if message.sender is None:
+                continue
             # Request butterfly text channel (creation, what happen when it exist)
             sender = message.sender
             logger.info('received offline message from %s : %s' % (sender.account, message.text))
@@ -389,11 +467,22 @@
             # Notify it of the message
             channel.offline_message_received(message)
 
+    # papyon.event.InviteEventInterface
+    def on_invite_file_transfer(self, session):
+        logger.debug("File transfer invite")
+        handle = ButterflyHandleFactory(self, 'contact', session.peer.account,
+                session.peer.network_id)
+
+        props = self._generate_props(telepathy.CHANNEL_TYPE_FILE_TRANSFER,
+                handle, False)
+        channel = self._channel_manager.create_channel_for_props(props,
+                signal=True, session=session)
+
     def _advertise_disconnected(self):
         self._manager.disconnected(self)
 
 
-def build_proxy_infos(self, parameters, proxy_type='http'):
+def build_proxy_infos(parameters, proxy_type='http'):
     server_key = proxy_type + '-proxy-server'
     port_key = proxy_type + '-proxy-port'
     username_key = proxy_type + '-proxy-username'
--- butterfly/connection_manager.py
+++ butterfly/connection_manager.py
@@ -84,6 +84,7 @@
 
     def quit(self):
         "Terminates all connections. Must be called upon quit"
-        for connection in self._connections:
+        conns = self._connections[:]
+        for connection in conns:
             connection.Disconnect()
         logger.info("Connection manager quitting")
--- butterfly/contacts.py
+++ butterfly/contacts.py
@@ -66,9 +66,9 @@
                 logger.debug("Ignoring unsupported interface %s" % interface)
 
         handle_type = telepathy.HANDLE_TYPE_CONTACT
-        ret = {}
+        ret = dbus.Dictionary(signature='ua{sv}')
         for handle in handles:
-            ret[handle] = {}
+            ret[handle] = dbus.Dictionary(signature='sv')
 
         functions = {
             telepathy.CONNECTION :
--- butterfly/handle.py
+++ butterfly/handle.py
@@ -55,7 +55,7 @@
     def __new__(cls, connection, *args):
         key = (cls, connection._account[0], args)
         if key not in cls.instances.keys():
-            instance = object.__new__(cls, connection, *args)
+            instance = object.__new__(cls)
             cls.instances[key] = instance # TRICKY: instances is a weakdict
             return instance, True
         return cls.instances[key], False
--- butterfly/presence.py
+++ butterfly/presence.py
@@ -72,15 +72,15 @@
             }
 
     to_presence_type = {
-            ONLINE:     telepathy.constants.CONNECTION_PRESENCE_TYPE_AVAILABLE,
-            AWAY:       telepathy.constants.CONNECTION_PRESENCE_TYPE_AWAY,
-            BUSY:       telepathy.constants.CONNECTION_PRESENCE_TYPE_BUSY,
-            IDLE:       telepathy.constants.CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY,
-            BRB:        telepathy.constants.CONNECTION_PRESENCE_TYPE_AWAY,
-            PHONE:      telepathy.constants.CONNECTION_PRESENCE_TYPE_BUSY,
-            LUNCH:      telepathy.constants.CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY,
-            INVISIBLE:  telepathy.constants.CONNECTION_PRESENCE_TYPE_HIDDEN,
-            OFFLINE:    telepathy.constants.CONNECTION_PRESENCE_TYPE_OFFLINE
+            ONLINE:     dbus.UInt32(telepathy.constants.CONNECTION_PRESENCE_TYPE_AVAILABLE),
+            AWAY:       dbus.UInt32(telepathy.constants.CONNECTION_PRESENCE_TYPE_AWAY),
+            BUSY:       dbus.UInt32(telepathy.constants.CONNECTION_PRESENCE_TYPE_BUSY),
+            IDLE:       dbus.UInt32(telepathy.constants.CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY),
+            BRB:        dbus.UInt32(telepathy.constants.CONNECTION_PRESENCE_TYPE_AWAY),
+            PHONE:      dbus.UInt32(telepathy.constants.CONNECTION_PRESENCE_TYPE_BUSY),
+            LUNCH:      dbus.UInt32(telepathy.constants.CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY),
+            INVISIBLE:  dbus.UInt32(telepathy.constants.CONNECTION_PRESENCE_TYPE_HIDDEN),
+            OFFLINE:    dbus.UInt32(telepathy.constants.CONNECTION_PRESENCE_TYPE_OFFLINE)
             }
 
 class ButterflyPresence(telepathy.server.ConnectionInterfacePresence,
@@ -213,7 +213,7 @@
             self.msn_client.profile.presence = presence
 
     def get_simple_presences(self, contacts):
-        presences = {}
+        presences = dbus.Dictionary(signature='u(uss)')
         for handle_id in contacts:
             handle = self.handle(telepathy.HANDLE_TYPE_CONTACT, handle_id)
             try:
@@ -230,7 +230,8 @@
 
             presence_type = ButterflyPresenceMapping.to_presence_type[presence]
 
-            presences[handle] = (presence_type, presence, personal_message)
+            presences[handle] = dbus.Struct((presence_type, presence,
+                personal_message), signature='uss')
         return presences
 
     def get_statuses(self):
--- configure
+++ configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.65 for telepathy-butterfly 0.5.8.
+# Generated by GNU Autoconf 2.65 for telepathy-butterfly 0.5.12.
 #
 # Report bugs to <http://bugs.freedesktop.org/enter_bug.cgi?product=Telepathy&component=butterfly>.
 #
@@ -552,8 +552,8 @@
 # Identity of this package.
 PACKAGE_NAME='telepathy-butterfly'
 PACKAGE_TARNAME='telepathy-butterfly'
-PACKAGE_VERSION='0.5.8'
-PACKAGE_STRING='telepathy-butterfly 0.5.8'
+PACKAGE_VERSION='0.5.12'
+PACKAGE_STRING='telepathy-butterfly 0.5.12'
 PACKAGE_BUGREPORT='http://bugs.freedesktop.org/enter_bug.cgi?product=Telepathy&component=butterfly'
 PACKAGE_URL=''
 
@@ -1180,7 +1180,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures telepathy-butterfly 0.5.8 to adapt to many kinds of systems.
+\`configure' configures telepathy-butterfly 0.5.12 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1247,7 +1247,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of telepathy-butterfly 0.5.8:";;
+     short | recursive ) echo "Configuration of telepathy-butterfly 0.5.12:";;
    esac
   cat <<\_ACEOF
 
@@ -1321,7 +1321,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-telepathy-butterfly configure 0.5.8
+telepathy-butterfly configure 0.5.12
 generated by GNU Autoconf 2.65
 
 Copyright (C) 2009 Free Software Foundation, Inc.
@@ -1338,7 +1338,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by telepathy-butterfly $as_me 0.5.8, which was
+It was created by telepathy-butterfly $as_me 0.5.12, which was
 generated by GNU Autoconf 2.65.  Invocation command line was
 
   $ $0 $@
@@ -2146,7 +2146,7 @@
 
 # Define the identity of the package.
  PACKAGE='telepathy-butterfly'
- VERSION='0.5.8'
+ VERSION='0.5.12'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -2971,7 +2971,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by telepathy-butterfly $as_me 0.5.8, which was
+This file was extended by telepathy-butterfly $as_me 0.5.12, which was
 generated by GNU Autoconf 2.65.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -3024,7 +3024,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-telepathy-butterfly config.status 0.5.8
+telepathy-butterfly config.status 0.5.12
 configured by $0, generated by GNU Autoconf 2.65,
   with options \\"\$ac_cs_config\\"
 
--- configure.ac
+++ configure.ac
@@ -6,7 +6,7 @@
 dnl The telepathy-python version number (must actually be numeric at the moment)
 m4_define(telepathy_butterfly_major_version, 0)
 m4_define(telepathy_butterfly_minor_version, 5)
-m4_define(telepathy_butterfly_micro_version, 8)
+m4_define(telepathy_butterfly_micro_version, 12)
 
 m4_define(telepathy_butterfly_maybe_datestamp,
           m4_esyscmd([if test x]telepathy_butterfly_released[ != x1; then date +.%Y%m%d | tr -d '\n\r'; fi]))
--- telepathy-butterfly
+++ telepathy-butterfly
@@ -35,8 +35,8 @@
     sys.exit(1)
 
 import papyon
-if papyon.version < (0, 4, 2):
-    print >> sys.stderr, 'Critical: papyon >= 0.4.2 required. Exiting.'
+if papyon.version < (0, 4, 9):
+    print >> sys.stderr, 'Critical: papyon >= 0.4.9 required. Exiting.'
     sys.exit(1)
 
 
@@ -67,6 +67,23 @@
         manager.quit()
         mainloop.quit()
 
+    # We only want to log to stderr if BUTTERFLY_DEBUG=all is set, but
+    # we want any other logging handlers to work fine (such as the
+    # debug sender one).
+    if os.environ.get('BUTTERFLY_DEBUG', None) != 'all':
+        # This dummy stream will replace sys.stderr.
+        class DummyStream(object):
+            def write(self, s):
+                pass
+
+        # First, replace the original stderr with our new dummy stream.
+        sys.stderr = DummyStream()
+
+        # The root handler has already had the original stderr set on it,
+        # so let's override that.
+        stderr_handler = logging.root.handlers[0]
+        stderr_handler.stream = sys.stderr
+
     if 'BUTTERFLY_PERSIST' not in os.environ:
         def timeout_cb():
             if len(manager._connections) == 0:
@@ -88,6 +105,7 @@
         sys.exit(1)
 
     mainloop = gobject.MainLoop(is_running=True)
+    gobject.threads_init()
 
     while mainloop.is_running():
         try:

++++++ telepathy-butterfly.yaml (new)
--- telepathy-butterfly.yaml
+++ telepathy-butterfly.yaml
+Name: telepathy-butterfly
+Summary: MSN connection manager for Telepathy
+Version: 0.5.12
+Release: 1
+Group: Applications/Communications
+License: GPLv2+
+URL: http://telepathy.freedesktop.org/wiki/
+Sources:
+    - http://telepathy.freedesktop.org/releases/%{name}/%{name}-%{version}.tar.gz
+Description: |
+    An MSN connection manager that handles presence, personal messages,
+    and conversations
+Requires:
+    - python-telepathy >= 0.15.17
+    - papyon >= 0.4.2
+    - dbus
+    - telepathy-filesystem
+PkgConfigBR:
+    - dbus-1
+PkgBR:
+    - python-devel
+    - pkgconfig
+Configure: none
+Builder: make
+BuildArch: noarch



More information about the MeeGo-commits mailing list